1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
44 #ifdef HAVE_MACHINE_ENDIAN_H
45 #include <machine/endian.h>
50 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
51 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
52 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
59 #include "SDCCpeeph.h"
63 char *aopLiteral (value * val, int offset);
66 /* this is the down and dirty file with all kinds of
67 kludgy & hacky stuff. This is what it is all about
68 CODE GENERATION for a specific MCU . some of the
69 routines may be reusable, will have to see */
71 static char *zero = "#0x00";
72 static char *one = "#0x01";
76 {"dpl", "dph", "b", "a"};
77 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
78 char **fReturn = fReturn8051;
79 static char *accUse[] =
82 static short rbank = -1;
96 static char *rb1regs[] = {
97 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
100 extern int mcs51_ptrRegReq;
101 extern int mcs51_nRegs;
102 extern FILE *codeOutFile;
103 static void saveRBank (int, iCode *, bool);
104 #define RESULTONSTACK(x) \
105 (IC_RESULT(x) && IC_RESULT(x)->aop && \
106 IC_RESULT(x)->aop->type == AOP_STK )
108 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
109 #define CLRC emitcode("clr","c")
110 #define SETC emitcode("setb","c")
112 static lineNode *lineHead = NULL;
113 static lineNode *lineCurr = NULL;
115 static unsigned char SLMask[] =
116 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
117 0xE0, 0xC0, 0x80, 0x00};
118 static unsigned char SRMask[] =
119 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
120 0x07, 0x03, 0x01, 0x00};
127 /*-----------------------------------------------------------------*/
128 /* emitcode - writes the code into a file : for now it is simple */
129 /*-----------------------------------------------------------------*/
131 emitcode (char *inst, char *fmt,...)
134 char lb[INITIAL_INLINEASM];
142 sprintf (lb, "%s\t", inst);
144 sprintf (lb, "%s", inst);
145 vsprintf (lb + (strlen (lb)), fmt, ap);
148 vsprintf (lb, fmt, ap);
150 while (isspace (*lbp))
154 lineCurr = (lineCurr ?
155 connectLine (lineCurr, newLineNode (lb)) :
156 (lineHead = newLineNode (lb)));
157 lineCurr->isInline = _G.inLine;
158 lineCurr->isDebug = _G.debugLine;
162 /*-----------------------------------------------------------------*/
163 /* mova - moves specified value into accumulator */
164 /*-----------------------------------------------------------------*/
168 /* do some early peephole optimization */
169 if (!strcmp(x, "a") || !strcmp(x, "acc"))
172 emitcode("mov","a,%s", x);
175 /*-----------------------------------------------------------------*/
176 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
177 /*-----------------------------------------------------------------*/
179 getFreePtr (iCode * ic, asmop ** aopp, bool result)
181 bool r0iu = FALSE, r1iu = FALSE;
182 bool r0ou = FALSE, r1ou = FALSE;
184 /* the logic: if r0 & r1 used in the instruction
185 then we are in trouble otherwise */
187 /* first check if r0 & r1 are used by this
188 instruction, in which case we are in trouble */
189 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
190 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
195 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
196 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
198 /* if no usage of r0 then return it */
201 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
202 (*aopp)->type = AOP_R0;
204 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
207 /* if no usage of r1 then return it */
210 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
211 (*aopp)->type = AOP_R1;
213 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
216 /* now we know they both have usage */
217 /* if r0 not used in this instruction */
220 /* push it if not already pushed */
223 emitcode ("push", "%s",
224 mcs51_regWithIdx (R0_IDX)->dname);
228 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
229 (*aopp)->type = AOP_R0;
231 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
234 /* if r1 not used then */
238 /* push it if not already pushed */
241 emitcode ("push", "%s",
242 mcs51_regWithIdx (R1_IDX)->dname);
246 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
247 (*aopp)->type = AOP_R1;
248 return mcs51_regWithIdx (R1_IDX);
252 /* I said end of world but not quite end of world yet */
253 /* if this is a result then we can push it on the stack */
256 (*aopp)->type = AOP_STK;
260 /* other wise this is true end of the world */
261 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
262 "getFreePtr should never reach here");
266 /*-----------------------------------------------------------------*/
267 /* newAsmop - creates a new asmOp */
268 /*-----------------------------------------------------------------*/
270 newAsmop (short type)
274 aop = Safe_calloc (1, sizeof (asmop));
279 /*-----------------------------------------------------------------*/
280 /* pointerCode - returns the code for a pointer type */
281 /*-----------------------------------------------------------------*/
283 pointerCode (sym_link * etype)
286 return PTR_TYPE (SPEC_OCLS (etype));
290 /*-----------------------------------------------------------------*/
291 /* aopForSym - for a true symbol */
292 /*-----------------------------------------------------------------*/
294 aopForSym (iCode * ic, symbol * sym, bool result)
299 wassertl (ic != NULL, "Got a null iCode");
300 wassertl (sym != NULL, "Got a null symbol");
302 space = SPEC_OCLS (sym->etype);
304 /* if already has one */
308 /* assign depending on the storage class */
309 /* if it is on the stack or indirectly addressable */
310 /* space we need to assign either r0 or r1 to it */
311 if (sym->onStack || sym->iaccess)
313 sym->aop = aop = newAsmop (0);
314 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
315 aop->size = getSize (sym->type);
317 /* now assign the address of the variable to
318 the pointer register */
319 if (aop->type != AOP_STK)
325 emitcode ("push", "acc");
327 emitcode ("mov", "a,_bp");
328 emitcode ("add", "a,#0x%02x",
330 ((char) (sym->stack - _G.nRegsSaved)) :
331 ((char) sym->stack)) & 0xff);
332 emitcode ("mov", "%s,a",
333 aop->aopu.aop_ptr->name);
336 emitcode ("pop", "acc");
339 emitcode ("mov", "%s,#%s",
340 aop->aopu.aop_ptr->name,
342 aop->paged = space->paged;
345 aop->aopu.aop_stk = sym->stack;
349 /* if in bit space */
350 if (IN_BITSPACE (space))
352 sym->aop = aop = newAsmop (AOP_CRY);
353 aop->aopu.aop_dir = sym->rname;
354 aop->size = getSize (sym->type);
357 /* if it is in direct space */
358 if (IN_DIRSPACE (space))
360 sym->aop = aop = newAsmop (AOP_DIR);
361 aop->aopu.aop_dir = sym->rname;
362 aop->size = getSize (sym->type);
366 /* special case for a function */
367 if (IS_FUNC (sym->type))
369 sym->aop = aop = newAsmop (AOP_IMMD);
370 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
371 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
372 aop->size = FPTRSIZE;
376 /* only remaining is far space */
377 /* in which case DPTR gets the address */
378 sym->aop = aop = newAsmop (AOP_DPTR);
379 emitcode ("mov", "dptr,#%s", sym->rname);
380 aop->size = getSize (sym->type);
382 /* if it is in code space */
383 if (IN_CODESPACE (space))
389 /*-----------------------------------------------------------------*/
390 /* aopForRemat - rematerialzes an object */
391 /*-----------------------------------------------------------------*/
393 aopForRemat (symbol * sym)
395 iCode *ic = sym->rematiCode;
396 asmop *aop = newAsmop (AOP_IMMD);
403 val += (int) operandLitValue (IC_RIGHT (ic));
404 else if (ic->op == '-')
405 val -= (int) operandLitValue (IC_RIGHT (ic));
406 else if (IS_CAST_ICODE(ic)) {
407 sym_link *from_type = operandType(IC_RIGHT(ic));
408 aop->aopu.aop_immd.from_cast_remat = 1;
409 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
410 ptr_type = DCL_TYPE(from_type);
411 if (ptr_type == IPOINTER) {
418 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
422 sprintf (buffer, "(%s %c 0x%04x)",
423 OP_SYMBOL (IC_LEFT (ic))->rname,
424 val >= 0 ? '+' : '-',
427 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
429 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
430 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
431 /* set immd2 field if required */
432 if (aop->aopu.aop_immd.from_cast_remat) {
433 sprintf(buffer,"#0x%02x",ptr_type);
434 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
435 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
441 /*-----------------------------------------------------------------*/
442 /* regsInCommon - two operands have some registers in common */
443 /*-----------------------------------------------------------------*/
445 regsInCommon (operand * op1, operand * op2)
450 /* if they have registers in common */
451 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
454 sym1 = OP_SYMBOL (op1);
455 sym2 = OP_SYMBOL (op2);
457 if (sym1->nRegs == 0 || sym2->nRegs == 0)
460 for (i = 0; i < sym1->nRegs; i++)
466 for (j = 0; j < sym2->nRegs; j++)
471 if (sym2->regs[j] == sym1->regs[i])
479 /*-----------------------------------------------------------------*/
480 /* operandsEqu - equivalent */
481 /*-----------------------------------------------------------------*/
483 operandsEqu (operand * op1, operand * op2)
487 /* if they not symbols */
488 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
491 sym1 = OP_SYMBOL (op1);
492 sym2 = OP_SYMBOL (op2);
494 /* if both are itemps & one is spilt
495 and the other is not then false */
496 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
497 sym1->isspilt != sym2->isspilt)
500 /* if they are the same */
504 if (strcmp (sym1->rname, sym2->rname) == 0)
508 /* if left is a tmp & right is not */
509 if (IS_ITEMP (op1) &&
512 (sym1->usl.spillLoc == sym2))
515 if (IS_ITEMP (op2) &&
519 (sym2->usl.spillLoc == sym1))
525 /*-----------------------------------------------------------------*/
526 /* sameRegs - two asmops have the same registers */
527 /*-----------------------------------------------------------------*/
529 sameRegs (asmop * aop1, asmop * aop2)
536 if (aop1->type != AOP_REG ||
537 aop2->type != AOP_REG)
540 if (aop1->size != aop2->size)
543 for (i = 0; i < aop1->size; i++)
544 if (aop1->aopu.aop_reg[i] !=
545 aop2->aopu.aop_reg[i])
551 /*-----------------------------------------------------------------*/
552 /* aopOp - allocates an asmop for an operand : */
553 /*-----------------------------------------------------------------*/
555 aopOp (operand * op, iCode * ic, bool result)
564 /* if this a literal */
565 if (IS_OP_LITERAL (op))
567 op->aop = aop = newAsmop (AOP_LIT);
568 aop->aopu.aop_lit = op->operand.valOperand;
569 aop->size = getSize (operandType (op));
573 /* if already has a asmop then continue */
577 /* if the underlying symbol has a aop */
578 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
580 op->aop = OP_SYMBOL (op)->aop;
584 /* if this is a true symbol */
585 if (IS_TRUE_SYMOP (op))
587 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
591 /* this is a temporary : this has
597 e) can be a return use only */
599 sym = OP_SYMBOL (op);
601 /* if the type is a conditional */
602 if (sym->regType == REG_CND)
604 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
609 /* if it is spilt then two situations
611 b) has a spill location */
612 if (sym->isspilt || sym->nRegs == 0)
615 /* rematerialize it NOW */
618 sym->aop = op->aop = aop =
620 aop->size = getSize (sym->type);
627 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
628 aop->size = getSize (sym->type);
629 for (i = 0; i < 2; i++)
630 aop->aopu.aop_str[i] = accUse[i];
638 aop = op->aop = sym->aop = newAsmop (AOP_STR);
639 aop->size = getSize (sym->type);
640 for (i = 0; i < fReturnSizeMCS51; i++)
641 aop->aopu.aop_str[i] = fReturn[i];
645 /* else spill location */
646 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
647 /* force a new aop if sizes differ */
648 sym->usl.spillLoc->aop = NULL;
650 sym->aop = op->aop = aop =
651 aopForSym (ic, sym->usl.spillLoc, result);
652 aop->size = getSize (sym->type);
656 /* must be in a register */
657 sym->aop = op->aop = aop = newAsmop (AOP_REG);
658 aop->size = sym->nRegs;
659 for (i = 0; i < sym->nRegs; i++)
660 aop->aopu.aop_reg[i] = sym->regs[i];
663 /*-----------------------------------------------------------------*/
664 /* freeAsmop - free up the asmop given to an operand */
665 /*----------------------------------------------------------------*/
667 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
684 /* depending on the asmop type only three cases need work AOP_RO
685 , AOP_R1 && AOP_STK */
693 emitcode ("pop", "ar0");
697 bitVectUnSetBit (ic->rUsed, R0_IDX);
705 emitcode ("pop", "ar1");
709 bitVectUnSetBit (ic->rUsed, R1_IDX);
715 int stk = aop->aopu.aop_stk + aop->size;
716 bitVectUnSetBit (ic->rUsed, R0_IDX);
717 bitVectUnSetBit (ic->rUsed, R1_IDX);
719 getFreePtr (ic, &aop, FALSE);
723 emitcode ("mov", "a,_bp");
724 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
725 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
729 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
734 emitcode ("pop", "acc");
735 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
738 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
741 freeAsmop (op, NULL, ic, TRUE);
744 emitcode ("pop", "ar0");
750 emitcode ("pop", "ar1");
757 /* all other cases just dealloc */
763 OP_SYMBOL (op)->aop = NULL;
764 /* if the symbol has a spill */
766 SPIL_LOC (op)->aop = NULL;
771 /*-----------------------------------------------------------------*/
772 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
773 /* clobber the accumulator */
774 /*-----------------------------------------------------------------*/
776 aopGetUsesAcc (asmop *aop, int offset)
778 if (offset > (aop->size - 1))
796 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
805 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
809 /* Error case --- will have been caught already */
816 /*-----------------------------------------------------------------*/
817 /* aopGet - for fetching value of the aop */
818 /*-----------------------------------------------------------------*/
820 aopGet (asmop * aop, int offset, bool bit16, bool dname)
825 /* offset is greater than
827 if (offset > (aop->size - 1) &&
828 aop->type != AOP_LIT)
831 /* depending on type */
837 /* if we need to increment it */
838 while (offset > aop->coff)
840 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
844 while (offset < aop->coff)
846 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
853 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
854 return (dname ? "acc" : "a");
856 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
857 rs = Safe_calloc (1, strlen (s) + 1);
862 if (aop->code && aop->coff==0 && offset>=1) {
863 emitcode ("mov", "a,#0x%02x", offset);
864 emitcode ("movc", "a,@a+dptr");
865 return (dname ? "acc" : "a");
868 while (offset > aop->coff)
870 emitcode ("inc", "dptr");
874 while (offset < aop->coff)
876 emitcode ("lcall", "__decdptr");
883 emitcode ("clr", "a");
884 emitcode ("movc", "a,@a+dptr");
888 emitcode ("movx", "a,@dptr");
890 return (dname ? "acc" : "a");
894 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
895 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
897 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
899 sprintf (s, "#(%s >> %d)",
900 aop->aopu.aop_immd.aop_immd1,
904 aop->aopu.aop_immd.aop_immd1);
905 rs = Safe_calloc (1, strlen (s) + 1);
911 sprintf (s, "(%s + %d)",
915 sprintf (s, "%s", aop->aopu.aop_dir);
916 rs = Safe_calloc (1, strlen (s) + 1);
922 return aop->aopu.aop_reg[offset]->dname;
924 return aop->aopu.aop_reg[offset]->name;
927 emitcode ("clr", "a");
928 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
929 emitcode ("rlc", "a");
930 return (dname ? "acc" : "a");
933 if (!offset && dname)
935 return aop->aopu.aop_str[offset];
938 return aopLiteral (aop->aopu.aop_lit, offset);
942 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
946 return aop->aopu.aop_str[offset];
950 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
951 "aopget got unsupported aop->type");
954 /*-----------------------------------------------------------------*/
955 /* aopPut - puts a string for a aop */
956 /*-----------------------------------------------------------------*/
958 aopPut (asmop * aop, char *s, int offset)
962 if (aop->size && offset > (aop->size - 1))
964 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
965 "aopPut got offset > aop->size");
969 /* will assign value to value */
970 /* depending on where it is ofcourse */
975 sprintf (d, "(%s + %d)",
976 aop->aopu.aop_dir, offset);
978 sprintf (d, "%s", aop->aopu.aop_dir);
981 emitcode ("mov", "%s,%s", d, s);
986 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
987 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
990 strcmp (s, "r0") == 0 ||
991 strcmp (s, "r1") == 0 ||
992 strcmp (s, "r2") == 0 ||
993 strcmp (s, "r3") == 0 ||
994 strcmp (s, "r4") == 0 ||
995 strcmp (s, "r5") == 0 ||
996 strcmp (s, "r6") == 0 ||
997 strcmp (s, "r7") == 0)
998 emitcode ("mov", "%s,%s",
999 aop->aopu.aop_reg[offset]->dname, s);
1001 emitcode ("mov", "%s,%s",
1002 aop->aopu.aop_reg[offset]->name, s);
1009 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1010 "aopPut writting to code space");
1014 while (offset > aop->coff)
1017 emitcode ("inc", "dptr");
1020 while (offset < aop->coff)
1023 emitcode ("lcall", "__decdptr");
1028 /* if not in accumulater */
1031 emitcode ("movx", "@dptr,a");
1036 while (offset > aop->coff)
1039 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1041 while (offset < aop->coff)
1044 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1051 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1057 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1059 else if (strcmp (s, "r0") == 0 ||
1060 strcmp (s, "r1") == 0 ||
1061 strcmp (s, "r2") == 0 ||
1062 strcmp (s, "r3") == 0 ||
1063 strcmp (s, "r4") == 0 ||
1064 strcmp (s, "r5") == 0 ||
1065 strcmp (s, "r6") == 0 ||
1066 strcmp (s, "r7") == 0)
1069 sprintf (buffer, "a%s", s);
1070 emitcode ("mov", "@%s,%s",
1071 aop->aopu.aop_ptr->name, buffer);
1074 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1079 if (strcmp (s, "a") == 0)
1080 emitcode ("push", "acc");
1084 emitcode ("push", "acc");
1086 emitcode ("push", s);
1092 /* if bit variable */
1093 if (!aop->aopu.aop_dir)
1095 emitcode ("clr", "a");
1096 emitcode ("rlc", "a");
1101 emitcode ("clr", "%s", aop->aopu.aop_dir);
1103 emitcode ("setb", "%s", aop->aopu.aop_dir);
1104 else if (!strcmp (s, "c"))
1105 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1108 if (strcmp (s, "a"))
1113 /* set C, if a >= 1 */
1114 emitcode ("add", "a,#0xff");
1115 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1123 if (strcmp (aop->aopu.aop_str[offset], s))
1124 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1129 if (!offset && (strcmp (s, "acc") == 0))
1132 if (strcmp (aop->aopu.aop_str[offset], s))
1133 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1137 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1138 "aopPut got unsupported aop->type");
1146 /*-----------------------------------------------------------------*/
1147 /* pointToEnd :- points to the last byte of the operand */
1148 /*-----------------------------------------------------------------*/
1150 pointToEnd (asmop * aop)
1156 aop->coff = count = (aop->size - 1);
1162 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1166 emitcode ("inc", "dptr");
1173 /*-----------------------------------------------------------------*/
1174 /* reAdjustPreg - points a register back to where it should */
1175 /*-----------------------------------------------------------------*/
1177 reAdjustPreg (asmop * aop)
1179 if ((aop->coff==0) || aop->size <= 1)
1187 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1192 emitcode ("lcall", "__decdptr");
1199 #define AOP(op) op->aop
1200 #define AOP_TYPE(op) AOP(op)->type
1201 #define AOP_SIZE(op) AOP(op)->size
1202 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1203 AOP_TYPE(x) == AOP_R0))
1205 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1206 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1208 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1209 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1210 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1212 /*-----------------------------------------------------------------*/
1213 /* genNotFloat - generates not for float operations */
1214 /*-----------------------------------------------------------------*/
1216 genNotFloat (operand * op, operand * res)
1222 D(emitcode ("; genNotFloat",""));
1224 /* we will put 127 in the first byte of
1226 aopPut (AOP (res), "#127", 0);
1227 size = AOP_SIZE (op) - 1;
1230 l = aopGet (op->aop, offset++, FALSE, FALSE);
1235 emitcode ("orl", "a,%s",
1237 offset++, FALSE, FALSE));
1240 tlbl = newiTempLabel (NULL);
1241 aopPut (res->aop, one, 1);
1242 emitcode ("jz", "%05d$", (tlbl->key + 100));
1243 aopPut (res->aop, zero, 1);
1244 emitcode ("", "%05d$:", (tlbl->key + 100));
1246 size = res->aop->size - 2;
1248 /* put zeros in the rest */
1250 aopPut (res->aop, zero, offset++);
1253 /*-----------------------------------------------------------------*/
1254 /* opIsGptr: returns non-zero if the passed operand is */
1255 /* a generic pointer type. */
1256 /*-----------------------------------------------------------------*/
1258 opIsGptr (operand * op)
1260 sym_link *type = operandType (op);
1262 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1269 /*-----------------------------------------------------------------*/
1270 /* getDataSize - get the operand data size */
1271 /*-----------------------------------------------------------------*/
1273 getDataSize (operand * op)
1276 size = AOP_SIZE (op);
1277 if (size == GPTRSIZE)
1279 sym_link *type = operandType (op);
1280 if (IS_GENPTR (type))
1282 /* generic pointer; arithmetic operations
1283 * should ignore the high byte (pointer type).
1291 /*-----------------------------------------------------------------*/
1292 /* outAcc - output Acc */
1293 /*-----------------------------------------------------------------*/
1295 outAcc (operand * result)
1298 size = getDataSize (result);
1301 aopPut (AOP (result), "a", 0);
1304 /* unsigned or positive */
1307 aopPut (AOP (result), zero, offset++);
1312 /*-----------------------------------------------------------------*/
1313 /* outBitC - output a bit C */
1314 /*-----------------------------------------------------------------*/
1316 outBitC (operand * result)
1318 /* if the result is bit */
1319 if (AOP_TYPE (result) == AOP_CRY)
1320 aopPut (AOP (result), "c", 0);
1323 emitcode ("clr", "a");
1324 emitcode ("rlc", "a");
1329 /*-----------------------------------------------------------------*/
1330 /* toBoolean - emit code for orl a,operator(sizeop) */
1331 /*-----------------------------------------------------------------*/
1333 toBoolean (operand * oper)
1335 int size = AOP_SIZE (oper) - 1;
1337 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1339 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1343 /*-----------------------------------------------------------------*/
1344 /* genNot - generate code for ! operation */
1345 /*-----------------------------------------------------------------*/
1350 sym_link *optype = operandType (IC_LEFT (ic));
1352 D(emitcode ("; genNot",""));
1354 /* assign asmOps to operand & result */
1355 aopOp (IC_LEFT (ic), ic, FALSE);
1356 aopOp (IC_RESULT (ic), ic, TRUE);
1358 /* if in bit space then a special case */
1359 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1361 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1362 emitcode ("cpl", "c");
1363 outBitC (IC_RESULT (ic));
1367 /* if type float then do float */
1368 if (IS_FLOAT (optype))
1370 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1374 toBoolean (IC_LEFT (ic));
1376 tlbl = newiTempLabel (NULL);
1377 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1378 emitcode ("", "%05d$:", tlbl->key + 100);
1379 outBitC (IC_RESULT (ic));
1382 /* release the aops */
1383 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1384 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1388 /*-----------------------------------------------------------------*/
1389 /* genCpl - generate code for complement */
1390 /*-----------------------------------------------------------------*/
1398 D(emitcode ("; genCpl",""));
1400 /* assign asmOps to operand & result */
1401 aopOp (IC_LEFT (ic), ic, FALSE);
1402 aopOp (IC_RESULT (ic), ic, TRUE);
1404 /* special case if in bit space */
1405 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1406 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1407 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1408 emitcode ("cpl", "c");
1409 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1412 tlbl=newiTempLabel(NULL);
1413 emitcode ("cjne", "%s,#0x01,%05d$",
1414 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1415 emitcode ("", "%05d$:", tlbl->key+100);
1416 outBitC (IC_RESULT(ic));
1420 size = AOP_SIZE (IC_RESULT (ic));
1423 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1425 emitcode ("cpl", "a");
1426 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1431 /* release the aops */
1432 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1433 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1436 /*-----------------------------------------------------------------*/
1437 /* genUminusFloat - unary minus for floating points */
1438 /*-----------------------------------------------------------------*/
1440 genUminusFloat (operand * op, operand * result)
1442 int size, offset = 0;
1445 D(emitcode ("; genUminusFloat",""));
1447 /* for this we just need to flip the
1448 first it then copy the rest in place */
1449 size = AOP_SIZE (op) - 1;
1450 l = aopGet (AOP (op), 3, FALSE, FALSE);
1454 emitcode ("cpl", "acc.7");
1455 aopPut (AOP (result), "a", 3);
1459 aopPut (AOP (result),
1460 aopGet (AOP (op), offset, FALSE, FALSE),
1466 /*-----------------------------------------------------------------*/
1467 /* genUminus - unary minus code generation */
1468 /*-----------------------------------------------------------------*/
1470 genUminus (iCode * ic)
1473 sym_link *optype, *rtype;
1476 D(emitcode ("; genUminus",""));
1479 aopOp (IC_LEFT (ic), ic, FALSE);
1480 aopOp (IC_RESULT (ic), ic, TRUE);
1482 /* if both in bit space then special
1484 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1485 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1488 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1489 emitcode ("cpl", "c");
1490 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1494 optype = operandType (IC_LEFT (ic));
1495 rtype = operandType (IC_RESULT (ic));
1497 /* if float then do float stuff */
1498 if (IS_FLOAT (optype))
1500 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1504 /* otherwise subtract from zero */
1505 size = AOP_SIZE (IC_LEFT (ic));
1510 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1511 if (!strcmp (l, "a"))
1515 emitcode ("cpl", "a");
1516 emitcode ("addc", "a,#0");
1522 emitcode ("clr", "a");
1523 emitcode ("subb", "a,%s", l);
1525 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1528 /* if any remaining bytes in the result */
1529 /* we just need to propagate the sign */
1530 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1532 emitcode ("rlc", "a");
1533 emitcode ("subb", "a,acc");
1535 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1539 /* release the aops */
1540 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1541 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1544 /*-----------------------------------------------------------------*/
1545 /* saveRegisters - will look for a call and save the registers */
1546 /*-----------------------------------------------------------------*/
1548 saveRegisters (iCode * lic)
1555 for (ic = lic; ic; ic = ic->next)
1556 if (ic->op == CALL || ic->op == PCALL)
1561 fprintf (stderr, "found parameter push with no function call\n");
1565 /* if the registers have been saved already or don't need to be then
1567 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1568 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1571 /* safe the registers in use at this time but skip the
1572 ones for the result */
1573 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1574 mcs51_rUmaskForOp (IC_RESULT(ic)));
1577 if (options.useXstack)
1579 if (bitVectBitValue (rsave, R0_IDX))
1580 emitcode ("mov", "b,r0");
1581 emitcode ("mov", "r0,%s", spname);
1582 for (i = 0; i < mcs51_nRegs; i++)
1584 if (bitVectBitValue (rsave, i))
1587 emitcode ("mov", "a,b");
1589 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1590 emitcode ("movx", "@r0,a");
1591 emitcode ("inc", "r0");
1594 emitcode ("mov", "%s,r0", spname);
1595 if (bitVectBitValue (rsave, R0_IDX))
1596 emitcode ("mov", "r0,b");
1599 for (i = 0; i < mcs51_nRegs; i++)
1601 if (bitVectBitValue (rsave, i))
1602 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1606 /*-----------------------------------------------------------------*/
1607 /* unsaveRegisters - pop the pushed registers */
1608 /*-----------------------------------------------------------------*/
1610 unsaveRegisters (iCode * ic)
1615 /* restore the registers in use at this time but skip the
1616 ones for the result */
1617 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1618 mcs51_rUmaskForOp (IC_RESULT(ic)));
1620 if (options.useXstack)
1622 emitcode ("mov", "r0,%s", spname);
1623 for (i = mcs51_nRegs; i >= 0; i--)
1625 if (bitVectBitValue (rsave, i))
1627 emitcode ("dec", "r0");
1628 emitcode ("movx", "a,@r0");
1630 emitcode ("mov", "b,a");
1632 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1636 emitcode ("mov", "%s,r0", spname);
1637 if (bitVectBitValue (rsave, R0_IDX))
1638 emitcode ("mov", "r0,b");
1641 for (i = mcs51_nRegs; i >= 0; i--)
1643 if (bitVectBitValue (rsave, i))
1644 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1650 /*-----------------------------------------------------------------*/
1652 /*-----------------------------------------------------------------*/
1654 pushSide (operand * oper, int size)
1659 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1660 if (AOP_TYPE (oper) != AOP_REG &&
1661 AOP_TYPE (oper) != AOP_DIR &&
1664 emitcode ("mov", "a,%s", l);
1665 emitcode ("push", "acc");
1668 emitcode ("push", "%s", l);
1672 /*-----------------------------------------------------------------*/
1673 /* assignResultValue - */
1674 /*-----------------------------------------------------------------*/
1676 assignResultValue (operand * oper)
1679 int size = AOP_SIZE (oper);
1682 aopPut (AOP (oper), fReturn[offset], offset);
1688 /*-----------------------------------------------------------------*/
1689 /* genXpush - pushes onto the external stack */
1690 /*-----------------------------------------------------------------*/
1692 genXpush (iCode * ic)
1694 asmop *aop = newAsmop (0);
1696 int size, offset = 0;
1698 D(emitcode ("; genXpush",""));
1700 aopOp (IC_LEFT (ic), ic, FALSE);
1701 r = getFreePtr (ic, &aop, FALSE);
1704 emitcode ("mov", "%s,_spx", r->name);
1706 size = AOP_SIZE (IC_LEFT (ic));
1710 char *l = aopGet (AOP (IC_LEFT (ic)),
1711 offset++, FALSE, FALSE);
1713 emitcode ("movx", "@%s,a", r->name);
1714 emitcode ("inc", "%s", r->name);
1719 emitcode ("mov", "_spx,%s", r->name);
1721 freeAsmop (NULL, aop, ic, TRUE);
1722 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1725 /*-----------------------------------------------------------------*/
1726 /* genIpush - genrate code for pushing this gets a little complex */
1727 /*-----------------------------------------------------------------*/
1729 genIpush (iCode * ic)
1731 int size, offset = 0;
1734 D(emitcode ("; genIpush",""));
1736 /* if this is not a parm push : ie. it is spill push
1737 and spill push is always done on the local stack */
1741 /* and the item is spilt then do nothing */
1742 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1745 aopOp (IC_LEFT (ic), ic, FALSE);
1746 size = AOP_SIZE (IC_LEFT (ic));
1747 /* push it on the stack */
1750 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1756 emitcode ("push", "%s", l);
1761 /* this is a paramter push: in this case we call
1762 the routine to find the call and save those
1763 registers that need to be saved */
1766 /* if use external stack then call the external
1767 stack pushing routine */
1768 if (options.useXstack)
1774 /* then do the push */
1775 aopOp (IC_LEFT (ic), ic, FALSE);
1778 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1779 size = AOP_SIZE (IC_LEFT (ic));
1783 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1784 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1785 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1788 emitcode ("mov", "a,%s", l);
1789 emitcode ("push", "acc");
1792 emitcode ("push", "%s", l);
1795 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1798 /*-----------------------------------------------------------------*/
1799 /* genIpop - recover the registers: can happen only for spilling */
1800 /*-----------------------------------------------------------------*/
1802 genIpop (iCode * ic)
1806 D(emitcode ("; genIpop",""));
1808 /* if the temp was not pushed then */
1809 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1812 aopOp (IC_LEFT (ic), ic, FALSE);
1813 size = AOP_SIZE (IC_LEFT (ic));
1814 offset = (size - 1);
1816 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1819 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1822 /*-----------------------------------------------------------------*/
1823 /* unsaveRBank - restores the resgister bank from stack */
1824 /*-----------------------------------------------------------------*/
1826 unsaveRBank (int bank, iCode * ic, bool popPsw)
1832 if (options.useXstack)
1836 /* Assume r0 is available for use. */
1837 r = mcs51_regWithIdx (R0_IDX);;
1842 r = getFreePtr (ic, &aop, FALSE);
1844 emitcode ("mov", "%s,_spx", r->name);
1849 if (options.useXstack)
1851 emitcode ("movx", "a,@%s", r->name);
1852 emitcode ("mov", "psw,a");
1853 emitcode ("dec", "%s", r->name);
1857 emitcode ("pop", "psw");
1861 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1863 if (options.useXstack)
1865 emitcode ("movx", "a,@%s", r->name);
1866 emitcode ("mov", "(%s+%d),a",
1867 regs8051[i].base, 8 * bank + regs8051[i].offset);
1868 emitcode ("dec", "%s", r->name);
1872 emitcode ("pop", "(%s+%d)",
1873 regs8051[i].base, 8 * bank + regs8051[i].offset);
1876 if (options.useXstack)
1878 emitcode ("mov", "_spx,%s", r->name);
1883 freeAsmop (NULL, aop, ic, TRUE);
1887 /*-----------------------------------------------------------------*/
1888 /* saveRBank - saves an entire register bank on the stack */
1889 /*-----------------------------------------------------------------*/
1891 saveRBank (int bank, iCode * ic, bool pushPsw)
1897 if (options.useXstack)
1901 /* Assume r0 is available for use. */
1902 r = mcs51_regWithIdx (R0_IDX);;
1907 r = getFreePtr (ic, &aop, FALSE);
1909 emitcode ("mov", "%s,_spx", r->name);
1912 for (i = 0; i < mcs51_nRegs; i++)
1914 if (options.useXstack)
1916 emitcode ("inc", "%s", r->name);
1917 emitcode ("mov", "a,(%s+%d)",
1918 regs8051[i].base, 8 * bank + regs8051[i].offset);
1919 emitcode ("movx", "@%s,a", r->name);
1922 emitcode ("push", "(%s+%d)",
1923 regs8051[i].base, 8 * bank + regs8051[i].offset);
1928 if (options.useXstack)
1930 emitcode ("mov", "a,psw");
1931 emitcode ("movx", "@%s,a", r->name);
1932 emitcode ("inc", "%s", r->name);
1933 emitcode ("mov", "_spx,%s", r->name);
1938 emitcode ("push", "psw");
1941 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1946 freeAsmop (NULL, aop, ic, TRUE);
1955 /*-----------------------------------------------------------------*/
1956 /* genSend - gen code for SEND */
1957 /*-----------------------------------------------------------------*/
1958 static void genSend(set *sendSet)
1963 for (sic = setFirstItem (_G.sendSet); sic;
1964 sic = setNextItem (_G.sendSet)) {
1965 int size, offset = 0;
1966 aopOp (IC_LEFT (sic), sic, FALSE);
1967 size = AOP_SIZE (IC_LEFT (sic));
1969 if (sic->argreg == 1) {
1971 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1973 if (strcmp (l, fReturn[offset]))
1974 emitcode ("mov", "%s,%s", fReturn[offset], l);
1980 emitcode ("mov","b1_%d,%s",rb1_count++,
1981 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1984 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1988 /*-----------------------------------------------------------------*/
1989 /* genCall - generates a call statement */
1990 /*-----------------------------------------------------------------*/
1992 genCall (iCode * ic)
1995 // bool restoreBank = FALSE;
1996 bool swapBanks = FALSE;
1998 D(emitcode("; genCall",""));
2000 dtype = operandType (IC_LEFT (ic));
2001 /* if send set is not empty the assign */
2004 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2005 genSend(reverseSet(_G.sendSet));
2007 genSend(_G.sendSet);
2013 /* if we are calling a not _naked function that is not using
2014 the same register bank then we need to save the
2015 destination registers on the stack */
2016 dtype = operandType (IC_LEFT (ic));
2017 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2018 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2019 !IFFUNC_ISISR (dtype))
2024 /* if caller saves & we have not saved then */
2030 emitcode ("mov", "psw,#0x%02x",
2031 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2035 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2036 OP_SYMBOL (IC_LEFT (ic))->rname :
2037 OP_SYMBOL (IC_LEFT (ic))->name));
2041 emitcode ("mov", "psw,#0x%02x",
2042 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2045 /* if we need assign a result value */
2046 if ((IS_ITEMP (IC_RESULT (ic)) &&
2047 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2048 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2049 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2050 IS_TRUE_SYMOP (IC_RESULT (ic)))
2054 aopOp (IC_RESULT (ic), ic, FALSE);
2057 assignResultValue (IC_RESULT (ic));
2059 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2062 /* adjust the stack for parameters if
2067 if (ic->parmBytes > 3)
2069 emitcode ("mov", "a,%s", spname);
2070 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2071 emitcode ("mov", "%s,a", spname);
2074 for (i = 0; i < ic->parmBytes; i++)
2075 emitcode ("dec", "%s", spname);
2078 /* if we hade saved some registers then unsave them */
2079 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2080 unsaveRegisters (ic);
2082 // /* if register bank was saved then pop them */
2084 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2087 /*-----------------------------------------------------------------*/
2088 /* -10l - generates a call by pointer statement */
2089 /*-----------------------------------------------------------------*/
2091 genPcall (iCode * ic)
2094 symbol *rlbl = newiTempLabel (NULL);
2095 // bool restoreBank=FALSE;
2096 bool swapBanks = FALSE;
2098 D(emitcode("; genPCall",""));
2100 /* if caller saves & we have not saved then */
2104 /* if we are calling a not _naked function that is not using
2105 the same register bank then we need to save the
2106 destination registers on the stack */
2107 dtype = operandType (IC_LEFT (ic))->next;
2108 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2109 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2110 !IFFUNC_ISISR (dtype))
2112 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2113 // restoreBank=TRUE;
2115 // need caution message to user here
2118 /* push the return address on to the stack */
2119 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2120 emitcode ("push", "acc");
2121 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2122 emitcode ("push", "acc");
2124 /* now push the calling address */
2125 aopOp (IC_LEFT (ic), ic, FALSE);
2127 pushSide (IC_LEFT (ic), FPTRSIZE);
2129 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2131 /* if send set is not empty the assign */
2134 genSend(reverseSet(_G.sendSet));
2140 emitcode ("mov", "psw,#0x%02x",
2141 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2145 emitcode ("ret", "");
2146 emitcode ("", "%05d$:", (rlbl->key + 100));
2151 emitcode ("mov", "psw,#0x%02x",
2152 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2155 /* if we need assign a result value */
2156 if ((IS_ITEMP (IC_RESULT (ic)) &&
2157 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2158 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2159 IS_TRUE_SYMOP (IC_RESULT (ic)))
2163 aopOp (IC_RESULT (ic), ic, FALSE);
2166 assignResultValue (IC_RESULT (ic));
2168 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2171 /* adjust the stack for parameters if
2176 if (ic->parmBytes > 3)
2178 emitcode ("mov", "a,%s", spname);
2179 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2180 emitcode ("mov", "%s,a", spname);
2183 for (i = 0; i < ic->parmBytes; i++)
2184 emitcode ("dec", "%s", spname);
2188 // /* if register bank was saved then unsave them */
2190 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2192 /* if we hade saved some registers then
2194 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2195 unsaveRegisters (ic);
2198 /*-----------------------------------------------------------------*/
2199 /* resultRemat - result is rematerializable */
2200 /*-----------------------------------------------------------------*/
2202 resultRemat (iCode * ic)
2204 if (SKIP_IC (ic) || ic->op == IFX)
2207 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2209 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2210 if (sym->remat && !POINTER_SET (ic))
2217 #if defined(__BORLANDC__) || defined(_MSC_VER)
2218 #define STRCASECMP stricmp
2220 #define STRCASECMP strcasecmp
2223 /*-----------------------------------------------------------------*/
2224 /* inExcludeList - return 1 if the string is in exclude Reg list */
2225 /*-----------------------------------------------------------------*/
2227 inExcludeList (char *s)
2231 if (options.excludeRegs[i] &&
2232 STRCASECMP (options.excludeRegs[i], "none") == 0)
2235 for (i = 0; options.excludeRegs[i]; i++)
2237 if (options.excludeRegs[i] &&
2238 STRCASECMP (s, options.excludeRegs[i]) == 0)
2244 /*-----------------------------------------------------------------*/
2245 /* genFunction - generated code for function entry */
2246 /*-----------------------------------------------------------------*/
2248 genFunction (iCode * ic)
2252 bool switchedPSW = FALSE;
2253 int calleesaves_saved_register = -1;
2256 /* create the function header */
2257 emitcode (";", "-----------------------------------------");
2258 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2259 emitcode (";", "-----------------------------------------");
2261 emitcode ("", "%s:", sym->rname);
2262 ftype = operandType (IC_LEFT (ic));
2264 if (IFFUNC_ISNAKED(ftype))
2266 emitcode(";", "naked function: no prologue.");
2270 /* if critical function then turn interrupts off */
2271 if (IFFUNC_ISCRITICAL (ftype))
2272 emitcode ("clr", "ea");
2274 /* here we need to generate the equates for the
2275 register bank if required */
2276 if (FUNC_REGBANK (ftype) != rbank)
2280 rbank = FUNC_REGBANK (ftype);
2281 for (i = 0; i < mcs51_nRegs; i++)
2283 if (strcmp (regs8051[i].base, "0") == 0)
2284 emitcode ("", "%s = 0x%02x",
2286 8 * rbank + regs8051[i].offset);
2288 emitcode ("", "%s = %s + 0x%02x",
2291 8 * rbank + regs8051[i].offset);
2295 /* if this is an interrupt service routine then
2296 save acc, b, dpl, dph */
2297 if (IFFUNC_ISISR (sym->type))
2300 if (!inExcludeList ("acc"))
2301 emitcode ("push", "acc");
2302 if (!inExcludeList ("b"))
2303 emitcode ("push", "b");
2304 if (!inExcludeList ("dpl"))
2305 emitcode ("push", "dpl");
2306 if (!inExcludeList ("dph"))
2307 emitcode ("push", "dph");
2308 /* if this isr has no bank i.e. is going to
2309 run with bank 0 , then we need to save more
2311 if (!FUNC_REGBANK (sym->type))
2314 /* if this function does not call any other
2315 function then we can be economical and
2316 save only those registers that are used */
2317 if (!IFFUNC_HASFCALL(sym->type))
2321 /* if any registers used */
2324 /* save the registers used */
2325 for (i = 0; i < sym->regsUsed->size; i++)
2327 if (bitVectBitValue (sym->regsUsed, i) ||
2328 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2329 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2337 /* this function has a function call cannot
2338 determines register usage so we will have to push the
2340 saveRBank (0, ic, FALSE);
2341 if (options.parms_in_bank1) {
2343 for (i=0; i < 8 ; i++ ) {
2344 emitcode ("push","%s",rb1regs[i]);
2351 /* This ISR uses a non-zero bank.
2353 * We assume that the bank is available for our
2356 * However, if this ISR calls a function which uses some
2357 * other bank, we must save that bank entirely.
2359 unsigned long banksToSave = 0;
2361 if (IFFUNC_HASFCALL(sym->type))
2364 #define MAX_REGISTER_BANKS 4
2369 for (i = ic; i; i = i->next)
2371 if (i->op == ENDFUNCTION)
2373 /* we got to the end OK. */
2381 dtype = operandType (IC_LEFT(i));
2383 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2385 /* Mark this bank for saving. */
2386 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2388 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2392 banksToSave |= (1 << FUNC_REGBANK(dtype));
2395 /* And note that we don't need to do it in
2403 /* This is a mess; we have no idea what
2404 * register bank the called function might
2407 * The only thing I can think of to do is
2408 * throw a warning and hope.
2410 werror(W_FUNCPTR_IN_USING_ISR);
2414 if (banksToSave && options.useXstack)
2416 /* Since we aren't passing it an ic,
2417 * saveRBank will assume r0 is available to abuse.
2419 * So switch to our (trashable) bank now, so
2420 * the caller's R0 isn't trashed.
2422 emitcode ("push", "psw");
2423 emitcode ("mov", "psw,#0x%02x",
2424 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2428 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2430 if (banksToSave & (1 << ix))
2432 saveRBank(ix, NULL, FALSE);
2436 // jwk: this needs a closer look
2437 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2442 /* if callee-save to be used for this function
2443 then save the registers being used in this function */
2444 if (IFFUNC_CALLEESAVES(sym->type))
2448 /* if any registers used */
2451 /* save the registers used */
2452 for (i = 0; i < sym->regsUsed->size; i++)
2454 if (bitVectBitValue (sym->regsUsed, i) ||
2455 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2457 /* remember one saved register for later usage */
2458 if (calleesaves_saved_register < 0)
2459 calleesaves_saved_register = i;
2460 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2468 /* set the register bank to the desired value */
2469 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2472 emitcode ("push", "psw");
2473 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2476 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2479 if (options.useXstack)
2481 emitcode ("mov", "r0,%s", spname);
2482 emitcode ("mov", "a,_bp");
2483 emitcode ("movx", "@r0,a");
2484 emitcode ("inc", "%s", spname);
2488 /* set up the stack */
2489 emitcode ("push", "_bp"); /* save the callers stack */
2491 emitcode ("mov", "_bp,%s", spname);
2494 /* adjust the stack for the function */
2500 werror (W_STACK_OVERFLOW, sym->name);
2502 if (i > 3 && sym->recvSize < 4)
2505 emitcode ("mov", "a,sp");
2506 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2507 emitcode ("mov", "sp,a");
2512 if (IFFUNC_CALLEESAVES(sym->type))
2514 /* if it's a callee-saves function we need a saved register */
2515 if (calleesaves_saved_register >= 0)
2517 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2518 emitcode ("mov", "a,sp");
2519 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2520 emitcode ("mov", "sp,a");
2521 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2524 /* do it the hard way */
2526 emitcode ("inc", "sp");
2530 /* not callee-saves, we can clobber r0 */
2531 emitcode ("mov", "r0,a");
2532 emitcode ("mov", "a,sp");
2533 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2534 emitcode ("mov", "sp,a");
2535 emitcode ("mov", "a,r0");
2540 emitcode ("inc", "sp");
2546 emitcode ("mov", "a,_spx");
2547 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2548 emitcode ("mov", "_spx,a");
2553 /*-----------------------------------------------------------------*/
2554 /* genEndFunction - generates epilogue for functions */
2555 /*-----------------------------------------------------------------*/
2557 genEndFunction (iCode * ic)
2559 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2561 if (IFFUNC_ISNAKED(sym->type))
2563 emitcode(";", "naked function: no epilogue.");
2567 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2569 emitcode ("mov", "%s,_bp", spname);
2572 /* if use external stack but some variables were
2573 added to the local stack then decrement the
2575 if (options.useXstack && sym->stack)
2577 emitcode ("mov", "a,sp");
2578 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2579 emitcode ("mov", "sp,a");
2583 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2585 if (options.useXstack)
2587 emitcode ("mov", "r0,%s", spname);
2588 emitcode ("movx", "a,@r0");
2589 emitcode ("mov", "_bp,a");
2590 emitcode ("dec", "%s", spname);
2594 emitcode ("pop", "_bp");
2598 /* restore the register bank */
2599 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2601 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2602 || !options.useXstack)
2604 /* Special case of ISR using non-zero bank with useXstack
2607 emitcode ("pop", "psw");
2611 if (IFFUNC_ISISR (sym->type))
2614 /* now we need to restore the registers */
2615 /* if this isr has no bank i.e. is going to
2616 run with bank 0 , then we need to save more
2618 if (!FUNC_REGBANK (sym->type))
2620 /* if this function does not call any other
2621 function then we can be economical and
2622 save only those registers that are used */
2623 if (!IFFUNC_HASFCALL(sym->type))
2627 /* if any registers used */
2630 /* save the registers used */
2631 for (i = sym->regsUsed->size; i >= 0; i--)
2633 if (bitVectBitValue (sym->regsUsed, i) ||
2634 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2635 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2642 if (options.parms_in_bank1) {
2644 for (i = 7 ; i >= 0 ; i-- ) {
2645 emitcode ("pop","%s",rb1regs[i]);
2648 /* this function has a function call cannot
2649 determines register usage so we will have to pop the
2651 unsaveRBank (0, ic, FALSE);
2656 /* This ISR uses a non-zero bank.
2658 * Restore any register banks saved by genFunction
2661 // jwk: this needs a closer look
2662 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2665 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2667 if (savedBanks & (1 << ix))
2669 unsaveRBank(ix, NULL, FALSE);
2673 if (options.useXstack)
2675 /* Restore bank AFTER calling unsaveRBank,
2676 * since it can trash r0.
2678 emitcode ("pop", "psw");
2682 if (!inExcludeList ("dph"))
2683 emitcode ("pop", "dph");
2684 if (!inExcludeList ("dpl"))
2685 emitcode ("pop", "dpl");
2686 if (!inExcludeList ("b"))
2687 emitcode ("pop", "b");
2688 if (!inExcludeList ("acc"))
2689 emitcode ("pop", "acc");
2691 if (IFFUNC_ISCRITICAL (sym->type))
2692 emitcode ("setb", "ea");
2694 /* if debug then send end of function */
2695 if (options.debug && currFunc)
2698 emitcode ("", "C$%s$%d$%d$%d ==.",
2699 FileBaseName (ic->filename), currFunc->lastLine,
2700 ic->level, ic->block);
2701 if (IS_STATIC (currFunc->etype))
2702 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2704 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2708 emitcode ("reti", "");
2712 if (IFFUNC_ISCRITICAL (sym->type))
2713 emitcode ("setb", "ea");
2715 if (IFFUNC_CALLEESAVES(sym->type))
2719 /* if any registers used */
2722 /* save the registers used */
2723 for (i = sym->regsUsed->size; i >= 0; i--)
2725 if (bitVectBitValue (sym->regsUsed, i) ||
2726 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2727 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2733 /* if debug then send end of function */
2734 if (options.debug && currFunc)
2737 emitcode ("", "C$%s$%d$%d$%d ==.",
2738 FileBaseName (ic->filename), currFunc->lastLine,
2739 ic->level, ic->block);
2740 if (IS_STATIC (currFunc->etype))
2741 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2743 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2747 emitcode ("ret", "");
2752 /*-----------------------------------------------------------------*/
2753 /* genRet - generate code for return statement */
2754 /*-----------------------------------------------------------------*/
2758 int size, offset = 0, pushed = 0;
2760 D(emitcode ("; genRet",""));
2762 /* if we have no return value then
2763 just generate the "ret" */
2767 /* we have something to return then
2768 move the return value into place */
2769 aopOp (IC_LEFT (ic), ic, FALSE);
2770 size = AOP_SIZE (IC_LEFT (ic));
2775 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2778 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2780 emitcode ("push", "%s", l);
2785 l = aopGet (AOP (IC_LEFT (ic)), offset,
2787 if (strcmp (fReturn[offset], l))
2788 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2797 if (strcmp (fReturn[pushed], "a"))
2798 emitcode ("pop", fReturn[pushed]);
2800 emitcode ("pop", "acc");
2803 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2806 /* generate a jump to the return label
2807 if the next is not the return statement */
2808 if (!(ic->next && ic->next->op == LABEL &&
2809 IC_LABEL (ic->next) == returnLabel))
2811 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2815 /*-----------------------------------------------------------------*/
2816 /* genLabel - generates a label */
2817 /*-----------------------------------------------------------------*/
2819 genLabel (iCode * ic)
2821 /* special case never generate */
2822 if (IC_LABEL (ic) == entryLabel)
2825 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2828 /*-----------------------------------------------------------------*/
2829 /* genGoto - generates a ljmp */
2830 /*-----------------------------------------------------------------*/
2832 genGoto (iCode * ic)
2834 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2837 /*-----------------------------------------------------------------*/
2838 /* findLabelBackwards: walks back through the iCode chain looking */
2839 /* for the given label. Returns number of iCode instructions */
2840 /* between that label and given ic. */
2841 /* Returns zero if label not found. */
2842 /*-----------------------------------------------------------------*/
2844 findLabelBackwards (iCode * ic, int key)
2853 /* If we have any pushes or pops, we cannot predict the distance.
2854 I don't like this at all, this should be dealt with in the
2856 if (ic->op == IPUSH || ic->op == IPOP) {
2860 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2869 /*-----------------------------------------------------------------*/
2870 /* genPlusIncr :- does addition with increment if possible */
2871 /*-----------------------------------------------------------------*/
2873 genPlusIncr (iCode * ic)
2875 unsigned int icount;
2876 unsigned int size = getDataSize (IC_RESULT (ic));
2878 /* will try to generate an increment */
2879 /* if the right side is not a literal
2881 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2884 /* if the literal value of the right hand side
2885 is greater than 4 then it is not worth it */
2886 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2889 D(emitcode ("; genPlusIncr",""));
2891 /* if increment 16 bits in register */
2892 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2893 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2901 /* If the next instruction is a goto and the goto target
2902 * is < 10 instructions previous to this, we can generate
2903 * jumps straight to that target.
2905 if (ic->next && ic->next->op == GOTO
2906 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2907 && labelRange <= 10)
2909 emitcode (";", "tail increment optimized");
2910 tlbl = IC_LABEL (ic->next);
2915 tlbl = newiTempLabel (NULL);
2918 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2919 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2920 IS_AOP_PREG (IC_RESULT (ic)))
2921 emitcode ("cjne", "%s,#0x00,%05d$",
2922 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2926 emitcode ("clr", "a");
2927 emitcode ("cjne", "a,%s,%05d$",
2928 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2932 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2935 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2936 IS_AOP_PREG (IC_RESULT (ic)))
2937 emitcode ("cjne", "%s,#0x00,%05d$",
2938 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2941 emitcode ("cjne", "a,%s,%05d$",
2942 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2945 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2949 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2950 IS_AOP_PREG (IC_RESULT (ic)))
2951 emitcode ("cjne", "%s,#0x00,%05d$",
2952 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2956 emitcode ("cjne", "a,%s,%05d$",
2957 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2960 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2965 emitcode ("", "%05d$:", tlbl->key + 100);
2970 /* if the sizes are greater than 1 then we cannot */
2971 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2972 AOP_SIZE (IC_LEFT (ic)) > 1)
2975 /* we can if the aops of the left & result match or
2976 if they are in registers and the registers are the
2978 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2983 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2984 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2985 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2991 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3000 /*-----------------------------------------------------------------*/
3001 /* outBitAcc - output a bit in acc */
3002 /*-----------------------------------------------------------------*/
3004 outBitAcc (operand * result)
3006 symbol *tlbl = newiTempLabel (NULL);
3007 /* if the result is a bit */
3008 if (AOP_TYPE (result) == AOP_CRY)
3010 aopPut (AOP (result), "a", 0);
3014 emitcode ("jz", "%05d$", tlbl->key + 100);
3015 emitcode ("mov", "a,%s", one);
3016 emitcode ("", "%05d$:", tlbl->key + 100);
3021 /*-----------------------------------------------------------------*/
3022 /* genPlusBits - generates code for addition of two bits */
3023 /*-----------------------------------------------------------------*/
3025 genPlusBits (iCode * ic)
3027 D(emitcode ("; genPlusBits",""));
3029 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3031 symbol *lbl = newiTempLabel (NULL);
3032 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3033 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3034 emitcode ("cpl", "c");
3035 emitcode ("", "%05d$:", (lbl->key + 100));
3036 outBitC (IC_RESULT (ic));
3040 emitcode ("clr", "a");
3041 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3042 emitcode ("rlc", "a");
3043 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3044 emitcode ("addc", "a,#0x00");
3045 outAcc (IC_RESULT (ic));
3050 /* This is the original version of this code.
3052 * This is being kept around for reference,
3053 * because I am not entirely sure I got it right...
3056 adjustArithmeticResult (iCode * ic)
3058 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3059 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3060 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3061 aopPut (AOP (IC_RESULT (ic)),
3062 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3065 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3066 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3067 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3068 aopPut (AOP (IC_RESULT (ic)),
3069 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3072 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3073 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3074 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3075 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3076 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3079 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3080 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3084 /* This is the pure and virtuous version of this code.
3085 * I'm pretty certain it's right, but not enough to toss the old
3089 adjustArithmeticResult (iCode * ic)
3091 if (opIsGptr (IC_RESULT (ic)) &&
3092 opIsGptr (IC_LEFT (ic)) &&
3093 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3095 aopPut (AOP (IC_RESULT (ic)),
3096 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3100 if (opIsGptr (IC_RESULT (ic)) &&
3101 opIsGptr (IC_RIGHT (ic)) &&
3102 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3104 aopPut (AOP (IC_RESULT (ic)),
3105 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3109 if (opIsGptr (IC_RESULT (ic)) &&
3110 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3111 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3112 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3113 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3116 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3117 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3122 /*-----------------------------------------------------------------*/
3123 /* genPlus - generates code for addition */
3124 /*-----------------------------------------------------------------*/
3126 genPlus (iCode * ic)
3128 int size, offset = 0;
3130 asmop *leftOp, *rightOp;
3132 /* special cases :- */
3134 D(emitcode ("; genPlus",""));
3136 aopOp (IC_LEFT (ic), ic, FALSE);
3137 aopOp (IC_RIGHT (ic), ic, FALSE);
3138 aopOp (IC_RESULT (ic), ic, TRUE);
3140 /* if literal, literal on the right or
3141 if left requires ACC or right is already
3143 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3144 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3145 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3147 operand *t = IC_RIGHT (ic);
3148 IC_RIGHT (ic) = IC_LEFT (ic);
3152 /* if both left & right are in bit
3154 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3155 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3161 /* if left in bit space & right literal */
3162 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3163 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3165 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3166 /* if result in bit space */
3167 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3169 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3170 emitcode ("cpl", "c");
3171 outBitC (IC_RESULT (ic));
3175 size = getDataSize (IC_RESULT (ic));
3178 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3179 emitcode ("addc", "a,#00");
3180 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3186 /* if I can do an increment instead
3187 of add then GOOD for ME */
3188 if (genPlusIncr (ic) == TRUE)
3191 size = getDataSize (IC_RESULT (ic));
3193 leftOp = AOP(IC_LEFT(ic));
3194 rightOp = AOP(IC_RIGHT(ic));
3199 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3201 emitcode("mov", "b,a");
3202 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3203 emitcode("xch", "a,b");
3204 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3205 emitcode (add, "a,b");
3207 else if (aopGetUsesAcc (leftOp, offset))
3209 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3210 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3214 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3215 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3217 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3218 add = "addc"; /* further adds must propagate carry */
3221 adjustArithmeticResult (ic);
3224 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3225 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3226 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3229 /*-----------------------------------------------------------------*/
3230 /* genMinusDec :- does subtraction with deccrement if possible */
3231 /*-----------------------------------------------------------------*/
3233 genMinusDec (iCode * ic)
3235 unsigned int icount;
3236 unsigned int size = getDataSize (IC_RESULT (ic));
3238 /* will try to generate an increment */
3239 /* if the right side is not a literal
3241 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3244 /* if the literal value of the right hand side
3245 is greater than 4 then it is not worth it */
3246 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3249 D(emitcode ("; genMinusDec",""));
3251 /* if decrement 16 bits in register */
3252 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3253 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3261 /* If the next instruction is a goto and the goto target
3262 * is <= 10 instructions previous to this, we can generate
3263 * jumps straight to that target.
3265 if (ic->next && ic->next->op == GOTO
3266 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3267 && labelRange <= 10)
3269 emitcode (";", "tail decrement optimized");
3270 tlbl = IC_LABEL (ic->next);
3275 tlbl = newiTempLabel (NULL);
3279 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3280 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3281 IS_AOP_PREG (IC_RESULT (ic)))
3282 emitcode ("cjne", "%s,#0xff,%05d$"
3283 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3287 emitcode ("mov", "a,#0xff");
3288 emitcode ("cjne", "a,%s,%05d$"
3289 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3292 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3295 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3296 IS_AOP_PREG (IC_RESULT (ic)))
3297 emitcode ("cjne", "%s,#0xff,%05d$"
3298 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3302 emitcode ("cjne", "a,%s,%05d$"
3303 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3306 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3310 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3311 IS_AOP_PREG (IC_RESULT (ic)))
3312 emitcode ("cjne", "%s,#0xff,%05d$"
3313 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3317 emitcode ("cjne", "a,%s,%05d$"
3318 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3321 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3325 emitcode ("", "%05d$:", tlbl->key + 100);
3330 /* if the sizes are greater than 1 then we cannot */
3331 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3332 AOP_SIZE (IC_LEFT (ic)) > 1)
3335 /* we can if the aops of the left & result match or
3336 if they are in registers and the registers are the
3338 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3342 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3350 /*-----------------------------------------------------------------*/
3351 /* addSign - complete with sign */
3352 /*-----------------------------------------------------------------*/
3354 addSign (operand * result, int offset, int sign)
3356 int size = (getDataSize (result) - offset);
3361 emitcode ("rlc", "a");
3362 emitcode ("subb", "a,acc");
3364 aopPut (AOP (result), "a", offset++);
3368 aopPut (AOP (result), zero, offset++);
3372 /*-----------------------------------------------------------------*/
3373 /* genMinusBits - generates code for subtraction of two bits */
3374 /*-----------------------------------------------------------------*/
3376 genMinusBits (iCode * ic)
3378 symbol *lbl = newiTempLabel (NULL);
3380 D(emitcode ("; genMinusBits",""));
3382 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3384 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3385 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3386 emitcode ("cpl", "c");
3387 emitcode ("", "%05d$:", (lbl->key + 100));
3388 outBitC (IC_RESULT (ic));
3392 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3393 emitcode ("subb", "a,acc");
3394 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3395 emitcode ("inc", "a");
3396 emitcode ("", "%05d$:", (lbl->key + 100));
3397 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3398 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3402 /*-----------------------------------------------------------------*/
3403 /* genMinus - generates code for subtraction */
3404 /*-----------------------------------------------------------------*/
3406 genMinus (iCode * ic)
3408 int size, offset = 0;
3410 D(emitcode ("; genMinus",""));
3412 aopOp (IC_LEFT (ic), ic, FALSE);
3413 aopOp (IC_RIGHT (ic), ic, FALSE);
3414 aopOp (IC_RESULT (ic), ic, TRUE);
3416 /* special cases :- */
3417 /* if both left & right are in bit space */
3418 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3419 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3425 /* if I can do an decrement instead
3426 of subtract then GOOD for ME */
3427 if (genMinusDec (ic) == TRUE)
3430 size = getDataSize (IC_RESULT (ic));
3432 /* if literal, add a,#-lit, else normal subb */
3433 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3435 unsigned long lit = 0L;
3437 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3442 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3443 /* first add without previous c */
3445 if (!size && lit==-1) {
3446 emitcode ("dec", "a");
3448 emitcode ("add", "a,#0x%02x",
3449 (unsigned int) (lit & 0x0FFL));
3452 emitcode ("addc", "a,#0x%02x",
3453 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3455 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3460 asmop *leftOp, *rightOp;
3462 leftOp = AOP(IC_LEFT(ic));
3463 rightOp = AOP(IC_RIGHT(ic));
3467 if (aopGetUsesAcc(rightOp, offset)) {
3468 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3469 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3471 emitcode( "cpl", "c");
3473 emitcode( "setb", "c");
3475 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3476 emitcode("cpl", "a");
3478 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3481 emitcode ("subb", "a,%s",
3482 aopGet(rightOp, offset, FALSE, TRUE));
3485 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3490 adjustArithmeticResult (ic);
3493 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3494 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3495 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3499 /*-----------------------------------------------------------------*/
3500 /* genMultbits :- multiplication of bits */
3501 /*-----------------------------------------------------------------*/
3503 genMultbits (operand * left,
3507 D(emitcode ("; genMultbits",""));
3509 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3510 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3515 /*-----------------------------------------------------------------*/
3516 /* genMultOneByte : 8*8=8/16 bit multiplication */
3517 /*-----------------------------------------------------------------*/
3519 genMultOneByte (operand * left,
3523 sym_link *opetype = operandType (result);
3525 int size=AOP_SIZE(result);
3527 D(emitcode ("; genMultOneByte",""));
3529 if (size<1 || size>2) {
3530 // this should never happen
3531 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3532 AOP_SIZE(result), __FILE__, lineno);
3536 /* (if two literals: the value is computed before) */
3537 /* if one literal, literal on the right */
3538 if (AOP_TYPE (left) == AOP_LIT)
3543 //emitcode (";", "swapped left and right");
3546 if (SPEC_USIGN(opetype)
3547 // ignore the sign of left and right, what else can we do?
3548 || (SPEC_USIGN(operandType(left)) &&
3549 SPEC_USIGN(operandType(right)))) {
3550 // just an unsigned 8*8=8/16 multiply
3551 //emitcode (";","unsigned");
3552 // TODO: check for accumulator clash between left & right aops?
3553 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3554 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3555 emitcode ("mul", "ab");
3556 aopPut (AOP (result), "a", 0);
3558 aopPut (AOP (result), "b", 1);
3563 // we have to do a signed multiply
3565 //emitcode (";", "signed");
3566 emitcode ("clr", "F0"); // reset sign flag
3567 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3569 lbl=newiTempLabel(NULL);
3570 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3571 // left side is negative, 8-bit two's complement, this fails for -128
3572 emitcode ("setb", "F0"); // set sign flag
3573 emitcode ("cpl", "a");
3574 emitcode ("inc", "a");
3576 emitcode ("", "%05d$:", lbl->key+100);
3579 if (AOP_TYPE(right)==AOP_LIT) {
3580 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3581 /* AND literal negative */
3583 emitcode ("cpl", "F0"); // complement sign flag
3584 emitcode ("mov", "b,#0x%02x", -val);
3586 emitcode ("mov", "b,#0x%02x", val);
3589 lbl=newiTempLabel(NULL);
3590 emitcode ("mov", "b,a");
3591 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3592 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3593 // right side is negative, 8-bit two's complement
3594 emitcode ("cpl", "F0"); // complement sign flag
3595 emitcode ("cpl", "a");
3596 emitcode ("inc", "a");
3597 emitcode ("", "%05d$:", lbl->key+100);
3599 emitcode ("mul", "ab");
3601 lbl=newiTempLabel(NULL);
3602 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3603 // only ONE op was negative, we have to do a 8/16-bit two's complement
3604 emitcode ("cpl", "a"); // lsb
3606 emitcode ("inc", "a");
3608 emitcode ("add", "a,#1");
3609 emitcode ("xch", "a,b");
3610 emitcode ("cpl", "a"); // msb
3611 emitcode ("addc", "a,#0");
3612 emitcode ("xch", "a,b");
3615 emitcode ("", "%05d$:", lbl->key+100);
3616 aopPut (AOP (result), "a", 0);
3618 aopPut (AOP (result), "b", 1);
3622 /*-----------------------------------------------------------------*/
3623 /* genMult - generates code for multiplication */
3624 /*-----------------------------------------------------------------*/
3626 genMult (iCode * ic)
3628 operand *left = IC_LEFT (ic);
3629 operand *right = IC_RIGHT (ic);
3630 operand *result = IC_RESULT (ic);
3632 D(emitcode ("; genMult",""));
3634 /* assign the amsops */
3635 aopOp (left, ic, FALSE);
3636 aopOp (right, ic, FALSE);
3637 aopOp (result, ic, TRUE);
3639 /* special cases first */
3641 if (AOP_TYPE (left) == AOP_CRY &&
3642 AOP_TYPE (right) == AOP_CRY)
3644 genMultbits (left, right, result);
3648 /* if both are of size == 1 */
3649 #if 0 // one of them can be a sloc shared with the result
3650 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3652 if (getSize(operandType(left)) == 1 &&
3653 getSize(operandType(right)) == 1)
3656 genMultOneByte (left, right, result);
3660 /* should have been converted to function call */
3661 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3662 getSize(OP_SYMBOL(right)->type));
3666 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3667 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3668 freeAsmop (result, NULL, ic, TRUE);
3671 /*-----------------------------------------------------------------*/
3672 /* genDivbits :- division of bits */
3673 /*-----------------------------------------------------------------*/
3675 genDivbits (operand * left,
3682 D(emitcode ("; genDivbits",""));
3684 /* the result must be bit */
3685 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3686 l = aopGet (AOP (left), 0, FALSE, FALSE);
3690 emitcode ("div", "ab");
3691 emitcode ("rrc", "a");
3692 aopPut (AOP (result), "c", 0);
3695 /*-----------------------------------------------------------------*/
3696 /* genDivOneByte : 8 bit division */
3697 /*-----------------------------------------------------------------*/
3699 genDivOneByte (operand * left,
3703 sym_link *opetype = operandType (result);
3708 D(emitcode ("; genDivOneByte",""));
3710 size = AOP_SIZE (result) - 1;
3712 /* signed or unsigned */
3713 if (SPEC_USIGN (opetype))
3715 /* unsigned is easy */
3716 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3717 l = aopGet (AOP (left), 0, FALSE, FALSE);
3719 emitcode ("div", "ab");
3720 aopPut (AOP (result), "a", 0);
3722 aopPut (AOP (result), zero, offset++);
3726 /* signed is a little bit more difficult */
3728 /* save the signs of the operands */
3729 l = aopGet (AOP (left), 0, FALSE, FALSE);
3731 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3732 emitcode ("push", "acc"); /* save it on the stack */
3734 /* now sign adjust for both left & right */
3735 l = aopGet (AOP (right), 0, FALSE, FALSE);
3737 lbl = newiTempLabel (NULL);
3738 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3739 emitcode ("cpl", "a");
3740 emitcode ("inc", "a");
3741 emitcode ("", "%05d$:", (lbl->key + 100));
3742 emitcode ("mov", "b,a");
3744 /* sign adjust left side */
3745 l = aopGet (AOP (left), 0, FALSE, FALSE);
3748 lbl = newiTempLabel (NULL);
3749 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3750 emitcode ("cpl", "a");
3751 emitcode ("inc", "a");
3752 emitcode ("", "%05d$:", (lbl->key + 100));
3754 /* now the division */
3755 emitcode ("div", "ab");
3756 /* we are interested in the lower order
3758 emitcode ("mov", "b,a");
3759 lbl = newiTempLabel (NULL);
3760 emitcode ("pop", "acc");
3761 /* if there was an over flow we don't
3762 adjust the sign of the result */
3763 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3764 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3766 emitcode ("clr", "a");
3767 emitcode ("subb", "a,b");
3768 emitcode ("mov", "b,a");
3769 emitcode ("", "%05d$:", (lbl->key + 100));
3771 /* now we are done */
3772 aopPut (AOP (result), "b", 0);
3775 emitcode ("mov", "c,b.7");
3776 emitcode ("subb", "a,acc");
3779 aopPut (AOP (result), "a", offset++);
3783 /*-----------------------------------------------------------------*/
3784 /* genDiv - generates code for division */
3785 /*-----------------------------------------------------------------*/
3789 operand *left = IC_LEFT (ic);
3790 operand *right = IC_RIGHT (ic);
3791 operand *result = IC_RESULT (ic);
3793 D(emitcode ("; genDiv",""));
3795 /* assign the amsops */
3796 aopOp (left, ic, FALSE);
3797 aopOp (right, ic, FALSE);
3798 aopOp (result, ic, TRUE);
3800 /* special cases first */
3802 if (AOP_TYPE (left) == AOP_CRY &&
3803 AOP_TYPE (right) == AOP_CRY)
3805 genDivbits (left, right, result);
3809 /* if both are of size == 1 */
3810 if (AOP_SIZE (left) == 1 &&
3811 AOP_SIZE (right) == 1)
3813 genDivOneByte (left, right, result);
3817 /* should have been converted to function call */
3820 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3821 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3822 freeAsmop (result, NULL, ic, TRUE);
3825 /*-----------------------------------------------------------------*/
3826 /* genModbits :- modulus of bits */
3827 /*-----------------------------------------------------------------*/
3829 genModbits (operand * left,
3836 D(emitcode ("; genModbits",""));
3838 /* the result must be bit */
3839 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3840 l = aopGet (AOP (left), 0, FALSE, FALSE);
3844 emitcode ("div", "ab");
3845 emitcode ("mov", "a,b");
3846 emitcode ("rrc", "a");
3847 aopPut (AOP (result), "c", 0);
3850 /*-----------------------------------------------------------------*/
3851 /* genModOneByte : 8 bit modulus */
3852 /*-----------------------------------------------------------------*/
3854 genModOneByte (operand * left,
3858 sym_link *opetype = operandType (result);
3862 D(emitcode ("; genModOneByte",""));
3864 /* signed or unsigned */
3865 if (SPEC_USIGN (opetype))
3867 /* unsigned is easy */
3868 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3869 l = aopGet (AOP (left), 0, FALSE, FALSE);
3871 emitcode ("div", "ab");
3872 aopPut (AOP (result), "b", 0);
3876 /* signed is a little bit more difficult */
3878 /* save the signs of the operands */
3879 l = aopGet (AOP (left), 0, FALSE, FALSE);
3882 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3883 emitcode ("push", "acc"); /* save it on the stack */
3885 /* now sign adjust for both left & right */
3886 l = aopGet (AOP (right), 0, FALSE, FALSE);
3889 lbl = newiTempLabel (NULL);
3890 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3891 emitcode ("cpl", "a");
3892 emitcode ("inc", "a");
3893 emitcode ("", "%05d$:", (lbl->key + 100));
3894 emitcode ("mov", "b,a");
3896 /* sign adjust left side */
3897 l = aopGet (AOP (left), 0, FALSE, FALSE);
3900 lbl = newiTempLabel (NULL);
3901 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3902 emitcode ("cpl", "a");
3903 emitcode ("inc", "a");
3904 emitcode ("", "%05d$:", (lbl->key + 100));
3906 /* now the multiplication */
3907 emitcode ("div", "ab");
3908 /* we are interested in the lower order
3910 lbl = newiTempLabel (NULL);
3911 emitcode ("pop", "acc");
3912 /* if there was an over flow we don't
3913 adjust the sign of the result */
3914 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3915 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3917 emitcode ("clr", "a");
3918 emitcode ("subb", "a,b");
3919 emitcode ("mov", "b,a");
3920 emitcode ("", "%05d$:", (lbl->key + 100));
3922 /* now we are done */
3923 aopPut (AOP (result), "b", 0);
3927 /*-----------------------------------------------------------------*/
3928 /* genMod - generates code for division */
3929 /*-----------------------------------------------------------------*/
3933 operand *left = IC_LEFT (ic);
3934 operand *right = IC_RIGHT (ic);
3935 operand *result = IC_RESULT (ic);
3937 D(emitcode ("; genMod",""));
3939 /* assign the amsops */
3940 aopOp (left, ic, FALSE);
3941 aopOp (right, ic, FALSE);
3942 aopOp (result, ic, TRUE);
3944 /* special cases first */
3946 if (AOP_TYPE (left) == AOP_CRY &&
3947 AOP_TYPE (right) == AOP_CRY)
3949 genModbits (left, right, result);
3953 /* if both are of size == 1 */
3954 if (AOP_SIZE (left) == 1 &&
3955 AOP_SIZE (right) == 1)
3957 genModOneByte (left, right, result);
3961 /* should have been converted to function call */
3965 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3966 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3967 freeAsmop (result, NULL, ic, TRUE);
3970 /*-----------------------------------------------------------------*/
3971 /* genIfxJump :- will create a jump depending on the ifx */
3972 /*-----------------------------------------------------------------*/
3974 genIfxJump (iCode * ic, char *jval)
3977 symbol *tlbl = newiTempLabel (NULL);
3980 D(emitcode ("; genIfxJump",""));
3982 /* if true label then we jump if condition
3986 jlbl = IC_TRUE (ic);
3987 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3988 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3992 /* false label is present */
3993 jlbl = IC_FALSE (ic);
3994 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3995 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3997 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3998 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4000 emitcode (inst, "%05d$", tlbl->key + 100);
4001 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4002 emitcode ("", "%05d$:", tlbl->key + 100);
4004 /* mark the icode as generated */
4008 /*-----------------------------------------------------------------*/
4009 /* genCmp :- greater or less than comparison */
4010 /*-----------------------------------------------------------------*/
4012 genCmp (operand * left, operand * right,
4013 operand * result, iCode * ifx, int sign, iCode *ic)
4015 int size, offset = 0;
4016 unsigned long lit = 0L;
4018 D(emitcode ("; genCmp",""));
4020 /* if left & right are bit variables */
4021 if (AOP_TYPE (left) == AOP_CRY &&
4022 AOP_TYPE (right) == AOP_CRY)
4024 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4025 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4029 /* subtract right from left if at the
4030 end the carry flag is set then we know that
4031 left is greater than right */
4032 size = max (AOP_SIZE (left), AOP_SIZE (right));
4034 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4035 if ((size == 1) && !sign &&
4036 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4038 symbol *lbl = newiTempLabel (NULL);
4039 emitcode ("cjne", "%s,%s,%05d$",
4040 aopGet (AOP (left), offset, FALSE, FALSE),
4041 aopGet (AOP (right), offset, FALSE, FALSE),
4043 emitcode ("", "%05d$:", lbl->key + 100);
4047 if (AOP_TYPE (right) == AOP_LIT)
4049 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4050 /* optimize if(x < 0) or if(x >= 0) */
4059 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4060 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4062 genIfxJump (ifx, "acc.7");
4066 emitcode ("rlc", "a");
4074 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4075 if (sign && size == 0)
4077 emitcode ("xrl", "a,#0x80");
4078 if (AOP_TYPE (right) == AOP_LIT)
4080 unsigned long lit = (unsigned long)
4081 floatFromVal (AOP (right)->aopu.aop_lit);
4082 emitcode ("subb", "a,#0x%02x",
4083 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4087 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4088 emitcode ("xrl", "b,#0x80");
4089 emitcode ("subb", "a,b");
4093 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4099 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4100 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4101 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4107 /* if the result is used in the next
4108 ifx conditional branch then generate
4109 code a little differently */
4111 genIfxJump (ifx, "c");
4114 /* leave the result in acc */
4118 /*-----------------------------------------------------------------*/
4119 /* genCmpGt :- greater than comparison */
4120 /*-----------------------------------------------------------------*/
4122 genCmpGt (iCode * ic, iCode * ifx)
4124 operand *left, *right, *result;
4125 sym_link *letype, *retype;
4128 D(emitcode ("; genCmpGt",""));
4130 left = IC_LEFT (ic);
4131 right = IC_RIGHT (ic);
4132 result = IC_RESULT (ic);
4134 letype = getSpec (operandType (left));
4135 retype = getSpec (operandType (right));
4136 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4137 /* assign the amsops */
4138 aopOp (left, ic, FALSE);
4139 aopOp (right, ic, FALSE);
4140 aopOp (result, ic, TRUE);
4142 genCmp (right, left, result, ifx, sign,ic);
4144 freeAsmop (result, NULL, ic, TRUE);
4147 /*-----------------------------------------------------------------*/
4148 /* genCmpLt - less than comparisons */
4149 /*-----------------------------------------------------------------*/
4151 genCmpLt (iCode * ic, iCode * ifx)
4153 operand *left, *right, *result;
4154 sym_link *letype, *retype;
4157 D(emitcode ("; genCmpLt",""));
4159 left = IC_LEFT (ic);
4160 right = IC_RIGHT (ic);
4161 result = IC_RESULT (ic);
4163 letype = getSpec (operandType (left));
4164 retype = getSpec (operandType (right));
4165 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4167 /* assign the amsops */
4168 aopOp (left, ic, FALSE);
4169 aopOp (right, ic, FALSE);
4170 aopOp (result, ic, TRUE);
4172 genCmp (left, right, result, ifx, sign,ic);
4174 freeAsmop (result, NULL, ic, TRUE);
4177 /*-----------------------------------------------------------------*/
4178 /* gencjneshort - compare and jump if not equal */
4179 /*-----------------------------------------------------------------*/
4181 gencjneshort (operand * left, operand * right, symbol * lbl)
4183 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4185 unsigned long lit = 0L;
4187 /* if the left side is a literal or
4188 if the right is in a pointer register and left
4190 if ((AOP_TYPE (left) == AOP_LIT) ||
4191 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4197 if (AOP_TYPE (right) == AOP_LIT)
4198 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4200 /* if the right side is a literal then anything goes */
4201 if (AOP_TYPE (right) == AOP_LIT &&
4202 AOP_TYPE (left) != AOP_DIR)
4206 emitcode ("cjne", "%s,%s,%05d$",
4207 aopGet (AOP (left), offset, FALSE, FALSE),
4208 aopGet (AOP (right), offset, FALSE, FALSE),
4214 /* if the right side is in a register or in direct space or
4215 if the left is a pointer register & right is not */
4216 else if (AOP_TYPE (right) == AOP_REG ||
4217 AOP_TYPE (right) == AOP_DIR ||
4218 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4219 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4223 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4224 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4225 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4226 emitcode ("jnz", "%05d$", lbl->key + 100);
4228 emitcode ("cjne", "a,%s,%05d$",
4229 aopGet (AOP (right), offset, FALSE, TRUE),
4236 /* right is a pointer reg need both a & b */
4239 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4240 if (strcmp (l, "b"))
4241 emitcode ("mov", "b,%s", l);
4242 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4243 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4249 /*-----------------------------------------------------------------*/
4250 /* gencjne - compare and jump if not equal */
4251 /*-----------------------------------------------------------------*/
4253 gencjne (operand * left, operand * right, symbol * lbl)
4255 symbol *tlbl = newiTempLabel (NULL);
4257 gencjneshort (left, right, lbl);
4259 emitcode ("mov", "a,%s", one);
4260 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4261 emitcode ("", "%05d$:", lbl->key + 100);
4262 emitcode ("clr", "a");
4263 emitcode ("", "%05d$:", tlbl->key + 100);
4266 /*-----------------------------------------------------------------*/
4267 /* genCmpEq - generates code for equal to */
4268 /*-----------------------------------------------------------------*/
4270 genCmpEq (iCode * ic, iCode * ifx)
4272 operand *left, *right, *result;
4274 D(emitcode ("; genCmpEq",""));
4276 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4277 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4278 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4280 /* if literal, literal on the right or
4281 if the right is in a pointer register and left
4283 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4284 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4286 operand *t = IC_RIGHT (ic);
4287 IC_RIGHT (ic) = IC_LEFT (ic);
4291 if (ifx && !AOP_SIZE (result))
4294 /* if they are both bit variables */
4295 if (AOP_TYPE (left) == AOP_CRY &&
4296 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4298 if (AOP_TYPE (right) == AOP_LIT)
4300 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4303 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4304 emitcode ("cpl", "c");
4308 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4312 emitcode ("clr", "c");
4314 /* AOP_TYPE(right) == AOP_CRY */
4318 symbol *lbl = newiTempLabel (NULL);
4319 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4320 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4321 emitcode ("cpl", "c");
4322 emitcode ("", "%05d$:", (lbl->key + 100));
4324 /* if true label then we jump if condition
4326 tlbl = newiTempLabel (NULL);
4329 emitcode ("jnc", "%05d$", tlbl->key + 100);
4330 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4334 emitcode ("jc", "%05d$", tlbl->key + 100);
4335 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4337 emitcode ("", "%05d$:", tlbl->key + 100);
4341 tlbl = newiTempLabel (NULL);
4342 gencjneshort (left, right, tlbl);
4345 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4346 emitcode ("", "%05d$:", tlbl->key + 100);
4350 symbol *lbl = newiTempLabel (NULL);
4351 emitcode ("sjmp", "%05d$", lbl->key + 100);
4352 emitcode ("", "%05d$:", tlbl->key + 100);
4353 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4354 emitcode ("", "%05d$:", lbl->key + 100);
4357 /* mark the icode as generated */
4362 /* if they are both bit variables */
4363 if (AOP_TYPE (left) == AOP_CRY &&
4364 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4366 if (AOP_TYPE (right) == AOP_LIT)
4368 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4371 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4372 emitcode ("cpl", "c");
4376 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4380 emitcode ("clr", "c");
4382 /* AOP_TYPE(right) == AOP_CRY */
4386 symbol *lbl = newiTempLabel (NULL);
4387 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4388 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4389 emitcode ("cpl", "c");
4390 emitcode ("", "%05d$:", (lbl->key + 100));
4393 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4400 genIfxJump (ifx, "c");
4403 /* if the result is used in an arithmetic operation
4404 then put the result in place */
4409 gencjne (left, right, newiTempLabel (NULL));
4410 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4412 aopPut (AOP (result), "a", 0);
4417 genIfxJump (ifx, "a");
4420 /* if the result is used in an arithmetic operation
4421 then put the result in place */
4422 if (AOP_TYPE (result) != AOP_CRY)
4424 /* leave the result in acc */
4428 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4429 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4430 freeAsmop (result, NULL, ic, TRUE);
4433 /*-----------------------------------------------------------------*/
4434 /* ifxForOp - returns the icode containing the ifx for operand */
4435 /*-----------------------------------------------------------------*/
4437 ifxForOp (operand * op, iCode * ic)
4439 /* if true symbol then needs to be assigned */
4440 if (IS_TRUE_SYMOP (op))
4443 /* if this has register type condition and
4444 the next instruction is ifx with the same operand
4445 and live to of the operand is upto the ifx only then */
4447 ic->next->op == IFX &&
4448 IC_COND (ic->next)->key == op->key &&
4449 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4455 /*-----------------------------------------------------------------*/
4456 /* hasInc - operand is incremented before any other use */
4457 /*-----------------------------------------------------------------*/
4459 hasInc (operand *op, iCode *ic,int osize)
4461 sym_link *type = operandType(op);
4462 sym_link *retype = getSpec (type);
4463 iCode *lic = ic->next;
4466 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4467 if (!IS_SYMOP(op)) return NULL;
4469 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4470 if (IS_AGGREGATE(type->next)) return NULL;
4471 if (osize != (isize = getSize(type->next))) return NULL;
4474 /* if operand of the form op = op + <sizeof *op> */
4475 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4476 isOperandEqual(IC_RESULT(lic),op) &&
4477 isOperandLiteral(IC_RIGHT(lic)) &&
4478 operandLitValue(IC_RIGHT(lic)) == isize) {
4481 /* if the operand used or deffed */
4482 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4485 /* if GOTO or IFX */
4486 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4492 /*-----------------------------------------------------------------*/
4493 /* genAndOp - for && operation */
4494 /*-----------------------------------------------------------------*/
4496 genAndOp (iCode * ic)
4498 operand *left, *right, *result;
4501 D(emitcode ("; genAndOp",""));
4503 /* note here that && operations that are in an
4504 if statement are taken away by backPatchLabels
4505 only those used in arthmetic operations remain */
4506 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4507 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4508 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4510 /* if both are bit variables */
4511 if (AOP_TYPE (left) == AOP_CRY &&
4512 AOP_TYPE (right) == AOP_CRY)
4514 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4515 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4520 tlbl = newiTempLabel (NULL);
4522 emitcode ("jz", "%05d$", tlbl->key + 100);
4524 emitcode ("", "%05d$:", tlbl->key + 100);
4528 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4529 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4530 freeAsmop (result, NULL, ic, TRUE);
4534 /*-----------------------------------------------------------------*/
4535 /* genOrOp - for || operation */
4536 /*-----------------------------------------------------------------*/
4538 genOrOp (iCode * ic)
4540 operand *left, *right, *result;
4543 D(emitcode ("; genOrOp",""));
4545 /* note here that || operations that are in an
4546 if statement are taken away by backPatchLabels
4547 only those used in arthmetic operations remain */
4548 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4549 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4550 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4552 /* if both are bit variables */
4553 if (AOP_TYPE (left) == AOP_CRY &&
4554 AOP_TYPE (right) == AOP_CRY)
4556 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4557 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4562 tlbl = newiTempLabel (NULL);
4564 emitcode ("jnz", "%05d$", tlbl->key + 100);
4566 emitcode ("", "%05d$:", tlbl->key + 100);
4570 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4571 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4572 freeAsmop (result, NULL, ic, TRUE);
4575 /*-----------------------------------------------------------------*/
4576 /* isLiteralBit - test if lit == 2^n */
4577 /*-----------------------------------------------------------------*/
4579 isLiteralBit (unsigned long lit)
4581 unsigned long pw[32] =
4582 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4583 0x100L, 0x200L, 0x400L, 0x800L,
4584 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4585 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4586 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4587 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4588 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4591 for (idx = 0; idx < 32; idx++)
4597 /*-----------------------------------------------------------------*/
4598 /* continueIfTrue - */
4599 /*-----------------------------------------------------------------*/
4601 continueIfTrue (iCode * ic)
4604 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4608 /*-----------------------------------------------------------------*/
4610 /*-----------------------------------------------------------------*/
4612 jumpIfTrue (iCode * ic)
4615 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4619 /*-----------------------------------------------------------------*/
4620 /* jmpTrueOrFalse - */
4621 /*-----------------------------------------------------------------*/
4623 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4625 // ugly but optimized by peephole
4628 symbol *nlbl = newiTempLabel (NULL);
4629 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4630 emitcode ("", "%05d$:", tlbl->key + 100);
4631 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4632 emitcode ("", "%05d$:", nlbl->key + 100);
4636 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4637 emitcode ("", "%05d$:", tlbl->key + 100);
4642 /*-----------------------------------------------------------------*/
4643 /* genAnd - code for and */
4644 /*-----------------------------------------------------------------*/
4646 genAnd (iCode * ic, iCode * ifx)
4648 operand *left, *right, *result;
4649 int size, offset = 0;
4650 unsigned long lit = 0L;
4654 D(emitcode ("; genAnd",""));
4656 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4657 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4658 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4661 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4663 AOP_TYPE (left), AOP_TYPE (right));
4664 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4666 AOP_SIZE (left), AOP_SIZE (right));
4669 /* if left is a literal & right is not then exchange them */
4670 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4671 AOP_NEEDSACC (left))
4673 operand *tmp = right;
4678 /* if result = right then exchange them */
4679 if (sameRegs (AOP (result), AOP (right)))
4681 operand *tmp = right;
4686 /* if right is bit then exchange them */
4687 if (AOP_TYPE (right) == AOP_CRY &&
4688 AOP_TYPE (left) != AOP_CRY)
4690 operand *tmp = right;
4694 if (AOP_TYPE (right) == AOP_LIT)
4695 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4697 size = AOP_SIZE (result);
4700 // result = bit & yy;
4701 if (AOP_TYPE (left) == AOP_CRY)
4703 // c = bit & literal;
4704 if (AOP_TYPE (right) == AOP_LIT)
4708 if (size && sameRegs (AOP (result), AOP (left)))
4711 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4716 if (size && (AOP_TYPE (result) == AOP_CRY))
4718 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4721 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4726 emitcode ("clr", "c");
4731 if (AOP_TYPE (right) == AOP_CRY)
4734 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4735 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4740 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4742 emitcode ("rrc", "a");
4743 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4751 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4752 genIfxJump (ifx, "c");
4756 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4757 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4758 if ((AOP_TYPE (right) == AOP_LIT) &&
4759 (AOP_TYPE (result) == AOP_CRY) &&
4760 (AOP_TYPE (left) != AOP_CRY))
4762 int posbit = isLiteralBit (lit);
4767 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4770 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4776 sprintf (buffer, "acc.%d", posbit & 0x07);
4777 genIfxJump (ifx, buffer);
4784 symbol *tlbl = newiTempLabel (NULL);
4785 int sizel = AOP_SIZE (left);
4787 emitcode ("setb", "c");
4790 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4792 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4794 if ((posbit = isLiteralBit (bytelit)) != 0)
4795 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4798 if (bytelit != 0x0FFL)
4799 emitcode ("anl", "a,%s",
4800 aopGet (AOP (right), offset, FALSE, TRUE));
4801 emitcode ("jnz", "%05d$", tlbl->key + 100);
4806 // bit = left & literal
4809 emitcode ("clr", "c");
4810 emitcode ("", "%05d$:", tlbl->key + 100);
4812 // if(left & literal)
4816 jmpTrueOrFalse (ifx, tlbl);
4824 /* if left is same as result */
4825 if (sameRegs (AOP (result), AOP (left)))
4827 for (; size--; offset++)
4829 if (AOP_TYPE (right) == AOP_LIT)
4831 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4833 else if (bytelit == 0)
4834 aopPut (AOP (result), zero, offset);
4835 else if (IS_AOP_PREG (result))
4837 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4838 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4839 aopPut (AOP (result), "a", offset);
4842 emitcode ("anl", "%s,%s",
4843 aopGet (AOP (left), offset, FALSE, TRUE),
4844 aopGet (AOP (right), offset, FALSE, FALSE));
4848 if (AOP_TYPE (left) == AOP_ACC)
4849 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4852 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4853 if (IS_AOP_PREG (result))
4855 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4856 aopPut (AOP (result), "a", offset);
4860 emitcode ("anl", "%s,a",
4861 aopGet (AOP (left), offset, FALSE, TRUE));
4868 // left & result in different registers
4869 if (AOP_TYPE (result) == AOP_CRY)
4872 // if(size), result in bit
4873 // if(!size && ifx), conditional oper: if(left & right)
4874 symbol *tlbl = newiTempLabel (NULL);
4875 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4877 emitcode ("setb", "c");
4880 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4881 emitcode ("anl", "a,%s",
4882 aopGet (AOP (right), offset, FALSE, FALSE));
4884 if (AOP_TYPE(left)==AOP_ACC) {
4885 emitcode("mov", "b,a");
4886 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4887 emitcode("anl", "a,b");
4889 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4890 emitcode ("anl", "a,%s",
4891 aopGet (AOP (left), offset, FALSE, FALSE));
4894 emitcode ("jnz", "%05d$", tlbl->key + 100);
4900 emitcode ("", "%05d$:", tlbl->key + 100);
4904 jmpTrueOrFalse (ifx, tlbl);
4908 for (; (size--); offset++)
4911 // result = left & right
4912 if (AOP_TYPE (right) == AOP_LIT)
4914 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4916 aopPut (AOP (result),
4917 aopGet (AOP (left), offset, FALSE, FALSE),
4921 else if (bytelit == 0)
4923 aopPut (AOP (result), zero, offset);
4927 // faster than result <- left, anl result,right
4928 // and better if result is SFR
4929 if (AOP_TYPE (left) == AOP_ACC)
4930 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4933 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4934 emitcode ("anl", "a,%s",
4935 aopGet (AOP (left), offset, FALSE, FALSE));
4937 aopPut (AOP (result), "a", offset);
4943 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4944 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4945 freeAsmop (result, NULL, ic, TRUE);
4948 /*-----------------------------------------------------------------*/
4949 /* genOr - code for or */
4950 /*-----------------------------------------------------------------*/
4952 genOr (iCode * ic, iCode * ifx)
4954 operand *left, *right, *result;
4955 int size, offset = 0;
4956 unsigned long lit = 0L;
4958 D(emitcode ("; genOr",""));
4960 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4961 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4962 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4965 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4967 AOP_TYPE (left), AOP_TYPE (right));
4968 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4970 AOP_SIZE (left), AOP_SIZE (right));
4973 /* if left is a literal & right is not then exchange them */
4974 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4975 AOP_NEEDSACC (left))
4977 operand *tmp = right;
4982 /* if result = right then exchange them */
4983 if (sameRegs (AOP (result), AOP (right)))
4985 operand *tmp = right;
4990 /* if right is bit then exchange them */
4991 if (AOP_TYPE (right) == AOP_CRY &&
4992 AOP_TYPE (left) != AOP_CRY)
4994 operand *tmp = right;
4998 if (AOP_TYPE (right) == AOP_LIT)
4999 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5001 size = AOP_SIZE (result);
5005 if (AOP_TYPE (left) == AOP_CRY)
5007 if (AOP_TYPE (right) == AOP_LIT)
5009 // c = bit | literal;
5012 // lit != 0 => result = 1
5013 if (AOP_TYPE (result) == AOP_CRY)
5016 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5018 continueIfTrue (ifx);
5021 emitcode ("setb", "c");
5025 // lit == 0 => result = left
5026 if (size && sameRegs (AOP (result), AOP (left)))
5028 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5033 if (AOP_TYPE (right) == AOP_CRY)
5036 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5037 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5042 symbol *tlbl = newiTempLabel (NULL);
5043 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5044 emitcode ("setb", "c");
5045 emitcode ("jb", "%s,%05d$",
5046 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5048 emitcode ("jnz", "%05d$", tlbl->key + 100);
5049 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5051 jmpTrueOrFalse (ifx, tlbl);
5057 emitcode ("", "%05d$:", tlbl->key + 100);
5066 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5067 genIfxJump (ifx, "c");
5071 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5072 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5073 if ((AOP_TYPE (right) == AOP_LIT) &&
5074 (AOP_TYPE (result) == AOP_CRY) &&
5075 (AOP_TYPE (left) != AOP_CRY))
5081 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5083 continueIfTrue (ifx);
5088 // lit = 0, result = boolean(left)
5090 emitcode ("setb", "c");
5094 symbol *tlbl = newiTempLabel (NULL);
5095 emitcode ("jnz", "%05d$", tlbl->key + 100);
5097 emitcode ("", "%05d$:", tlbl->key + 100);
5101 genIfxJump (ifx, "a");
5109 /* if left is same as result */
5110 if (sameRegs (AOP (result), AOP (left)))
5112 for (; size--; offset++)
5114 if (AOP_TYPE (right) == AOP_LIT)
5116 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5118 else if (IS_AOP_PREG (left))
5120 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5121 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5122 aopPut (AOP (result), "a", offset);
5125 emitcode ("orl", "%s,%s",
5126 aopGet (AOP (left), offset, FALSE, TRUE),
5127 aopGet (AOP (right), offset, FALSE, FALSE));
5131 if (AOP_TYPE (left) == AOP_ACC)
5132 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5135 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5136 if (IS_AOP_PREG (left))
5138 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5139 aopPut (AOP (result), "a", offset);
5142 emitcode ("orl", "%s,a",
5143 aopGet (AOP (left), offset, FALSE, TRUE));
5150 // left & result in different registers
5151 if (AOP_TYPE (result) == AOP_CRY)
5154 // if(size), result in bit
5155 // if(!size && ifx), conditional oper: if(left | right)
5156 symbol *tlbl = newiTempLabel (NULL);
5157 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5159 emitcode ("setb", "c");
5162 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5163 emitcode ("orl", "a,%s",
5164 aopGet (AOP (right), offset, FALSE, FALSE));
5166 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5167 emitcode ("orl", "a,%s",
5168 aopGet (AOP (left), offset, FALSE, FALSE));
5170 emitcode ("jnz", "%05d$", tlbl->key + 100);
5176 emitcode ("", "%05d$:", tlbl->key + 100);
5180 jmpTrueOrFalse (ifx, tlbl);
5183 for (; (size--); offset++)
5186 // result = left & right
5187 if (AOP_TYPE (right) == AOP_LIT)
5189 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5191 aopPut (AOP (result),
5192 aopGet (AOP (left), offset, FALSE, FALSE),
5197 // faster than result <- left, anl result,right
5198 // and better if result is SFR
5199 if (AOP_TYPE (left) == AOP_ACC)
5200 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5203 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5204 emitcode ("orl", "a,%s",
5205 aopGet (AOP (left), offset, FALSE, FALSE));
5207 aopPut (AOP (result), "a", offset);
5212 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5213 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5214 freeAsmop (result, NULL, ic, TRUE);
5217 /*-----------------------------------------------------------------*/
5218 /* genXor - code for xclusive or */
5219 /*-----------------------------------------------------------------*/
5221 genXor (iCode * ic, iCode * ifx)
5223 operand *left, *right, *result;
5224 int size, offset = 0;
5225 unsigned long lit = 0L;
5227 D(emitcode ("; genXor",""));
5229 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5230 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5231 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5234 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5236 AOP_TYPE (left), AOP_TYPE (right));
5237 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5239 AOP_SIZE (left), AOP_SIZE (right));
5242 /* if left is a literal & right is not ||
5243 if left needs acc & right does not */
5244 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5245 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5247 operand *tmp = right;
5252 /* if result = right then exchange them */
5253 if (sameRegs (AOP (result), AOP (right)))
5255 operand *tmp = right;
5260 /* if right is bit then exchange them */
5261 if (AOP_TYPE (right) == AOP_CRY &&
5262 AOP_TYPE (left) != AOP_CRY)
5264 operand *tmp = right;
5268 if (AOP_TYPE (right) == AOP_LIT)
5269 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5271 size = AOP_SIZE (result);
5275 if (AOP_TYPE (left) == AOP_CRY)
5277 if (AOP_TYPE (right) == AOP_LIT)
5279 // c = bit & literal;
5282 // lit>>1 != 0 => result = 1
5283 if (AOP_TYPE (result) == AOP_CRY)
5286 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5288 continueIfTrue (ifx);
5291 emitcode ("setb", "c");
5298 // lit == 0, result = left
5299 if (size && sameRegs (AOP (result), AOP (left)))
5301 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5305 // lit == 1, result = not(left)
5306 if (size && sameRegs (AOP (result), AOP (left)))
5308 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5313 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5314 emitcode ("cpl", "c");
5323 symbol *tlbl = newiTempLabel (NULL);
5324 if (AOP_TYPE (right) == AOP_CRY)
5327 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5331 int sizer = AOP_SIZE (right);
5333 // if val>>1 != 0, result = 1
5334 emitcode ("setb", "c");
5337 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5339 // test the msb of the lsb
5340 emitcode ("anl", "a,#0xfe");
5341 emitcode ("jnz", "%05d$", tlbl->key + 100);
5345 emitcode ("rrc", "a");
5347 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5348 emitcode ("cpl", "c");
5349 emitcode ("", "%05d$:", (tlbl->key + 100));
5356 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5357 genIfxJump (ifx, "c");
5361 if (sameRegs (AOP (result), AOP (left)))
5363 /* if left is same as result */
5364 for (; size--; offset++)
5366 if (AOP_TYPE (right) == AOP_LIT)
5368 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5370 else if (IS_AOP_PREG (left))
5372 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5373 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5374 aopPut (AOP (result), "a", offset);
5377 emitcode ("xrl", "%s,%s",
5378 aopGet (AOP (left), offset, FALSE, TRUE),
5379 aopGet (AOP (right), offset, FALSE, FALSE));
5383 if (AOP_TYPE (left) == AOP_ACC)
5384 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5387 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5388 if (IS_AOP_PREG (left))
5390 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5391 aopPut (AOP (result), "a", offset);
5394 emitcode ("xrl", "%s,a",
5395 aopGet (AOP (left), offset, FALSE, TRUE));
5402 // left & result in different registers
5403 if (AOP_TYPE (result) == AOP_CRY)
5406 // if(size), result in bit
5407 // if(!size && ifx), conditional oper: if(left ^ right)
5408 symbol *tlbl = newiTempLabel (NULL);
5409 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5411 emitcode ("setb", "c");
5414 if ((AOP_TYPE (right) == AOP_LIT) &&
5415 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5417 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5421 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5422 emitcode ("xrl", "a,%s",
5423 aopGet (AOP (right), offset, FALSE, FALSE));
5425 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5426 emitcode ("xrl", "a,%s",
5427 aopGet (AOP (left), offset, FALSE, FALSE));
5430 emitcode ("jnz", "%05d$", tlbl->key + 100);
5436 emitcode ("", "%05d$:", tlbl->key + 100);
5440 jmpTrueOrFalse (ifx, tlbl);
5443 for (; (size--); offset++)
5446 // result = left & right
5447 if (AOP_TYPE (right) == AOP_LIT)
5449 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5451 aopPut (AOP (result),
5452 aopGet (AOP (left), offset, FALSE, FALSE),
5457 // faster than result <- left, anl result,right
5458 // and better if result is SFR
5459 if (AOP_TYPE (left) == AOP_ACC)
5460 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5463 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5464 emitcode ("xrl", "a,%s",
5465 aopGet (AOP (left), offset, FALSE, TRUE));
5467 aopPut (AOP (result), "a", offset);
5472 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5473 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5474 freeAsmop (result, NULL, ic, TRUE);
5477 /*-----------------------------------------------------------------*/
5478 /* genInline - write the inline code out */
5479 /*-----------------------------------------------------------------*/
5481 genInline (iCode * ic)
5483 char *buffer, *bp, *bp1;
5485 D(emitcode ("; genInline",""));
5487 _G.inLine += (!options.asmpeep);
5489 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5490 strcpy (buffer, IC_INLINE (ic));
5492 /* emit each line as a code */
5517 /* emitcode("",buffer); */
5518 _G.inLine -= (!options.asmpeep);
5521 /*-----------------------------------------------------------------*/
5522 /* genRRC - rotate right with carry */
5523 /*-----------------------------------------------------------------*/
5527 operand *left, *result;
5528 int size, offset = 0;
5531 D(emitcode ("; genRRC",""));
5533 /* rotate right with carry */
5534 left = IC_LEFT (ic);
5535 result = IC_RESULT (ic);
5536 aopOp (left, ic, FALSE);
5537 aopOp (result, ic, FALSE);
5539 /* move it to the result */
5540 size = AOP_SIZE (result);
5542 if (size == 1) { /* special case for 1 byte */
5543 l = aopGet (AOP (left), offset, FALSE, FALSE);
5545 emitcode ("rr", "a");
5551 l = aopGet (AOP (left), offset, FALSE, FALSE);
5553 emitcode ("rrc", "a");
5554 if (AOP_SIZE (result) > 1)
5555 aopPut (AOP (result), "a", offset--);
5557 /* now we need to put the carry into the
5558 highest order byte of the result */
5559 if (AOP_SIZE (result) > 1)
5561 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5564 emitcode ("mov", "acc.7,c");
5566 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5567 freeAsmop (left, NULL, ic, TRUE);
5568 freeAsmop (result, NULL, ic, TRUE);
5571 /*-----------------------------------------------------------------*/
5572 /* genRLC - generate code for rotate left with carry */
5573 /*-----------------------------------------------------------------*/
5577 operand *left, *result;
5578 int size, offset = 0;
5581 D(emitcode ("; genRLC",""));
5583 /* rotate right with carry */
5584 left = IC_LEFT (ic);
5585 result = IC_RESULT (ic);
5586 aopOp (left, ic, FALSE);
5587 aopOp (result, ic, FALSE);
5589 /* move it to the result */
5590 size = AOP_SIZE (result);
5594 l = aopGet (AOP (left), offset, FALSE, FALSE);
5596 if (size == 0) { /* special case for 1 byte */
5600 emitcode ("add", "a,acc");
5601 if (AOP_SIZE (result) > 1)
5602 aopPut (AOP (result), "a", offset++);
5605 l = aopGet (AOP (left), offset, FALSE, FALSE);
5607 emitcode ("rlc", "a");
5608 if (AOP_SIZE (result) > 1)
5609 aopPut (AOP (result), "a", offset++);
5612 /* now we need to put the carry into the
5613 highest order byte of the result */
5614 if (AOP_SIZE (result) > 1)
5616 l = aopGet (AOP (result), 0, FALSE, FALSE);
5619 emitcode ("mov", "acc.0,c");
5621 aopPut (AOP (result), "a", 0);
5622 freeAsmop (left, NULL, ic, TRUE);
5623 freeAsmop (result, NULL, ic, TRUE);
5626 /*-----------------------------------------------------------------*/
5627 /* genGetHbit - generates code get highest order bit */
5628 /*-----------------------------------------------------------------*/
5630 genGetHbit (iCode * ic)
5632 operand *left, *result;
5634 D(emitcode ("; genGetHbit",""));
5636 left = IC_LEFT (ic);
5637 result = IC_RESULT (ic);
5638 aopOp (left, ic, FALSE);
5639 aopOp (result, ic, FALSE);
5641 /* get the highest order byte into a */
5642 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5643 if (AOP_TYPE (result) == AOP_CRY)
5645 emitcode ("rlc", "a");
5650 emitcode ("rl", "a");
5651 emitcode ("anl", "a,#0x01");
5656 freeAsmop (left, NULL, ic, TRUE);
5657 freeAsmop (result, NULL, ic, TRUE);
5660 /*-----------------------------------------------------------------*/
5661 /* AccRol - rotate left accumulator by known count */
5662 /*-----------------------------------------------------------------*/
5664 AccRol (int shCount)
5666 shCount &= 0x0007; // shCount : 0..7
5673 emitcode ("rl", "a");
5676 emitcode ("rl", "a");
5677 emitcode ("rl", "a");
5680 emitcode ("swap", "a");
5681 emitcode ("rr", "a");
5684 emitcode ("swap", "a");
5687 emitcode ("swap", "a");
5688 emitcode ("rl", "a");
5691 emitcode ("rr", "a");
5692 emitcode ("rr", "a");
5695 emitcode ("rr", "a");
5700 /*-----------------------------------------------------------------*/
5701 /* AccLsh - left shift accumulator by known count */
5702 /*-----------------------------------------------------------------*/
5704 AccLsh (int shCount)
5709 emitcode ("add", "a,acc");
5710 else if (shCount == 2)
5712 emitcode ("add", "a,acc");
5713 emitcode ("add", "a,acc");
5717 /* rotate left accumulator */
5719 /* and kill the lower order bits */
5720 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5725 /*-----------------------------------------------------------------*/
5726 /* AccRsh - right shift accumulator by known count */
5727 /*-----------------------------------------------------------------*/
5729 AccRsh (int shCount)
5736 emitcode ("rrc", "a");
5740 /* rotate right accumulator */
5741 AccRol (8 - shCount);
5742 /* and kill the higher order bits */
5743 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5748 /*-----------------------------------------------------------------*/
5749 /* AccSRsh - signed right shift accumulator by known count */
5750 /*-----------------------------------------------------------------*/
5752 AccSRsh (int shCount)
5759 emitcode ("mov", "c,acc.7");
5760 emitcode ("rrc", "a");
5762 else if (shCount == 2)
5764 emitcode ("mov", "c,acc.7");
5765 emitcode ("rrc", "a");
5766 emitcode ("mov", "c,acc.7");
5767 emitcode ("rrc", "a");
5771 tlbl = newiTempLabel (NULL);
5772 /* rotate right accumulator */
5773 AccRol (8 - shCount);
5774 /* and kill the higher order bits */
5775 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5776 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5777 emitcode ("orl", "a,#0x%02x",
5778 (unsigned char) ~SRMask[shCount]);
5779 emitcode ("", "%05d$:", tlbl->key + 100);
5784 /*-----------------------------------------------------------------*/
5785 /* shiftR1Left2Result - shift right one byte from left to result */
5786 /*-----------------------------------------------------------------*/
5788 shiftR1Left2Result (operand * left, int offl,
5789 operand * result, int offr,
5790 int shCount, int sign)
5792 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5793 /* shift right accumulator */
5798 aopPut (AOP (result), "a", offr);
5801 /*-----------------------------------------------------------------*/
5802 /* shiftL1Left2Result - shift left one byte from left to result */
5803 /*-----------------------------------------------------------------*/
5805 shiftL1Left2Result (operand * left, int offl,
5806 operand * result, int offr, int shCount)
5809 l = aopGet (AOP (left), offl, FALSE, FALSE);
5811 /* shift left accumulator */
5813 aopPut (AOP (result), "a", offr);
5816 /*-----------------------------------------------------------------*/
5817 /* movLeft2Result - move byte from left to result */
5818 /*-----------------------------------------------------------------*/
5820 movLeft2Result (operand * left, int offl,
5821 operand * result, int offr, int sign)
5824 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5826 l = aopGet (AOP (left), offl, FALSE, FALSE);
5828 if (*l == '@' && (IS_AOP_PREG (result)))
5830 emitcode ("mov", "a,%s", l);
5831 aopPut (AOP (result), "a", offr);
5836 aopPut (AOP (result), l, offr);
5839 /* MSB sign in acc.7 ! */
5840 if (getDataSize (left) == offl + 1)
5842 emitcode ("mov", "a,%s", l);
5843 aopPut (AOP (result), "a", offr);
5850 /*-----------------------------------------------------------------*/
5851 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5852 /*-----------------------------------------------------------------*/
5856 emitcode ("rrc", "a");
5857 emitcode ("xch", "a,%s", x);
5858 emitcode ("rrc", "a");
5859 emitcode ("xch", "a,%s", x);
5862 /*-----------------------------------------------------------------*/
5863 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5864 /*-----------------------------------------------------------------*/
5868 emitcode ("xch", "a,%s", x);
5869 emitcode ("rlc", "a");
5870 emitcode ("xch", "a,%s", x);
5871 emitcode ("rlc", "a");
5874 /*-----------------------------------------------------------------*/
5875 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5876 /*-----------------------------------------------------------------*/
5880 emitcode ("xch", "a,%s", x);
5881 emitcode ("add", "a,acc");
5882 emitcode ("xch", "a,%s", x);
5883 emitcode ("rlc", "a");
5886 /*-----------------------------------------------------------------*/
5887 /* AccAXLsh - left shift a:x by known count (0..7) */
5888 /*-----------------------------------------------------------------*/
5890 AccAXLsh (char *x, int shCount)
5905 case 5: // AAAAABBB:CCCCCDDD
5907 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5909 emitcode ("anl", "a,#0x%02x",
5910 SLMask[shCount]); // BBB00000:CCCCCDDD
5912 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5914 AccRol (shCount); // DDDCCCCC:BBB00000
5916 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5918 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5920 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5922 emitcode ("anl", "a,#0x%02x",
5923 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5925 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5927 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5930 case 6: // AAAAAABB:CCCCCCDD
5931 emitcode ("anl", "a,#0x%02x",
5932 SRMask[shCount]); // 000000BB:CCCCCCDD
5933 emitcode ("mov", "c,acc.0"); // c = B
5934 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5936 AccAXRrl1 (x); // BCCCCCCD:D000000B
5937 AccAXRrl1 (x); // BBCCCCCC:DD000000
5939 emitcode("rrc","a");
5940 emitcode("xch","a,%s", x);
5941 emitcode("rrc","a");
5942 emitcode("mov","c,acc.0"); //<< get correct bit
5943 emitcode("xch","a,%s", x);
5945 emitcode("rrc","a");
5946 emitcode("xch","a,%s", x);
5947 emitcode("rrc","a");
5948 emitcode("xch","a,%s", x);
5951 case 7: // a:x <<= 7
5953 emitcode ("anl", "a,#0x%02x",
5954 SRMask[shCount]); // 0000000B:CCCCCCCD
5956 emitcode ("mov", "c,acc.0"); // c = B
5958 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5960 AccAXRrl1 (x); // BCCCCCCC:D0000000
5968 /*-----------------------------------------------------------------*/
5969 /* AccAXRsh - right shift a:x known count (0..7) */
5970 /*-----------------------------------------------------------------*/
5972 AccAXRsh (char *x, int shCount)
5980 AccAXRrl1 (x); // 0->a:x
5985 AccAXRrl1 (x); // 0->a:x
5988 AccAXRrl1 (x); // 0->a:x
5993 case 5: // AAAAABBB:CCCCCDDD = a:x
5995 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5997 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5999 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6001 emitcode ("anl", "a,#0x%02x",
6002 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6004 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6006 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6008 emitcode ("anl", "a,#0x%02x",
6009 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6011 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6013 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6015 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6018 case 6: // AABBBBBB:CCDDDDDD
6020 emitcode ("mov", "c,acc.7");
6021 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6023 emitcode ("mov", "c,acc.7");
6024 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6026 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6028 emitcode ("anl", "a,#0x%02x",
6029 SRMask[shCount]); // 000000AA:BBBBBBCC
6032 case 7: // ABBBBBBB:CDDDDDDD
6034 emitcode ("mov", "c,acc.7"); // c = A
6036 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6038 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6040 emitcode ("anl", "a,#0x%02x",
6041 SRMask[shCount]); // 0000000A:BBBBBBBC
6049 /*-----------------------------------------------------------------*/
6050 /* AccAXRshS - right shift signed a:x known count (0..7) */
6051 /*-----------------------------------------------------------------*/
6053 AccAXRshS (char *x, int shCount)
6061 emitcode ("mov", "c,acc.7");
6062 AccAXRrl1 (x); // s->a:x
6066 emitcode ("mov", "c,acc.7");
6067 AccAXRrl1 (x); // s->a:x
6069 emitcode ("mov", "c,acc.7");
6070 AccAXRrl1 (x); // s->a:x
6075 case 5: // AAAAABBB:CCCCCDDD = a:x
6077 tlbl = newiTempLabel (NULL);
6078 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6080 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6082 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6084 emitcode ("anl", "a,#0x%02x",
6085 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6087 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6089 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6091 emitcode ("anl", "a,#0x%02x",
6092 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6094 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6096 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6098 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6100 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6101 emitcode ("orl", "a,#0x%02x",
6102 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6104 emitcode ("", "%05d$:", tlbl->key + 100);
6105 break; // SSSSAAAA:BBBCCCCC
6107 case 6: // AABBBBBB:CCDDDDDD
6109 tlbl = newiTempLabel (NULL);
6110 emitcode ("mov", "c,acc.7");
6111 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6113 emitcode ("mov", "c,acc.7");
6114 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6116 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6118 emitcode ("anl", "a,#0x%02x",
6119 SRMask[shCount]); // 000000AA:BBBBBBCC
6121 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6122 emitcode ("orl", "a,#0x%02x",
6123 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6125 emitcode ("", "%05d$:", tlbl->key + 100);
6127 case 7: // ABBBBBBB:CDDDDDDD
6129 tlbl = newiTempLabel (NULL);
6130 emitcode ("mov", "c,acc.7"); // c = A
6132 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6134 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6136 emitcode ("anl", "a,#0x%02x",
6137 SRMask[shCount]); // 0000000A:BBBBBBBC
6139 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6140 emitcode ("orl", "a,#0x%02x",
6141 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6143 emitcode ("", "%05d$:", tlbl->key + 100);
6150 /*-----------------------------------------------------------------*/
6151 /* shiftL2Left2Result - shift left two bytes from left to result */
6152 /*-----------------------------------------------------------------*/
6154 shiftL2Left2Result (operand * left, int offl,
6155 operand * result, int offr, int shCount)
6157 if (sameRegs (AOP (result), AOP (left)) &&
6158 ((offl + MSB16) == offr))
6160 /* don't crash result[offr] */
6161 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6162 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6166 movLeft2Result (left, offl, result, offr, 0);
6167 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6169 /* ax << shCount (x = lsb(result)) */
6170 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6171 aopPut (AOP (result), "a", offr + MSB16);
6175 /*-----------------------------------------------------------------*/
6176 /* shiftR2Left2Result - shift right two bytes from left to result */
6177 /*-----------------------------------------------------------------*/
6179 shiftR2Left2Result (operand * left, int offl,
6180 operand * result, int offr,
6181 int shCount, int sign)
6183 if (sameRegs (AOP (result), AOP (left)) &&
6184 ((offl + MSB16) == offr))
6186 /* don't crash result[offr] */
6187 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6188 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6192 movLeft2Result (left, offl, result, offr, 0);
6193 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6195 /* a:x >> shCount (x = lsb(result)) */
6197 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6199 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6200 if (getDataSize (result) > 1)
6201 aopPut (AOP (result), "a", offr + MSB16);
6204 /*-----------------------------------------------------------------*/
6205 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6206 /*-----------------------------------------------------------------*/
6208 shiftLLeftOrResult (operand * left, int offl,
6209 operand * result, int offr, int shCount)
6211 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6212 /* shift left accumulator */
6214 /* or with result */
6215 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6216 /* back to result */
6217 aopPut (AOP (result), "a", offr);
6220 /*-----------------------------------------------------------------*/
6221 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6222 /*-----------------------------------------------------------------*/
6224 shiftRLeftOrResult (operand * left, int offl,
6225 operand * result, int offr, int shCount)
6227 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6228 /* shift right accumulator */
6230 /* or with result */
6231 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6232 /* back to result */
6233 aopPut (AOP (result), "a", offr);
6236 /*-----------------------------------------------------------------*/
6237 /* genlshOne - left shift a one byte quantity by known count */
6238 /*-----------------------------------------------------------------*/
6240 genlshOne (operand * result, operand * left, int shCount)
6242 D(emitcode ("; genlshOne",""));
6244 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6247 /*-----------------------------------------------------------------*/
6248 /* genlshTwo - left shift two bytes by known amount != 0 */
6249 /*-----------------------------------------------------------------*/
6251 genlshTwo (operand * result, operand * left, int shCount)
6255 D(emitcode ("; genlshTwo",""));
6257 size = getDataSize (result);
6259 /* if shCount >= 8 */
6267 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6269 movLeft2Result (left, LSB, result, MSB16, 0);
6271 aopPut (AOP (result), zero, LSB);
6274 /* 1 <= shCount <= 7 */
6278 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6280 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6284 /*-----------------------------------------------------------------*/
6285 /* shiftLLong - shift left one long from left to result */
6286 /* offl = LSB or MSB16 */
6287 /*-----------------------------------------------------------------*/
6289 shiftLLong (operand * left, operand * result, int offr)
6292 int size = AOP_SIZE (result);
6294 if (size >= LSB + offr)
6296 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6298 emitcode ("add", "a,acc");
6299 if (sameRegs (AOP (left), AOP (result)) &&
6300 size >= MSB16 + offr && offr != LSB)
6301 emitcode ("xch", "a,%s",
6302 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6304 aopPut (AOP (result), "a", LSB + offr);
6307 if (size >= MSB16 + offr)
6309 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6311 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6314 emitcode ("rlc", "a");
6315 if (sameRegs (AOP (left), AOP (result)) &&
6316 size >= MSB24 + offr && offr != LSB)
6317 emitcode ("xch", "a,%s",
6318 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6320 aopPut (AOP (result), "a", MSB16 + offr);
6323 if (size >= MSB24 + offr)
6325 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6327 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6330 emitcode ("rlc", "a");
6331 if (sameRegs (AOP (left), AOP (result)) &&
6332 size >= MSB32 + offr && offr != LSB)
6333 emitcode ("xch", "a,%s",
6334 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6336 aopPut (AOP (result), "a", MSB24 + offr);
6339 if (size > MSB32 + offr)
6341 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6343 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6346 emitcode ("rlc", "a");
6347 aopPut (AOP (result), "a", MSB32 + offr);
6350 aopPut (AOP (result), zero, LSB);
6353 /*-----------------------------------------------------------------*/
6354 /* genlshFour - shift four byte by a known amount != 0 */
6355 /*-----------------------------------------------------------------*/
6357 genlshFour (operand * result, operand * left, int shCount)
6361 D(emitcode ("; genlshFour",""));
6363 size = AOP_SIZE (result);
6365 /* if shifting more that 3 bytes */
6370 /* lowest order of left goes to the highest
6371 order of the destination */
6372 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6374 movLeft2Result (left, LSB, result, MSB32, 0);
6375 aopPut (AOP (result), zero, LSB);
6376 aopPut (AOP (result), zero, MSB16);
6377 aopPut (AOP (result), zero, MSB24);
6381 /* more than two bytes */
6382 else if (shCount >= 16)
6384 /* lower order two bytes goes to higher order two bytes */
6386 /* if some more remaining */
6388 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6391 movLeft2Result (left, MSB16, result, MSB32, 0);
6392 movLeft2Result (left, LSB, result, MSB24, 0);
6394 aopPut (AOP (result), zero, MSB16);
6395 aopPut (AOP (result), zero, LSB);
6399 /* if more than 1 byte */
6400 else if (shCount >= 8)
6402 /* lower order three bytes goes to higher order three bytes */
6407 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6409 movLeft2Result (left, LSB, result, MSB16, 0);
6415 movLeft2Result (left, MSB24, result, MSB32, 0);
6416 movLeft2Result (left, MSB16, result, MSB24, 0);
6417 movLeft2Result (left, LSB, result, MSB16, 0);
6418 aopPut (AOP (result), zero, LSB);
6420 else if (shCount == 1)
6421 shiftLLong (left, result, MSB16);
6424 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6425 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6426 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6427 aopPut (AOP (result), zero, LSB);
6432 /* 1 <= shCount <= 7 */
6433 else if (shCount <= 2)
6435 shiftLLong (left, result, LSB);
6437 shiftLLong (result, result, LSB);
6439 /* 3 <= shCount <= 7, optimize */
6442 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6443 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6444 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6448 /*-----------------------------------------------------------------*/
6449 /* genLeftShiftLiteral - left shifting by known count */
6450 /*-----------------------------------------------------------------*/
6452 genLeftShiftLiteral (operand * left,
6457 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6460 D(emitcode ("; genLeftShiftLiteral",""));
6462 freeAsmop (right, NULL, ic, TRUE);
6464 aopOp (left, ic, FALSE);
6465 aopOp (result, ic, FALSE);
6467 size = getSize (operandType (result));
6470 emitcode ("; shift left ", "result %d, left %d", size,
6474 /* I suppose that the left size >= result size */
6479 movLeft2Result (left, size, result, size, 0);
6483 else if (shCount >= (size * 8))
6485 aopPut (AOP (result), zero, size);
6491 genlshOne (result, left, shCount);
6495 genlshTwo (result, left, shCount);
6499 genlshFour (result, left, shCount);
6502 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6503 "*** ack! mystery literal shift!\n");
6507 freeAsmop (left, NULL, ic, TRUE);
6508 freeAsmop (result, NULL, ic, TRUE);
6511 /*-----------------------------------------------------------------*/
6512 /* genLeftShift - generates code for left shifting */
6513 /*-----------------------------------------------------------------*/
6515 genLeftShift (iCode * ic)
6517 operand *left, *right, *result;
6520 symbol *tlbl, *tlbl1;
6522 D(emitcode ("; genLeftShift",""));
6524 right = IC_RIGHT (ic);
6525 left = IC_LEFT (ic);
6526 result = IC_RESULT (ic);
6528 aopOp (right, ic, FALSE);
6530 /* if the shift count is known then do it
6531 as efficiently as possible */
6532 if (AOP_TYPE (right) == AOP_LIT)
6534 genLeftShiftLiteral (left, right, result, ic);
6538 /* shift count is unknown then we have to form
6539 a loop get the loop count in B : Note: we take
6540 only the lower order byte since shifting
6541 more that 32 bits make no sense anyway, ( the
6542 largest size of an object can be only 32 bits ) */
6544 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6545 emitcode ("inc", "b");
6546 freeAsmop (right, NULL, ic, TRUE);
6547 aopOp (left, ic, FALSE);
6548 aopOp (result, ic, FALSE);
6550 /* now move the left to the result if they are not the
6552 if (!sameRegs (AOP (left), AOP (result)) &&
6553 AOP_SIZE (result) > 1)
6556 size = AOP_SIZE (result);
6560 l = aopGet (AOP (left), offset, FALSE, TRUE);
6561 if (*l == '@' && (IS_AOP_PREG (result)))
6564 emitcode ("mov", "a,%s", l);
6565 aopPut (AOP (result), "a", offset);
6568 aopPut (AOP (result), l, offset);
6573 tlbl = newiTempLabel (NULL);
6574 size = AOP_SIZE (result);
6576 tlbl1 = newiTempLabel (NULL);
6578 /* if it is only one byte then */
6581 symbol *tlbl1 = newiTempLabel (NULL);
6583 l = aopGet (AOP (left), 0, FALSE, FALSE);
6585 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6586 emitcode ("", "%05d$:", tlbl->key + 100);
6587 emitcode ("add", "a,acc");
6588 emitcode ("", "%05d$:", tlbl1->key + 100);
6589 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6590 aopPut (AOP (result), "a", 0);
6594 reAdjustPreg (AOP (result));
6596 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6597 emitcode ("", "%05d$:", tlbl->key + 100);
6598 l = aopGet (AOP (result), offset, FALSE, FALSE);
6600 emitcode ("add", "a,acc");
6601 aopPut (AOP (result), "a", offset++);
6604 l = aopGet (AOP (result), offset, FALSE, FALSE);
6606 emitcode ("rlc", "a");
6607 aopPut (AOP (result), "a", offset++);
6609 reAdjustPreg (AOP (result));
6611 emitcode ("", "%05d$:", tlbl1->key + 100);
6612 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6614 freeAsmop (left, NULL, ic, TRUE);
6615 freeAsmop (result, NULL, ic, TRUE);
6618 /*-----------------------------------------------------------------*/
6619 /* genrshOne - right shift a one byte quantity by known count */
6620 /*-----------------------------------------------------------------*/
6622 genrshOne (operand * result, operand * left,
6623 int shCount, int sign)
6625 D(emitcode ("; genrshOne",""));
6627 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6630 /*-----------------------------------------------------------------*/
6631 /* genrshTwo - right shift two bytes by known amount != 0 */
6632 /*-----------------------------------------------------------------*/
6634 genrshTwo (operand * result, operand * left,
6635 int shCount, int sign)
6637 D(emitcode ("; genrshTwo",""));
6639 /* if shCount >= 8 */
6644 shiftR1Left2Result (left, MSB16, result, LSB,
6647 movLeft2Result (left, MSB16, result, LSB, sign);
6648 addSign (result, MSB16, sign);
6651 /* 1 <= shCount <= 7 */
6653 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6656 /*-----------------------------------------------------------------*/
6657 /* shiftRLong - shift right one long from left to result */
6658 /* offl = LSB or MSB16 */
6659 /*-----------------------------------------------------------------*/
6661 shiftRLong (operand * left, int offl,
6662 operand * result, int sign)
6664 int isSameRegs=sameRegs(AOP(left),AOP(result));
6666 if (isSameRegs && offl>1) {
6667 // we are in big trouble, but this shouldn't happen
6668 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6671 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6676 emitcode ("rlc", "a");
6677 emitcode ("subb", "a,acc");
6679 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6681 aopPut (AOP (result), "a", MSB32);
6682 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6685 aopPut (AOP(result), zero, MSB32);
6690 emitcode ("clr", "c");
6692 emitcode ("mov", "c,acc.7");
6695 emitcode ("rrc", "a");
6697 if (isSameRegs && offl==MSB16) {
6698 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6700 aopPut (AOP (result), "a", MSB32-offl);
6701 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6704 emitcode ("rrc", "a");
6705 if (isSameRegs && offl==1) {
6706 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6708 aopPut (AOP (result), "a", MSB24-offl);
6709 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6711 emitcode ("rrc", "a");
6712 aopPut (AOP (result), "a", MSB16 - offl);
6716 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6717 emitcode ("rrc", "a");
6718 aopPut (AOP (result), "a", LSB);
6722 /*-----------------------------------------------------------------*/
6723 /* genrshFour - shift four byte by a known amount != 0 */
6724 /*-----------------------------------------------------------------*/
6726 genrshFour (operand * result, operand * left,
6727 int shCount, int sign)
6729 D(emitcode ("; genrshFour",""));
6731 /* if shifting more that 3 bytes */
6736 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6738 movLeft2Result (left, MSB32, result, LSB, sign);
6739 addSign (result, MSB16, sign);
6741 else if (shCount >= 16)
6745 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6748 movLeft2Result (left, MSB24, result, LSB, 0);
6749 movLeft2Result (left, MSB32, result, MSB16, sign);
6751 addSign (result, MSB24, sign);
6753 else if (shCount >= 8)
6757 shiftRLong (left, MSB16, result, sign);
6758 else if (shCount == 0)
6760 movLeft2Result (left, MSB16, result, LSB, 0);
6761 movLeft2Result (left, MSB24, result, MSB16, 0);
6762 movLeft2Result (left, MSB32, result, MSB24, sign);
6763 addSign (result, MSB32, sign);
6767 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6768 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6769 /* the last shift is signed */
6770 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6771 addSign (result, MSB32, sign);
6775 { /* 1 <= shCount <= 7 */
6778 shiftRLong (left, LSB, result, sign);
6780 shiftRLong (result, LSB, result, sign);
6784 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6785 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6786 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6791 /*-----------------------------------------------------------------*/
6792 /* genRightShiftLiteral - right shifting by known count */
6793 /*-----------------------------------------------------------------*/
6795 genRightShiftLiteral (operand * left,
6801 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6804 D(emitcode ("; genRightShiftLiteral",""));
6806 freeAsmop (right, NULL, ic, TRUE);
6808 aopOp (left, ic, FALSE);
6809 aopOp (result, ic, FALSE);
6812 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6816 size = getDataSize (left);
6817 /* test the LEFT size !!! */
6819 /* I suppose that the left size >= result size */
6822 size = getDataSize (result);
6824 movLeft2Result (left, size, result, size, 0);
6827 else if (shCount >= (size * 8))
6830 /* get sign in acc.7 */
6831 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6833 addSign (result, LSB, sign);
6834 freeAsmop (left, NULL, ic, TRUE);
6835 freeAsmop (result, NULL, ic, TRUE);
6842 genrshOne (result, left, shCount, sign);
6846 genrshTwo (result, left, shCount, sign);
6850 genrshFour (result, left, shCount, sign);
6856 freeAsmop (left, NULL, ic, TRUE);
6857 freeAsmop (result, NULL, ic, TRUE);
6861 /*-----------------------------------------------------------------*/
6862 /* genSignedRightShift - right shift of signed number */
6863 /*-----------------------------------------------------------------*/
6865 genSignedRightShift (iCode * ic)
6867 operand *right, *left, *result;
6870 symbol *tlbl, *tlbl1;
6872 D(emitcode ("; genSignedRightShift",""));
6874 /* we do it the hard way put the shift count in b
6875 and loop thru preserving the sign */
6877 right = IC_RIGHT (ic);
6878 left = IC_LEFT (ic);
6879 result = IC_RESULT (ic);
6881 aopOp (right, ic, FALSE);
6884 if (AOP_TYPE (right) == AOP_LIT)
6886 genRightShiftLiteral (left, right, result, ic, 1);
6889 /* shift count is unknown then we have to form
6890 a loop get the loop count in B : Note: we take
6891 only the lower order byte since shifting
6892 more that 32 bits make no sense anyway, ( the
6893 largest size of an object can be only 32 bits ) */
6895 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6896 emitcode ("inc", "b");
6897 freeAsmop (right, NULL, ic, TRUE);
6898 aopOp (left, ic, FALSE);
6899 aopOp (result, ic, FALSE);
6901 /* now move the left to the result if they are not the
6903 if (!sameRegs (AOP (left), AOP (result)) &&
6904 AOP_SIZE (result) > 1)
6907 size = AOP_SIZE (result);
6911 l = aopGet (AOP (left), offset, FALSE, TRUE);
6912 if (*l == '@' && IS_AOP_PREG (result))
6915 emitcode ("mov", "a,%s", l);
6916 aopPut (AOP (result), "a", offset);
6919 aopPut (AOP (result), l, offset);
6924 /* mov the highest order bit to OVR */
6925 tlbl = newiTempLabel (NULL);
6926 tlbl1 = newiTempLabel (NULL);
6928 size = AOP_SIZE (result);
6930 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6931 emitcode ("rlc", "a");
6932 emitcode ("mov", "ov,c");
6933 /* if it is only one byte then */
6936 l = aopGet (AOP (left), 0, FALSE, FALSE);
6938 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6939 emitcode ("", "%05d$:", tlbl->key + 100);
6940 emitcode ("mov", "c,ov");
6941 emitcode ("rrc", "a");
6942 emitcode ("", "%05d$:", tlbl1->key + 100);
6943 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6944 aopPut (AOP (result), "a", 0);
6948 reAdjustPreg (AOP (result));
6949 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6950 emitcode ("", "%05d$:", tlbl->key + 100);
6951 emitcode ("mov", "c,ov");
6954 l = aopGet (AOP (result), offset, FALSE, FALSE);
6956 emitcode ("rrc", "a");
6957 aopPut (AOP (result), "a", offset--);
6959 reAdjustPreg (AOP (result));
6960 emitcode ("", "%05d$:", tlbl1->key + 100);
6961 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6964 freeAsmop (left, NULL, ic, TRUE);
6965 freeAsmop (result, NULL, ic, TRUE);
6968 /*-----------------------------------------------------------------*/
6969 /* genRightShift - generate code for right shifting */
6970 /*-----------------------------------------------------------------*/
6972 genRightShift (iCode * ic)
6974 operand *right, *left, *result;
6978 symbol *tlbl, *tlbl1;
6980 D(emitcode ("; genRightShift",""));
6982 /* if signed then we do it the hard way preserve the
6983 sign bit moving it inwards */
6984 retype = getSpec (operandType (IC_RESULT (ic)));
6986 if (!SPEC_USIGN (retype))
6988 genSignedRightShift (ic);
6992 /* signed & unsigned types are treated the same : i.e. the
6993 signed is NOT propagated inwards : quoting from the
6994 ANSI - standard : "for E1 >> E2, is equivalent to division
6995 by 2**E2 if unsigned or if it has a non-negative value,
6996 otherwise the result is implementation defined ", MY definition
6997 is that the sign does not get propagated */
6999 right = IC_RIGHT (ic);
7000 left = IC_LEFT (ic);
7001 result = IC_RESULT (ic);
7003 aopOp (right, ic, FALSE);
7005 /* if the shift count is known then do it
7006 as efficiently as possible */
7007 if (AOP_TYPE (right) == AOP_LIT)
7009 genRightShiftLiteral (left, right, result, ic, 0);
7013 /* shift count is unknown then we have to form
7014 a loop get the loop count in B : Note: we take
7015 only the lower order byte since shifting
7016 more that 32 bits make no sense anyway, ( the
7017 largest size of an object can be only 32 bits ) */
7019 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7020 emitcode ("inc", "b");
7021 freeAsmop (right, NULL, ic, TRUE);
7022 aopOp (left, ic, FALSE);
7023 aopOp (result, ic, FALSE);
7025 /* now move the left to the result if they are not the
7027 if (!sameRegs (AOP (left), AOP (result)) &&
7028 AOP_SIZE (result) > 1)
7031 size = AOP_SIZE (result);
7035 l = aopGet (AOP (left), offset, FALSE, TRUE);
7036 if (*l == '@' && IS_AOP_PREG (result))
7039 emitcode ("mov", "a,%s", l);
7040 aopPut (AOP (result), "a", offset);
7043 aopPut (AOP (result), l, offset);
7048 tlbl = newiTempLabel (NULL);
7049 tlbl1 = newiTempLabel (NULL);
7050 size = AOP_SIZE (result);
7053 /* if it is only one byte then */
7056 l = aopGet (AOP (left), 0, FALSE, FALSE);
7058 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7059 emitcode ("", "%05d$:", tlbl->key + 100);
7061 emitcode ("rrc", "a");
7062 emitcode ("", "%05d$:", tlbl1->key + 100);
7063 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7064 aopPut (AOP (result), "a", 0);
7068 reAdjustPreg (AOP (result));
7069 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7070 emitcode ("", "%05d$:", tlbl->key + 100);
7074 l = aopGet (AOP (result), offset, FALSE, FALSE);
7076 emitcode ("rrc", "a");
7077 aopPut (AOP (result), "a", offset--);
7079 reAdjustPreg (AOP (result));
7081 emitcode ("", "%05d$:", tlbl1->key + 100);
7082 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7085 freeAsmop (left, NULL, ic, TRUE);
7086 freeAsmop (result, NULL, ic, TRUE);
7089 /*-----------------------------------------------------------------*/
7090 /* genUnpackBits - generates code for unpacking bits */
7091 /*-----------------------------------------------------------------*/
7093 genUnpackBits (operand * result, char *rname, int ptype)
7101 D(emitcode ("; genUnpackBits",""));
7103 etype = getSpec (operandType (result));
7104 rsize = getSize (operandType (result));
7105 /* read the first byte */
7111 emitcode ("mov", "a,@%s", rname);
7115 emitcode ("movx", "a,@%s", rname);
7119 emitcode ("movx", "a,@dptr");
7123 emitcode ("clr", "a");
7124 emitcode ("movc", "a,@a+dptr");
7128 emitcode ("lcall", "__gptrget");
7132 rlen = SPEC_BLEN (etype);
7134 /* if we have bitdisplacement then it fits */
7135 /* into this byte completely or if length is */
7136 /* less than a byte */
7137 if ((shCnt = SPEC_BSTR (etype)) ||
7138 (SPEC_BLEN (etype) <= 8))
7141 /* shift right acc */
7144 emitcode ("anl", "a,#0x%02x",
7145 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7146 aopPut (AOP (result), "a", offset++);
7150 /* bit field did not fit in a byte */
7151 aopPut (AOP (result), "a", offset++);
7160 emitcode ("inc", "%s", rname);
7161 emitcode ("mov", "a,@%s", rname);
7165 emitcode ("inc", "%s", rname);
7166 emitcode ("movx", "a,@%s", rname);
7170 emitcode ("inc", "dptr");
7171 emitcode ("movx", "a,@dptr");
7175 emitcode ("clr", "a");
7176 emitcode ("inc", "dptr");
7177 emitcode ("movc", "a,@a+dptr");
7181 emitcode ("inc", "dptr");
7182 emitcode ("lcall", "__gptrget");
7187 /* if we are done */
7191 aopPut (AOP (result), "a", offset++);
7197 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7199 aopPut (AOP (result), "a", offset++);
7207 aopPut (AOP (result), zero, offset++);
7213 /*-----------------------------------------------------------------*/
7214 /* genDataPointerGet - generates code when ptr offset is known */
7215 /*-----------------------------------------------------------------*/
7217 genDataPointerGet (operand * left,
7223 int size, offset = 0;
7225 D(emitcode ("; genDataPointerGet",""));
7227 aopOp (result, ic, TRUE);
7229 /* get the string representation of the name */
7230 l = aopGet (AOP (left), 0, FALSE, TRUE);
7231 size = AOP_SIZE (result);
7235 sprintf (buffer, "(%s + %d)", l + 1, offset);
7237 sprintf (buffer, "%s", l + 1);
7238 aopPut (AOP (result), buffer, offset++);
7241 freeAsmop (left, NULL, ic, TRUE);
7242 freeAsmop (result, NULL, ic, TRUE);
7245 /*-----------------------------------------------------------------*/
7246 /* genNearPointerGet - emitcode for near pointer fetch */
7247 /*-----------------------------------------------------------------*/
7249 genNearPointerGet (operand * left,
7257 sym_link *rtype, *retype;
7258 sym_link *ltype = operandType (left);
7261 D(emitcode ("; genNearPointerGet",""));
7263 rtype = operandType (result);
7264 retype = getSpec (rtype);
7266 aopOp (left, ic, FALSE);
7268 /* if left is rematerialisable and
7269 result is not bit variable type and
7270 the left is pointer to data space i.e
7271 lower 128 bytes of space */
7272 if (AOP_TYPE (left) == AOP_IMMD &&
7273 !IS_BITVAR (retype) &&
7274 DCL_TYPE (ltype) == POINTER)
7276 genDataPointerGet (left, result, ic);
7280 /* if the value is already in a pointer register
7281 then don't need anything more */
7282 if (!AOP_INPREG (AOP (left)))
7284 /* otherwise get a free pointer register */
7286 preg = getFreePtr (ic, &aop, FALSE);
7287 emitcode ("mov", "%s,%s",
7289 aopGet (AOP (left), 0, FALSE, TRUE));
7293 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7295 //aopOp (result, ic, FALSE);
7296 aopOp (result, ic, result?TRUE:FALSE);
7298 /* if bitfield then unpack the bits */
7299 if (IS_BITVAR (retype))
7300 genUnpackBits (result, rname, POINTER);
7303 /* we have can just get the values */
7304 int size = AOP_SIZE (result);
7309 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7312 emitcode ("mov", "a,@%s", rname);
7313 aopPut (AOP (result), "a", offset);
7317 sprintf (buffer, "@%s", rname);
7318 aopPut (AOP (result), buffer, offset);
7322 emitcode ("inc", "%s", rname);
7326 /* now some housekeeping stuff */
7327 if (aop) /* we had to allocate for this iCode */
7329 if (pi) { /* post increment present */
7330 aopPut(AOP ( left ),rname,0);
7332 freeAsmop (NULL, aop, ic, TRUE);
7336 /* we did not allocate which means left
7337 already in a pointer register, then
7338 if size > 0 && this could be used again
7339 we have to point it back to where it
7341 if ((AOP_SIZE (result) > 1 &&
7342 !OP_SYMBOL (left)->remat &&
7343 (OP_SYMBOL (left)->liveTo > ic->seq ||
7347 int size = AOP_SIZE (result) - 1;
7349 emitcode ("dec", "%s", rname);
7354 freeAsmop (left, NULL, ic, TRUE);
7355 freeAsmop (result, NULL, ic, TRUE);
7356 if (pi) pi->generated = 1;
7359 /*-----------------------------------------------------------------*/
7360 /* genPagedPointerGet - emitcode for paged pointer fetch */
7361 /*-----------------------------------------------------------------*/
7363 genPagedPointerGet (operand * left,
7371 sym_link *rtype, *retype;
7373 D(emitcode ("; genPagedPointerGet",""));
7375 rtype = operandType (result);
7376 retype = getSpec (rtype);
7378 aopOp (left, ic, FALSE);
7380 /* if the value is already in a pointer register
7381 then don't need anything more */
7382 if (!AOP_INPREG (AOP (left)))
7384 /* otherwise get a free pointer register */
7386 preg = getFreePtr (ic, &aop, FALSE);
7387 emitcode ("mov", "%s,%s",
7389 aopGet (AOP (left), 0, FALSE, TRUE));
7393 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7395 aopOp (result, ic, FALSE);
7397 /* if bitfield then unpack the bits */
7398 if (IS_BITVAR (retype))
7399 genUnpackBits (result, rname, PPOINTER);
7402 /* we have can just get the values */
7403 int size = AOP_SIZE (result);
7409 emitcode ("movx", "a,@%s", rname);
7410 aopPut (AOP (result), "a", offset);
7415 emitcode ("inc", "%s", rname);
7419 /* now some housekeeping stuff */
7420 if (aop) /* we had to allocate for this iCode */
7422 if (pi) aopPut ( AOP (left), rname, 0);
7423 freeAsmop (NULL, aop, ic, TRUE);
7427 /* we did not allocate which means left
7428 already in a pointer register, then
7429 if size > 0 && this could be used again
7430 we have to point it back to where it
7432 if ((AOP_SIZE (result) > 1 &&
7433 !OP_SYMBOL (left)->remat &&
7434 (OP_SYMBOL (left)->liveTo > ic->seq ||
7438 int size = AOP_SIZE (result) - 1;
7440 emitcode ("dec", "%s", rname);
7445 freeAsmop (left, NULL, ic, TRUE);
7446 freeAsmop (result, NULL, ic, TRUE);
7447 if (pi) pi->generated = 1;
7451 /*-----------------------------------------------------------------*/
7452 /* genFarPointerGet - gget value from far space */
7453 /*-----------------------------------------------------------------*/
7455 genFarPointerGet (operand * left,
7456 operand * result, iCode * ic, iCode * pi)
7459 sym_link *retype = getSpec (operandType (result));
7461 D(emitcode ("; genFarPointerGet",""));
7463 aopOp (left, ic, FALSE);
7465 /* if the operand is already in dptr
7466 then we do nothing else we move the value to dptr */
7467 if (AOP_TYPE (left) != AOP_STR)
7469 /* if this is remateriazable */
7470 if (AOP_TYPE (left) == AOP_IMMD)
7471 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7473 { /* we need to get it byte by byte */
7474 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7475 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7478 /* so dptr know contains the address */
7479 aopOp (result, ic, FALSE);
7481 /* if bit then unpack */
7482 if (IS_BITVAR (retype))
7483 genUnpackBits (result, "dptr", FPOINTER);
7486 size = AOP_SIZE (result);
7491 emitcode ("movx", "a,@dptr");
7492 aopPut (AOP (result), "a", offset++);
7494 emitcode ("inc", "dptr");
7498 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7499 aopPut ( AOP (left), "dpl", 0);
7500 aopPut ( AOP (left), "dph", 1);
7503 freeAsmop (left, NULL, ic, TRUE);
7504 freeAsmop (result, NULL, ic, TRUE);
7507 /*-----------------------------------------------------------------*/
7508 /* genCodePointerGet - gget value from code space */
7509 /*-----------------------------------------------------------------*/
7511 genCodePointerGet (operand * left,
7512 operand * result, iCode * ic, iCode *pi)
7515 sym_link *retype = getSpec (operandType (result));
7517 D(emitcode ("; genCodePointerGet",""));
7519 aopOp (left, ic, FALSE);
7521 /* if the operand is already in dptr
7522 then we do nothing else we move the value to dptr */
7523 if (AOP_TYPE (left) != AOP_STR)
7525 /* if this is remateriazable */
7526 if (AOP_TYPE (left) == AOP_IMMD)
7527 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7529 { /* we need to get it byte by byte */
7530 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7531 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7534 /* so dptr know contains the address */
7535 aopOp (result, ic, FALSE);
7537 /* if bit then unpack */
7538 if (IS_BITVAR (retype))
7539 genUnpackBits (result, "dptr", CPOINTER);
7542 size = AOP_SIZE (result);
7547 emitcode ("clr", "a");
7548 emitcode ("movc", "a,@a+dptr");
7549 aopPut (AOP (result), "a", offset++);
7551 emitcode ("inc", "dptr");
7555 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7556 aopPut ( AOP (left), "dpl", 0);
7557 aopPut ( AOP (left), "dph", 1);
7560 freeAsmop (left, NULL, ic, TRUE);
7561 freeAsmop (result, NULL, ic, TRUE);
7564 /*-----------------------------------------------------------------*/
7565 /* genGenPointerGet - gget value from generic pointer space */
7566 /*-----------------------------------------------------------------*/
7568 genGenPointerGet (operand * left,
7569 operand * result, iCode * ic, iCode *pi)
7572 sym_link *retype = getSpec (operandType (result));
7574 D(emitcode ("; genGenPointerGet",""));
7576 aopOp (left, ic, FALSE);
7578 /* if the operand is already in dptr
7579 then we do nothing else we move the value to dptr */
7580 if (AOP_TYPE (left) != AOP_STR)
7582 /* if this is remateriazable */
7583 if (AOP_TYPE (left) == AOP_IMMD)
7585 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7586 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7587 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7589 emitcode ("mov", "b,#%d", pointerCode (retype));
7592 { /* we need to get it byte by byte */
7593 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7594 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7595 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7598 /* so dptr know contains the address */
7599 aopOp (result, ic, FALSE);
7601 /* if bit then unpack */
7602 if (IS_BITVAR (retype))
7603 genUnpackBits (result, "dptr", GPOINTER);
7606 size = AOP_SIZE (result);
7611 emitcode ("lcall", "__gptrget");
7612 aopPut (AOP (result), "a", offset++);
7614 emitcode ("inc", "dptr");
7618 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7619 aopPut ( AOP (left), "dpl", 0);
7620 aopPut ( AOP (left), "dph", 1);
7621 aopPut ( AOP (left), "b", 2);
7624 freeAsmop (left, NULL, ic, TRUE);
7625 freeAsmop (result, NULL, ic, TRUE);
7628 /*-----------------------------------------------------------------*/
7629 /* genPointerGet - generate code for pointer get */
7630 /*-----------------------------------------------------------------*/
7632 genPointerGet (iCode * ic, iCode *pi)
7634 operand *left, *result;
7635 sym_link *type, *etype;
7638 D(emitcode ("; genPointerGet",""));
7640 left = IC_LEFT (ic);
7641 result = IC_RESULT (ic);
7643 /* depending on the type of pointer we need to
7644 move it to the correct pointer register */
7645 type = operandType (left);
7646 etype = getSpec (type);
7647 /* if left is of type of pointer then it is simple */
7648 if (IS_PTR (type) && !IS_FUNC (type->next))
7649 p_type = DCL_TYPE (type);
7652 /* we have to go by the storage class */
7653 p_type = PTR_TYPE (SPEC_OCLS (etype));
7656 /* special case when cast remat */
7657 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7658 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7659 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7660 type = operandType (left);
7661 p_type = DCL_TYPE (type);
7663 /* now that we have the pointer type we assign
7664 the pointer values */
7670 genNearPointerGet (left, result, ic, pi);
7674 genPagedPointerGet (left, result, ic, pi);
7678 genFarPointerGet (left, result, ic, pi);
7682 genCodePointerGet (left, result, ic, pi);
7686 genGenPointerGet (left, result, ic, pi);
7692 /*-----------------------------------------------------------------*/
7693 /* genPackBits - generates code for packed bit storage */
7694 /*-----------------------------------------------------------------*/
7696 genPackBits (sym_link * etype,
7698 char *rname, int p_type)
7706 D(emitcode ("; genPackBits",""));
7708 blen = SPEC_BLEN (etype);
7709 bstr = SPEC_BSTR (etype);
7711 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7714 /* if the bit lenth is less than or */
7715 /* it exactly fits a byte then */
7716 if (SPEC_BLEN (etype) <= 8)
7718 shCount = SPEC_BSTR (etype);
7720 /* shift left acc */
7723 if (SPEC_BLEN (etype) < 8)
7724 { /* if smaller than a byte */
7730 emitcode ("mov", "b,a");
7731 emitcode ("mov", "a,@%s", rname);
7735 emitcode ("mov", "b,a");
7736 emitcode ("movx", "a,@dptr");
7740 emitcode ("push", "b");
7741 emitcode ("push", "acc");
7742 emitcode ("lcall", "__gptrget");
7743 emitcode ("pop", "b");
7747 emitcode ("anl", "a,#0x%02x", (unsigned char)
7748 ((unsigned char) (0xFF << (blen + bstr)) |
7749 (unsigned char) (0xFF >> (8 - bstr))));
7750 emitcode ("orl", "a,b");
7751 if (p_type == GPOINTER)
7752 emitcode ("pop", "b");
7759 emitcode ("mov", "@%s,a", rname);
7763 emitcode ("movx", "@dptr,a");
7767 emitcode ("lcall", "__gptrput");
7772 if (SPEC_BLEN (etype) <= 8)
7775 emitcode ("inc", "%s", rname);
7776 rLen = SPEC_BLEN (etype);
7778 /* now generate for lengths greater than one byte */
7782 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7794 emitcode ("mov", "@%s,a", rname);
7797 emitcode ("mov", "@%s,%s", rname, l);
7802 emitcode ("movx", "@dptr,a");
7807 emitcode ("lcall", "__gptrput");
7810 emitcode ("inc", "%s", rname);
7815 /* last last was not complete */
7818 /* save the byte & read byte */
7822 emitcode ("mov", "b,a");
7823 emitcode ("mov", "a,@%s", rname);
7827 emitcode ("mov", "b,a");
7828 emitcode ("movx", "a,@dptr");
7832 emitcode ("push", "b");
7833 emitcode ("push", "acc");
7834 emitcode ("lcall", "__gptrget");
7835 emitcode ("pop", "b");
7839 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7840 emitcode ("orl", "a,b");
7843 if (p_type == GPOINTER)
7844 emitcode ("pop", "b");
7850 emitcode ("mov", "@%s,a", rname);
7854 emitcode ("movx", "@dptr,a");
7858 emitcode ("lcall", "__gptrput");
7862 /*-----------------------------------------------------------------*/
7863 /* genDataPointerSet - remat pointer to data space */
7864 /*-----------------------------------------------------------------*/
7866 genDataPointerSet (operand * right,
7870 int size, offset = 0;
7871 char *l, buffer[256];
7873 D(emitcode ("; genDataPointerSet",""));
7875 aopOp (right, ic, FALSE);
7877 l = aopGet (AOP (result), 0, FALSE, TRUE);
7878 size = AOP_SIZE (right);
7882 sprintf (buffer, "(%s + %d)", l + 1, offset);
7884 sprintf (buffer, "%s", l + 1);
7885 emitcode ("mov", "%s,%s", buffer,
7886 aopGet (AOP (right), offset++, FALSE, FALSE));
7889 freeAsmop (right, NULL, ic, TRUE);
7890 freeAsmop (result, NULL, ic, TRUE);
7893 /*-----------------------------------------------------------------*/
7894 /* genNearPointerSet - emitcode for near pointer put */
7895 /*-----------------------------------------------------------------*/
7897 genNearPointerSet (operand * right,
7905 sym_link *retype, *letype;
7906 sym_link *ptype = operandType (result);
7908 D(emitcode ("; genNearPointerSet",""));
7910 retype = getSpec (operandType (right));
7911 letype = getSpec (ptype);
7912 aopOp (result, ic, FALSE);
7914 /* if the result is rematerializable &
7915 in data space & not a bit variable */
7916 if (AOP_TYPE (result) == AOP_IMMD &&
7917 DCL_TYPE (ptype) == POINTER &&
7918 !IS_BITVAR (retype) &&
7919 !IS_BITVAR (letype))
7921 genDataPointerSet (right, result, ic);
7925 /* if the value is already in a pointer register
7926 then don't need anything more */
7927 if (!AOP_INPREG (AOP (result)))
7930 //AOP_TYPE (result) == AOP_STK
7934 // Aha, it is a pointer, just in disguise.
7935 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7938 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7939 __FILE__, __LINE__);
7944 rname++; // skip the '@'.
7949 /* otherwise get a free pointer register */
7951 preg = getFreePtr (ic, &aop, FALSE);
7952 emitcode ("mov", "%s,%s",
7954 aopGet (AOP (result), 0, FALSE, TRUE));
7960 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7963 aopOp (right, ic, FALSE);
7965 /* if bitfield then unpack the bits */
7966 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7967 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7970 /* we have can just get the values */
7971 int size = AOP_SIZE (right);
7976 l = aopGet (AOP (right), offset, FALSE, TRUE);
7980 emitcode ("mov", "@%s,a", rname);
7983 emitcode ("mov", "@%s,%s", rname, l);
7985 emitcode ("inc", "%s", rname);
7990 /* now some housekeeping stuff */
7991 if (aop) /* we had to allocate for this iCode */
7993 if (pi) aopPut (AOP (result),rname,0);
7994 freeAsmop (NULL, aop, ic, TRUE);
7998 /* we did not allocate which means left
7999 already in a pointer register, then
8000 if size > 0 && this could be used again
8001 we have to point it back to where it
8003 if ((AOP_SIZE (right) > 1 &&
8004 !OP_SYMBOL (result)->remat &&
8005 (OP_SYMBOL (result)->liveTo > ic->seq ||
8009 int size = AOP_SIZE (right) - 1;
8011 emitcode ("dec", "%s", rname);
8016 if (pi) pi->generated = 1;
8017 freeAsmop (result, NULL, ic, TRUE);
8018 freeAsmop (right, NULL, ic, TRUE);
8021 /*-----------------------------------------------------------------*/
8022 /* genPagedPointerSet - emitcode for Paged pointer put */
8023 /*-----------------------------------------------------------------*/
8025 genPagedPointerSet (operand * right,
8033 sym_link *retype, *letype;
8035 D(emitcode ("; genPagedPointerSet",""));
8037 retype = getSpec (operandType (right));
8038 letype = getSpec (operandType (result));
8040 aopOp (result, ic, FALSE);
8042 /* if the value is already in a pointer register
8043 then don't need anything more */
8044 if (!AOP_INPREG (AOP (result)))
8046 /* otherwise get a free pointer register */
8048 preg = getFreePtr (ic, &aop, FALSE);
8049 emitcode ("mov", "%s,%s",
8051 aopGet (AOP (result), 0, FALSE, TRUE));
8055 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8057 aopOp (right, ic, FALSE);
8059 /* if bitfield then unpack the bits */
8060 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8061 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8064 /* we have can just get the values */
8065 int size = AOP_SIZE (right);
8070 l = aopGet (AOP (right), offset, FALSE, TRUE);
8073 emitcode ("movx", "@%s,a", rname);
8076 emitcode ("inc", "%s", rname);
8082 /* now some housekeeping stuff */
8083 if (aop) /* we had to allocate for this iCode */
8085 if (pi) aopPut (AOP (result),rname,0);
8086 freeAsmop (NULL, aop, ic, TRUE);
8090 /* we did not allocate which means left
8091 already in a pointer register, then
8092 if size > 0 && this could be used again
8093 we have to point it back to where it
8095 if (AOP_SIZE (right) > 1 &&
8096 !OP_SYMBOL (result)->remat &&
8097 (OP_SYMBOL (result)->liveTo > ic->seq ||
8100 int size = AOP_SIZE (right) - 1;
8102 emitcode ("dec", "%s", rname);
8107 if (pi) pi->generated = 1;
8108 freeAsmop (result, NULL, ic, TRUE);
8109 freeAsmop (right, NULL, ic, TRUE);
8114 /*-----------------------------------------------------------------*/
8115 /* genFarPointerSet - set value from far space */
8116 /*-----------------------------------------------------------------*/
8118 genFarPointerSet (operand * right,
8119 operand * result, iCode * ic, iCode * pi)
8122 sym_link *retype = getSpec (operandType (right));
8123 sym_link *letype = getSpec (operandType (result));
8125 D(emitcode ("; genFarPointerSet",""));
8127 aopOp (result, ic, FALSE);
8129 /* if the operand is already in dptr
8130 then we do nothing else we move the value to dptr */
8131 if (AOP_TYPE (result) != AOP_STR)
8133 /* if this is remateriazable */
8134 if (AOP_TYPE (result) == AOP_IMMD)
8135 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8137 { /* we need to get it byte by byte */
8138 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8139 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8142 /* so dptr know contains the address */
8143 aopOp (right, ic, FALSE);
8145 /* if bit then unpack */
8146 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8147 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8150 size = AOP_SIZE (right);
8155 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8157 emitcode ("movx", "@dptr,a");
8159 emitcode ("inc", "dptr");
8162 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8163 aopPut (AOP(result),"dpl",0);
8164 aopPut (AOP(result),"dph",1);
8167 freeAsmop (result, NULL, ic, TRUE);
8168 freeAsmop (right, NULL, ic, TRUE);
8171 /*-----------------------------------------------------------------*/
8172 /* genGenPointerSet - set value from generic pointer space */
8173 /*-----------------------------------------------------------------*/
8175 genGenPointerSet (operand * right,
8176 operand * result, iCode * ic, iCode * pi)
8179 sym_link *retype = getSpec (operandType (right));
8180 sym_link *letype = getSpec (operandType (result));
8182 D(emitcode ("; genGenPointerSet",""));
8184 aopOp (result, ic, FALSE);
8186 /* if the operand is already in dptr
8187 then we do nothing else we move the value to dptr */
8188 if (AOP_TYPE (result) != AOP_STR)
8190 /* if this is remateriazable */
8191 if (AOP_TYPE (result) == AOP_IMMD)
8193 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8194 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8195 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8197 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8200 { /* we need to get it byte by byte */
8201 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8202 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8203 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8206 /* so dptr know contains the address */
8207 aopOp (right, ic, FALSE);
8209 /* if bit then unpack */
8210 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8211 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8214 size = AOP_SIZE (right);
8219 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8221 emitcode ("lcall", "__gptrput");
8223 emitcode ("inc", "dptr");
8227 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8228 aopPut (AOP(result),"dpl",0);
8229 aopPut (AOP(result),"dph",1);
8230 aopPut (AOP(result),"b",2);
8233 freeAsmop (result, NULL, ic, TRUE);
8234 freeAsmop (right, NULL, ic, TRUE);
8237 /*-----------------------------------------------------------------*/
8238 /* genPointerSet - stores the value into a pointer location */
8239 /*-----------------------------------------------------------------*/
8241 genPointerSet (iCode * ic, iCode *pi)
8243 operand *right, *result;
8244 sym_link *type, *etype;
8247 D(emitcode ("; genPointerSet",""));
8249 right = IC_RIGHT (ic);
8250 result = IC_RESULT (ic);
8252 /* depending on the type of pointer we need to
8253 move it to the correct pointer register */
8254 type = operandType (result);
8255 etype = getSpec (type);
8256 /* if left is of type of pointer then it is simple */
8257 if (IS_PTR (type) && !IS_FUNC (type->next))
8259 p_type = DCL_TYPE (type);
8263 /* we have to go by the storage class */
8264 p_type = PTR_TYPE (SPEC_OCLS (etype));
8267 /* special case when cast remat */
8268 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8269 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8270 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8271 type = operandType (result);
8272 p_type = DCL_TYPE (type);
8274 /* now that we have the pointer type we assign
8275 the pointer values */
8281 genNearPointerSet (right, result, ic, pi);
8285 genPagedPointerSet (right, result, ic, pi);
8289 genFarPointerSet (right, result, ic, pi);
8293 genGenPointerSet (right, result, ic, pi);
8297 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8298 "genPointerSet: illegal pointer type");
8303 /*-----------------------------------------------------------------*/
8304 /* genIfx - generate code for Ifx statement */
8305 /*-----------------------------------------------------------------*/
8307 genIfx (iCode * ic, iCode * popIc)
8309 operand *cond = IC_COND (ic);
8312 D(emitcode ("; genIfx",""));
8314 aopOp (cond, ic, FALSE);
8316 /* get the value into acc */
8317 if (AOP_TYPE (cond) != AOP_CRY)
8321 /* the result is now in the accumulator */
8322 freeAsmop (cond, NULL, ic, TRUE);
8324 /* if there was something to be popped then do it */
8328 /* if the condition is a bit variable */
8329 if (isbit && IS_ITEMP (cond) &&
8331 genIfxJump (ic, SPIL_LOC (cond)->rname);
8332 else if (isbit && !IS_ITEMP (cond))
8333 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8335 genIfxJump (ic, "a");
8340 /*-----------------------------------------------------------------*/
8341 /* genAddrOf - generates code for address of */
8342 /*-----------------------------------------------------------------*/
8344 genAddrOf (iCode * ic)
8346 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8349 D(emitcode ("; genAddrOf",""));
8351 aopOp (IC_RESULT (ic), ic, FALSE);
8353 /* if the operand is on the stack then we
8354 need to get the stack offset of this
8358 /* if it has an offset then we need to compute
8362 emitcode ("mov", "a,_bp");
8363 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8364 ((char) (sym->stack - _G.nRegsSaved)) :
8365 ((char) sym->stack)) & 0xff);
8366 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8370 /* we can just move _bp */
8371 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8373 /* fill the result with zero */
8374 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8379 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8385 /* object not on stack then we need the name */
8386 size = AOP_SIZE (IC_RESULT (ic));
8391 char s[SDCC_NAME_MAX];
8393 sprintf (s, "#(%s >> %d)",
8397 sprintf (s, "#%s", sym->rname);
8398 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8402 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8406 /*-----------------------------------------------------------------*/
8407 /* genFarFarAssign - assignment when both are in far space */
8408 /*-----------------------------------------------------------------*/
8410 genFarFarAssign (operand * result, operand * right, iCode * ic)
8412 int size = AOP_SIZE (right);
8416 D(emitcode ("; genFarFarAssign",""));
8418 /* first push the right side on to the stack */
8421 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8423 emitcode ("push", "acc");
8426 freeAsmop (right, NULL, ic, FALSE);
8427 /* now assign DPTR to result */
8428 aopOp (result, ic, FALSE);
8429 size = AOP_SIZE (result);
8432 emitcode ("pop", "acc");
8433 aopPut (AOP (result), "a", --offset);
8435 freeAsmop (result, NULL, ic, FALSE);
8439 /*-----------------------------------------------------------------*/
8440 /* genAssign - generate code for assignment */
8441 /*-----------------------------------------------------------------*/
8443 genAssign (iCode * ic)
8445 operand *result, *right;
8447 unsigned long lit = 0L;
8449 D(emitcode("; genAssign",""));
8451 result = IC_RESULT (ic);
8452 right = IC_RIGHT (ic);
8454 /* if they are the same */
8455 if (operandsEqu (result, right)) {
8459 aopOp (right, ic, FALSE);
8461 /* special case both in far space */
8462 if (AOP_TYPE (right) == AOP_DPTR &&
8463 IS_TRUE_SYMOP (result) &&
8464 isOperandInFarSpace (result))
8467 genFarFarAssign (result, right, ic);
8471 aopOp (result, ic, TRUE);
8473 /* if they are the same registers */
8474 if (sameRegs (AOP (right), AOP (result)))
8477 /* if the result is a bit */
8478 if (AOP_TYPE (result) == AOP_CRY)
8481 /* if the right size is a literal then
8482 we know what the value is */
8483 if (AOP_TYPE (right) == AOP_LIT)
8485 if (((int) operandLitValue (right)))
8486 aopPut (AOP (result), one, 0);
8488 aopPut (AOP (result), zero, 0);
8492 /* the right is also a bit variable */
8493 if (AOP_TYPE (right) == AOP_CRY)
8495 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8496 aopPut (AOP (result), "c", 0);
8502 aopPut (AOP (result), "a", 0);
8506 /* bit variables done */
8508 size = AOP_SIZE (result);
8510 if (AOP_TYPE (right) == AOP_LIT)
8511 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8513 (AOP_TYPE (result) != AOP_REG) &&
8514 (AOP_TYPE (right) == AOP_LIT) &&
8515 !IS_FLOAT (operandType (right)) &&
8518 emitcode ("clr", "a");
8521 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8522 aopPut (AOP (result), "a", size);
8524 aopPut (AOP (result),
8525 aopGet (AOP (right), size, FALSE, FALSE),
8533 aopPut (AOP (result),
8534 aopGet (AOP (right), offset, FALSE, FALSE),
8541 freeAsmop (right, NULL, ic, TRUE);
8542 freeAsmop (result, NULL, ic, TRUE);
8545 /*-----------------------------------------------------------------*/
8546 /* genJumpTab - genrates code for jump table */
8547 /*-----------------------------------------------------------------*/
8549 genJumpTab (iCode * ic)
8554 D(emitcode ("; genJumpTab",""));
8556 aopOp (IC_JTCOND (ic), ic, FALSE);
8557 /* get the condition into accumulator */
8558 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8560 /* multiply by three */
8561 emitcode ("add", "a,acc");
8562 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8563 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8565 jtab = newiTempLabel (NULL);
8566 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8567 emitcode ("jmp", "@a+dptr");
8568 emitcode ("", "%05d$:", jtab->key + 100);
8569 /* now generate the jump labels */
8570 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8571 jtab = setNextItem (IC_JTLABELS (ic)))
8572 emitcode ("ljmp", "%05d$", jtab->key + 100);
8576 /*-----------------------------------------------------------------*/
8577 /* genCast - gen code for casting */
8578 /*-----------------------------------------------------------------*/
8580 genCast (iCode * ic)
8582 operand *result = IC_RESULT (ic);
8583 sym_link *ctype = operandType (IC_LEFT (ic));
8584 sym_link *rtype = operandType (IC_RIGHT (ic));
8585 operand *right = IC_RIGHT (ic);
8588 D(emitcode("; genCast",""));
8590 /* if they are equivalent then do nothing */
8591 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8594 aopOp (right, ic, FALSE);
8595 aopOp (result, ic, FALSE);
8597 /* if the result is a bit */
8598 if (IS_BITVAR(OP_SYMBOL(result)->type))
8600 /* if the right size is a literal then
8601 we know what the value is */
8602 if (AOP_TYPE (right) == AOP_LIT)
8604 if (((int) operandLitValue (right)))
8605 aopPut (AOP (result), one, 0);
8607 aopPut (AOP (result), zero, 0);
8612 /* the right is also a bit variable */
8613 if (AOP_TYPE (right) == AOP_CRY)
8615 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8616 aopPut (AOP (result), "c", 0);
8622 aopPut (AOP (result), "a", 0);
8626 /* if they are the same size : or less */
8627 if (AOP_SIZE (result) <= AOP_SIZE (right))
8630 /* if they are in the same place */
8631 if (sameRegs (AOP (right), AOP (result)))
8634 /* if they in different places then copy */
8635 size = AOP_SIZE (result);
8639 aopPut (AOP (result),
8640 aopGet (AOP (right), offset, FALSE, FALSE),
8648 /* if the result is of type pointer */
8653 sym_link *type = operandType (right);
8654 sym_link *etype = getSpec (type);
8656 /* pointer to generic pointer */
8657 if (IS_GENPTR (ctype))
8660 p_type = DCL_TYPE (type);
8663 if (SPEC_SCLS(etype)==S_REGISTER) {
8664 // let's assume it is a generic pointer
8667 /* we have to go by the storage class */
8668 p_type = PTR_TYPE (SPEC_OCLS (etype));
8672 /* the first two bytes are known */
8673 size = GPTRSIZE - 1;
8677 aopPut (AOP (result),
8678 aopGet (AOP (right), offset, FALSE, FALSE),
8682 /* the last byte depending on type */
8684 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8689 // pointerTypeToGPByte will have bitched.
8693 sprintf(gpValStr, "#0x%d", gpVal);
8694 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8699 /* just copy the pointers */
8700 size = AOP_SIZE (result);
8704 aopPut (AOP (result),
8705 aopGet (AOP (right), offset, FALSE, FALSE),
8712 /* so we now know that the size of destination is greater
8713 than the size of the source */
8714 /* we move to result for the size of source */
8715 size = AOP_SIZE (right);
8719 aopPut (AOP (result),
8720 aopGet (AOP (right), offset, FALSE, FALSE),
8725 /* now depending on the sign of the source && destination */
8726 size = AOP_SIZE (result) - AOP_SIZE (right);
8727 /* if unsigned or not an integral type */
8728 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8731 aopPut (AOP (result), zero, offset++);
8735 /* we need to extend the sign :{ */
8736 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8739 emitcode ("rlc", "a");
8740 emitcode ("subb", "a,acc");
8742 aopPut (AOP (result), "a", offset++);
8745 /* we are done hurray !!!! */
8748 freeAsmop (right, NULL, ic, TRUE);
8749 freeAsmop (result, NULL, ic, TRUE);
8753 /*-----------------------------------------------------------------*/
8754 /* genDjnz - generate decrement & jump if not zero instrucion */
8755 /*-----------------------------------------------------------------*/
8757 genDjnz (iCode * ic, iCode * ifx)
8763 D(emitcode ("; genDjnz",""));
8765 /* if the if condition has a false label
8766 then we cannot save */
8770 /* if the minus is not of the form
8772 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8773 !IS_OP_LITERAL (IC_RIGHT (ic)))
8776 if (operandLitValue (IC_RIGHT (ic)) != 1)
8779 /* if the size of this greater than one then no
8781 if (getSize (operandType (IC_RESULT (ic))) > 1)
8784 /* otherwise we can save BIG */
8785 lbl = newiTempLabel (NULL);
8786 lbl1 = newiTempLabel (NULL);
8788 aopOp (IC_RESULT (ic), ic, FALSE);
8790 if (AOP_NEEDSACC(IC_RESULT(ic)))
8792 /* If the result is accessed indirectly via
8793 * the accumulator, we must explicitly write
8794 * it back after the decrement.
8796 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8798 if (strcmp(rByte, "a"))
8800 /* Something is hopelessly wrong */
8801 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8802 __FILE__, __LINE__);
8803 /* We can just give up; the generated code will be inefficient,
8806 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8809 emitcode ("dec", "%s", rByte);
8810 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8811 emitcode ("jnz", "%05d$", lbl->key + 100);
8813 else if (IS_AOP_PREG (IC_RESULT (ic)))
8815 emitcode ("dec", "%s",
8816 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8817 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8818 emitcode ("jnz", "%05d$", lbl->key + 100);
8822 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8825 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8826 emitcode ("", "%05d$:", lbl->key + 100);
8827 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8828 emitcode ("", "%05d$:", lbl1->key + 100);
8830 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8835 /*-----------------------------------------------------------------*/
8836 /* genReceive - generate code for a receive iCode */
8837 /*-----------------------------------------------------------------*/
8839 genReceive (iCode * ic)
8841 int size = getSize (operandType (IC_RESULT (ic)));
8843 D(emitcode ("; genReceive",""));
8845 if (ic->argreg == 1) { /* first parameter */
8846 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8847 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8848 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8850 offset = fReturnSizeMCS51 - size;
8852 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8853 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8856 aopOp (IC_RESULT (ic), ic, FALSE);
8857 size = AOP_SIZE (IC_RESULT (ic));
8860 emitcode ("pop", "acc");
8861 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8866 aopOp (IC_RESULT (ic), ic, FALSE);
8868 assignResultValue (IC_RESULT (ic));
8870 } else { /* second receive onwards */
8872 aopOp (IC_RESULT (ic), ic, FALSE);
8873 rb1off = ic->argreg;
8875 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
8878 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8881 /*-----------------------------------------------------------------*/
8882 /* gen51Code - generate code for 8051 based controllers */
8883 /*-----------------------------------------------------------------*/
8885 gen51Code (iCode * lic)
8890 lineHead = lineCurr = NULL;
8892 /* print the allocation information */
8894 printAllocInfo (currFunc, codeOutFile);
8895 /* if debug information required */
8896 if (options.debug && currFunc)
8898 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8900 if (IS_STATIC (currFunc->etype))
8901 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8903 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8906 /* stack pointer name */
8907 if (options.useXstack)
8913 for (ic = lic; ic; ic = ic->next)
8916 if (ic->lineno && cln != ic->lineno)
8921 emitcode ("", "C$%s$%d$%d$%d ==.",
8922 FileBaseName (ic->filename), ic->lineno,
8923 ic->level, ic->block);
8926 if (!options.noCcodeInAsm) {
8927 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8928 printCLine(ic->filename, ic->lineno));
8932 if (options.iCodeInAsm) {
8933 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
8935 /* if the result is marked as
8936 spilt and rematerializable or code for
8937 this has already been generated then
8939 if (resultRemat (ic) || ic->generated)
8942 /* depending on the operation */
8962 /* IPOP happens only when trying to restore a
8963 spilt live range, if there is an ifx statement
8964 following this pop then the if statement might
8965 be using some of the registers being popped which
8966 would destory the contents of the register so
8967 we need to check for this condition and handle it */
8969 ic->next->op == IFX &&
8970 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8971 genIfx (ic->next, ic);
8989 genEndFunction (ic);
9009 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9026 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9030 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9037 /* note these two are xlated by algebraic equivalence
9038 during parsing SDCC.y */
9039 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9040 "got '>=' or '<=' shouldn't have come here");
9044 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9056 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9060 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9064 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9091 case GET_VALUE_AT_ADDRESS:
9092 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9096 if (POINTER_SET (ic))
9097 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9123 addSet (&_G.sendSet, ic);
9132 /* now we are ready to call the
9133 peep hole optimizer */
9134 if (!options.nopeep)
9135 peepHole (&lineHead);
9137 /* now do the actual printing */
9138 printLine (lineHead, codeOutFile);