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 while (offset > aop->coff)
864 emitcode ("inc", "dptr");
868 while (offset < aop->coff)
870 emitcode ("lcall", "__decdptr");
877 emitcode ("clr", "a");
878 emitcode ("movc", "a,@a+dptr");
882 emitcode ("movx", "a,@dptr");
884 return (dname ? "acc" : "a");
888 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
889 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
891 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
893 sprintf (s, "#(%s >> %d)",
894 aop->aopu.aop_immd.aop_immd1,
898 aop->aopu.aop_immd.aop_immd1);
899 rs = Safe_calloc (1, strlen (s) + 1);
905 sprintf (s, "(%s + %d)",
909 sprintf (s, "%s", aop->aopu.aop_dir);
910 rs = Safe_calloc (1, strlen (s) + 1);
916 return aop->aopu.aop_reg[offset]->dname;
918 return aop->aopu.aop_reg[offset]->name;
921 emitcode ("clr", "a");
922 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
923 emitcode ("rlc", "a");
924 return (dname ? "acc" : "a");
927 if (!offset && dname)
929 return aop->aopu.aop_str[offset];
932 return aopLiteral (aop->aopu.aop_lit, offset);
936 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
940 return aop->aopu.aop_str[offset];
944 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
945 "aopget got unsupported aop->type");
948 /*-----------------------------------------------------------------*/
949 /* aopPut - puts a string for a aop */
950 /*-----------------------------------------------------------------*/
952 aopPut (asmop * aop, char *s, int offset)
956 if (aop->size && offset > (aop->size - 1))
958 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
959 "aopPut got offset > aop->size");
963 /* will assign value to value */
964 /* depending on where it is ofcourse */
969 sprintf (d, "(%s + %d)",
970 aop->aopu.aop_dir, offset);
972 sprintf (d, "%s", aop->aopu.aop_dir);
975 emitcode ("mov", "%s,%s", d, s);
980 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
981 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
984 strcmp (s, "r0") == 0 ||
985 strcmp (s, "r1") == 0 ||
986 strcmp (s, "r2") == 0 ||
987 strcmp (s, "r3") == 0 ||
988 strcmp (s, "r4") == 0 ||
989 strcmp (s, "r5") == 0 ||
990 strcmp (s, "r6") == 0 ||
991 strcmp (s, "r7") == 0)
992 emitcode ("mov", "%s,%s",
993 aop->aopu.aop_reg[offset]->dname, s);
995 emitcode ("mov", "%s,%s",
996 aop->aopu.aop_reg[offset]->name, s);
1003 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1004 "aopPut writting to code space");
1008 while (offset > aop->coff)
1011 emitcode ("inc", "dptr");
1014 while (offset < aop->coff)
1017 emitcode ("lcall", "__decdptr");
1022 /* if not in accumulater */
1025 emitcode ("movx", "@dptr,a");
1030 while (offset > aop->coff)
1033 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1035 while (offset < aop->coff)
1038 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1045 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1051 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1053 else if (strcmp (s, "r0") == 0 ||
1054 strcmp (s, "r1") == 0 ||
1055 strcmp (s, "r2") == 0 ||
1056 strcmp (s, "r3") == 0 ||
1057 strcmp (s, "r4") == 0 ||
1058 strcmp (s, "r5") == 0 ||
1059 strcmp (s, "r6") == 0 ||
1060 strcmp (s, "r7") == 0)
1063 sprintf (buffer, "a%s", s);
1064 emitcode ("mov", "@%s,%s",
1065 aop->aopu.aop_ptr->name, buffer);
1068 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1073 if (strcmp (s, "a") == 0)
1074 emitcode ("push", "acc");
1078 emitcode ("push", "acc");
1080 emitcode ("push", s);
1086 /* if bit variable */
1087 if (!aop->aopu.aop_dir)
1089 emitcode ("clr", "a");
1090 emitcode ("rlc", "a");
1095 emitcode ("clr", "%s", aop->aopu.aop_dir);
1097 emitcode ("setb", "%s", aop->aopu.aop_dir);
1098 else if (!strcmp (s, "c"))
1099 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1102 if (strcmp (s, "a"))
1107 /* set C, if a >= 1 */
1108 emitcode ("add", "a,#0xff");
1109 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1117 if (strcmp (aop->aopu.aop_str[offset], s))
1118 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1123 if (!offset && (strcmp (s, "acc") == 0))
1126 if (strcmp (aop->aopu.aop_str[offset], s))
1127 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1131 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1132 "aopPut got unsupported aop->type");
1140 /*-----------------------------------------------------------------*/
1141 /* pointToEnd :- points to the last byte of the operand */
1142 /*-----------------------------------------------------------------*/
1144 pointToEnd (asmop * aop)
1150 aop->coff = count = (aop->size - 1);
1156 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1160 emitcode ("inc", "dptr");
1167 /*-----------------------------------------------------------------*/
1168 /* reAdjustPreg - points a register back to where it should */
1169 /*-----------------------------------------------------------------*/
1171 reAdjustPreg (asmop * aop)
1173 if ((aop->coff==0) || aop->size <= 1)
1181 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1186 emitcode ("lcall", "__decdptr");
1193 #define AOP(op) op->aop
1194 #define AOP_TYPE(op) AOP(op)->type
1195 #define AOP_SIZE(op) AOP(op)->size
1196 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1197 AOP_TYPE(x) == AOP_R0))
1199 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1200 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1202 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1203 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1204 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1206 /*-----------------------------------------------------------------*/
1207 /* genNotFloat - generates not for float operations */
1208 /*-----------------------------------------------------------------*/
1210 genNotFloat (operand * op, operand * res)
1216 D(emitcode (";", "genNotFloat"));
1218 /* we will put 127 in the first byte of
1220 aopPut (AOP (res), "#127", 0);
1221 size = AOP_SIZE (op) - 1;
1224 l = aopGet (op->aop, offset++, FALSE, FALSE);
1229 emitcode ("orl", "a,%s",
1231 offset++, FALSE, FALSE));
1234 tlbl = newiTempLabel (NULL);
1235 aopPut (res->aop, one, 1);
1236 emitcode ("jz", "%05d$", (tlbl->key + 100));
1237 aopPut (res->aop, zero, 1);
1238 emitcode ("", "%05d$:", (tlbl->key + 100));
1240 size = res->aop->size - 2;
1242 /* put zeros in the rest */
1244 aopPut (res->aop, zero, offset++);
1247 /*-----------------------------------------------------------------*/
1248 /* opIsGptr: returns non-zero if the passed operand is */
1249 /* a generic pointer type. */
1250 /*-----------------------------------------------------------------*/
1252 opIsGptr (operand * op)
1254 sym_link *type = operandType (op);
1256 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1263 /*-----------------------------------------------------------------*/
1264 /* getDataSize - get the operand data size */
1265 /*-----------------------------------------------------------------*/
1267 getDataSize (operand * op)
1270 size = AOP_SIZE (op);
1271 if (size == GPTRSIZE)
1273 sym_link *type = operandType (op);
1274 if (IS_GENPTR (type))
1276 /* generic pointer; arithmetic operations
1277 * should ignore the high byte (pointer type).
1285 /*-----------------------------------------------------------------*/
1286 /* outAcc - output Acc */
1287 /*-----------------------------------------------------------------*/
1289 outAcc (operand * result)
1292 size = getDataSize (result);
1295 aopPut (AOP (result), "a", 0);
1298 /* unsigned or positive */
1301 aopPut (AOP (result), zero, offset++);
1306 /*-----------------------------------------------------------------*/
1307 /* outBitC - output a bit C */
1308 /*-----------------------------------------------------------------*/
1310 outBitC (operand * result)
1312 /* if the result is bit */
1313 if (AOP_TYPE (result) == AOP_CRY)
1314 aopPut (AOP (result), "c", 0);
1317 emitcode ("clr", "a");
1318 emitcode ("rlc", "a");
1323 /*-----------------------------------------------------------------*/
1324 /* toBoolean - emit code for orl a,operator(sizeop) */
1325 /*-----------------------------------------------------------------*/
1327 toBoolean (operand * oper)
1329 int size = AOP_SIZE (oper) - 1;
1331 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1333 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1337 /*-----------------------------------------------------------------*/
1338 /* genNot - generate code for ! operation */
1339 /*-----------------------------------------------------------------*/
1344 sym_link *optype = operandType (IC_LEFT (ic));
1346 D(emitcode (";", "genNot"));
1348 /* assign asmOps to operand & result */
1349 aopOp (IC_LEFT (ic), ic, FALSE);
1350 aopOp (IC_RESULT (ic), ic, TRUE);
1352 /* if in bit space then a special case */
1353 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1355 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1356 emitcode ("cpl", "c");
1357 outBitC (IC_RESULT (ic));
1361 /* if type float then do float */
1362 if (IS_FLOAT (optype))
1364 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1368 toBoolean (IC_LEFT (ic));
1370 tlbl = newiTempLabel (NULL);
1371 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1372 emitcode ("", "%05d$:", tlbl->key + 100);
1373 outBitC (IC_RESULT (ic));
1376 /* release the aops */
1377 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1378 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1382 /*-----------------------------------------------------------------*/
1383 /* genCpl - generate code for complement */
1384 /*-----------------------------------------------------------------*/
1392 D(emitcode (";", "genCpl"));
1394 /* assign asmOps to operand & result */
1395 aopOp (IC_LEFT (ic), ic, FALSE);
1396 aopOp (IC_RESULT (ic), ic, TRUE);
1398 /* special case if in bit space */
1399 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1400 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1401 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1402 emitcode ("cpl", "c");
1403 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1406 tlbl=newiTempLabel(NULL);
1407 emitcode ("cjne", "%s,#0x01,%05d$",
1408 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1409 emitcode ("", "%05d$:", tlbl->key+100);
1410 outBitC (IC_RESULT(ic));
1414 size = AOP_SIZE (IC_RESULT (ic));
1417 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1419 emitcode ("cpl", "a");
1420 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1425 /* release the aops */
1426 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1427 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1430 /*-----------------------------------------------------------------*/
1431 /* genUminusFloat - unary minus for floating points */
1432 /*-----------------------------------------------------------------*/
1434 genUminusFloat (operand * op, operand * result)
1436 int size, offset = 0;
1439 D(emitcode (";", "genUminusFloat"));
1441 /* for this we just need to flip the
1442 first it then copy the rest in place */
1443 size = AOP_SIZE (op) - 1;
1444 l = aopGet (AOP (op), 3, FALSE, FALSE);
1448 emitcode ("cpl", "acc.7");
1449 aopPut (AOP (result), "a", 3);
1453 aopPut (AOP (result),
1454 aopGet (AOP (op), offset, FALSE, FALSE),
1460 /*-----------------------------------------------------------------*/
1461 /* genUminus - unary minus code generation */
1462 /*-----------------------------------------------------------------*/
1464 genUminus (iCode * ic)
1467 sym_link *optype, *rtype;
1470 D(emitcode (";", "genUminus"));
1473 aopOp (IC_LEFT (ic), ic, FALSE);
1474 aopOp (IC_RESULT (ic), ic, TRUE);
1476 /* if both in bit space then special
1478 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1479 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1482 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1483 emitcode ("cpl", "c");
1484 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1488 optype = operandType (IC_LEFT (ic));
1489 rtype = operandType (IC_RESULT (ic));
1491 /* if float then do float stuff */
1492 if (IS_FLOAT (optype))
1494 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1498 /* otherwise subtract from zero */
1499 size = AOP_SIZE (IC_LEFT (ic));
1504 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1505 if (!strcmp (l, "a"))
1509 emitcode ("cpl", "a");
1510 emitcode ("addc", "a,#0");
1516 emitcode ("clr", "a");
1517 emitcode ("subb", "a,%s", l);
1519 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1522 /* if any remaining bytes in the result */
1523 /* we just need to propagate the sign */
1524 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1526 emitcode ("rlc", "a");
1527 emitcode ("subb", "a,acc");
1529 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1533 /* release the aops */
1534 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1535 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1538 /*-----------------------------------------------------------------*/
1539 /* saveRegisters - will look for a call and save the registers */
1540 /*-----------------------------------------------------------------*/
1542 saveRegisters (iCode * lic)
1549 for (ic = lic; ic; ic = ic->next)
1550 if (ic->op == CALL || ic->op == PCALL)
1555 fprintf (stderr, "found parameter push with no function call\n");
1559 /* if the registers have been saved already or don't need to be then
1561 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1562 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1565 /* safe the registers in use at this time but skip the
1566 ones for the result */
1567 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1568 mcs51_rUmaskForOp (IC_RESULT(ic)));
1571 if (options.useXstack)
1573 if (bitVectBitValue (rsave, R0_IDX))
1574 emitcode ("mov", "b,r0");
1575 emitcode ("mov", "r0,%s", spname);
1576 for (i = 0; i < mcs51_nRegs; i++)
1578 if (bitVectBitValue (rsave, i))
1581 emitcode ("mov", "a,b");
1583 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1584 emitcode ("movx", "@r0,a");
1585 emitcode ("inc", "r0");
1588 emitcode ("mov", "%s,r0", spname);
1589 if (bitVectBitValue (rsave, R0_IDX))
1590 emitcode ("mov", "r0,b");
1593 for (i = 0; i < mcs51_nRegs; i++)
1595 if (bitVectBitValue (rsave, i))
1596 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1600 /*-----------------------------------------------------------------*/
1601 /* unsaveRegisters - pop the pushed registers */
1602 /*-----------------------------------------------------------------*/
1604 unsaveRegisters (iCode * ic)
1609 /* restore the registers in use at this time but skip the
1610 ones for the result */
1611 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1612 mcs51_rUmaskForOp (IC_RESULT(ic)));
1614 if (options.useXstack)
1616 emitcode ("mov", "r0,%s", spname);
1617 for (i = mcs51_nRegs; i >= 0; i--)
1619 if (bitVectBitValue (rsave, i))
1621 emitcode ("dec", "r0");
1622 emitcode ("movx", "a,@r0");
1624 emitcode ("mov", "b,a");
1626 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1630 emitcode ("mov", "%s,r0", spname);
1631 if (bitVectBitValue (rsave, R0_IDX))
1632 emitcode ("mov", "r0,b");
1635 for (i = mcs51_nRegs; i >= 0; i--)
1637 if (bitVectBitValue (rsave, i))
1638 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1644 /*-----------------------------------------------------------------*/
1646 /*-----------------------------------------------------------------*/
1648 pushSide (operand * oper, int size)
1653 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1654 if (AOP_TYPE (oper) != AOP_REG &&
1655 AOP_TYPE (oper) != AOP_DIR &&
1658 emitcode ("mov", "a,%s", l);
1659 emitcode ("push", "acc");
1662 emitcode ("push", "%s", l);
1666 /*-----------------------------------------------------------------*/
1667 /* assignResultValue - */
1668 /*-----------------------------------------------------------------*/
1670 assignResultValue (operand * oper)
1673 int size = AOP_SIZE (oper);
1676 aopPut (AOP (oper), fReturn[offset], offset);
1682 /*-----------------------------------------------------------------*/
1683 /* genXpush - pushes onto the external stack */
1684 /*-----------------------------------------------------------------*/
1686 genXpush (iCode * ic)
1688 asmop *aop = newAsmop (0);
1690 int size, offset = 0;
1692 D(emitcode (";", "genXpush"));
1694 aopOp (IC_LEFT (ic), ic, FALSE);
1695 r = getFreePtr (ic, &aop, FALSE);
1698 emitcode ("mov", "%s,_spx", r->name);
1700 size = AOP_SIZE (IC_LEFT (ic));
1704 char *l = aopGet (AOP (IC_LEFT (ic)),
1705 offset++, FALSE, FALSE);
1707 emitcode ("movx", "@%s,a", r->name);
1708 emitcode ("inc", "%s", r->name);
1713 emitcode ("mov", "_spx,%s", r->name);
1715 freeAsmop (NULL, aop, ic, TRUE);
1716 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1719 /*-----------------------------------------------------------------*/
1720 /* genIpush - genrate code for pushing this gets a little complex */
1721 /*-----------------------------------------------------------------*/
1723 genIpush (iCode * ic)
1725 int size, offset = 0;
1728 D(emitcode (";", "genIpush"));
1730 /* if this is not a parm push : ie. it is spill push
1731 and spill push is always done on the local stack */
1735 /* and the item is spilt then do nothing */
1736 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1739 aopOp (IC_LEFT (ic), ic, FALSE);
1740 size = AOP_SIZE (IC_LEFT (ic));
1741 /* push it on the stack */
1744 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1750 emitcode ("push", "%s", l);
1755 /* this is a paramter push: in this case we call
1756 the routine to find the call and save those
1757 registers that need to be saved */
1760 /* if use external stack then call the external
1761 stack pushing routine */
1762 if (options.useXstack)
1768 /* then do the push */
1769 aopOp (IC_LEFT (ic), ic, FALSE);
1772 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1773 size = AOP_SIZE (IC_LEFT (ic));
1777 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1778 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1779 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1782 emitcode ("mov", "a,%s", l);
1783 emitcode ("push", "acc");
1786 emitcode ("push", "%s", l);
1789 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1792 /*-----------------------------------------------------------------*/
1793 /* genIpop - recover the registers: can happen only for spilling */
1794 /*-----------------------------------------------------------------*/
1796 genIpop (iCode * ic)
1800 D(emitcode (";", "genIpop"));
1802 /* if the temp was not pushed then */
1803 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1806 aopOp (IC_LEFT (ic), ic, FALSE);
1807 size = AOP_SIZE (IC_LEFT (ic));
1808 offset = (size - 1);
1810 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1813 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1816 /*-----------------------------------------------------------------*/
1817 /* unsaveRBank - restores the resgister bank from stack */
1818 /*-----------------------------------------------------------------*/
1820 unsaveRBank (int bank, iCode * ic, bool popPsw)
1826 if (options.useXstack)
1830 /* Assume r0 is available for use. */
1831 r = mcs51_regWithIdx (R0_IDX);;
1836 r = getFreePtr (ic, &aop, FALSE);
1838 emitcode ("mov", "%s,_spx", r->name);
1843 if (options.useXstack)
1845 emitcode ("movx", "a,@%s", r->name);
1846 emitcode ("mov", "psw,a");
1847 emitcode ("dec", "%s", r->name);
1851 emitcode ("pop", "psw");
1855 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1857 if (options.useXstack)
1859 emitcode ("movx", "a,@%s", r->name);
1860 emitcode ("mov", "(%s+%d),a",
1861 regs8051[i].base, 8 * bank + regs8051[i].offset);
1862 emitcode ("dec", "%s", r->name);
1866 emitcode ("pop", "(%s+%d)",
1867 regs8051[i].base, 8 * bank + regs8051[i].offset);
1870 if (options.useXstack)
1872 emitcode ("mov", "_spx,%s", r->name);
1877 freeAsmop (NULL, aop, ic, TRUE);
1881 /*-----------------------------------------------------------------*/
1882 /* saveRBank - saves an entire register bank on the stack */
1883 /*-----------------------------------------------------------------*/
1885 saveRBank (int bank, iCode * ic, bool pushPsw)
1891 if (options.useXstack)
1895 /* Assume r0 is available for use. */
1896 r = mcs51_regWithIdx (R0_IDX);;
1901 r = getFreePtr (ic, &aop, FALSE);
1903 emitcode ("mov", "%s,_spx", r->name);
1906 for (i = 0; i < mcs51_nRegs; i++)
1908 if (options.useXstack)
1910 emitcode ("inc", "%s", r->name);
1911 emitcode ("mov", "a,(%s+%d)",
1912 regs8051[i].base, 8 * bank + regs8051[i].offset);
1913 emitcode ("movx", "@%s,a", r->name);
1916 emitcode ("push", "(%s+%d)",
1917 regs8051[i].base, 8 * bank + regs8051[i].offset);
1922 if (options.useXstack)
1924 emitcode ("mov", "a,psw");
1925 emitcode ("movx", "@%s,a", r->name);
1926 emitcode ("inc", "%s", r->name);
1927 emitcode ("mov", "_spx,%s", r->name);
1932 emitcode ("push", "psw");
1935 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1940 freeAsmop (NULL, aop, ic, TRUE);
1949 /*-----------------------------------------------------------------*/
1950 /* genSend - gen code for SEND */
1951 /*-----------------------------------------------------------------*/
1952 static void genSend(set *sendSet)
1957 for (sic = setFirstItem (_G.sendSet); sic;
1958 sic = setNextItem (_G.sendSet)) {
1959 int size, offset = 0;
1960 aopOp (IC_LEFT (sic), sic, FALSE);
1961 size = AOP_SIZE (IC_LEFT (sic));
1963 if (sic->argreg == 1) {
1965 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1967 if (strcmp (l, fReturn[offset]))
1968 emitcode ("mov", "%s,%s", fReturn[offset], l);
1974 emitcode ("mov","b1_%d,%s",rb1_count++,
1975 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1978 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1982 /*-----------------------------------------------------------------*/
1983 /* genCall - generates a call statement */
1984 /*-----------------------------------------------------------------*/
1986 genCall (iCode * ic)
1989 // bool restoreBank = FALSE;
1990 bool swapBanks = FALSE;
1992 D(emitcode(";", "genCall"));
1994 dtype = operandType (IC_LEFT (ic));
1995 /* if send set is not empty the assign */
1998 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
1999 genSend(reverseSet(_G.sendSet));
2001 genSend(_G.sendSet);
2007 /* if we are calling a not _naked function that is not using
2008 the same register bank then we need to save the
2009 destination registers on the stack */
2010 dtype = operandType (IC_LEFT (ic));
2011 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2012 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2013 !IFFUNC_ISISR (dtype))
2018 /* if caller saves & we have not saved then */
2024 emitcode ("mov", "psw,#0x%02x",
2025 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2029 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2030 OP_SYMBOL (IC_LEFT (ic))->rname :
2031 OP_SYMBOL (IC_LEFT (ic))->name));
2035 emitcode ("mov", "psw,#0x%02x",
2036 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2039 /* if we need assign a result value */
2040 if ((IS_ITEMP (IC_RESULT (ic)) &&
2041 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2042 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2043 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2044 IS_TRUE_SYMOP (IC_RESULT (ic)))
2048 aopOp (IC_RESULT (ic), ic, FALSE);
2051 assignResultValue (IC_RESULT (ic));
2053 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2056 /* adjust the stack for parameters if
2061 if (ic->parmBytes > 3)
2063 emitcode ("mov", "a,%s", spname);
2064 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2065 emitcode ("mov", "%s,a", spname);
2068 for (i = 0; i < ic->parmBytes; i++)
2069 emitcode ("dec", "%s", spname);
2072 /* if we hade saved some registers then unsave them */
2073 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2074 unsaveRegisters (ic);
2076 // /* if register bank was saved then pop them */
2078 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2081 /*-----------------------------------------------------------------*/
2082 /* -10l - generates a call by pointer statement */
2083 /*-----------------------------------------------------------------*/
2085 genPcall (iCode * ic)
2088 symbol *rlbl = newiTempLabel (NULL);
2089 // bool restoreBank=FALSE;
2090 bool swapBanks = FALSE;
2092 D(emitcode(";", "genPCall"));
2094 /* if caller saves & we have not saved then */
2098 /* if we are calling a not _naked function that is not using
2099 the same register bank then we need to save the
2100 destination registers on the stack */
2101 dtype = operandType (IC_LEFT (ic))->next;
2102 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2103 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2104 !IFFUNC_ISISR (dtype))
2106 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2107 // restoreBank=TRUE;
2109 // need caution message to user here
2112 /* push the return address on to the stack */
2113 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2114 emitcode ("push", "acc");
2115 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2116 emitcode ("push", "acc");
2118 /* now push the calling address */
2119 aopOp (IC_LEFT (ic), ic, FALSE);
2121 pushSide (IC_LEFT (ic), FPTRSIZE);
2123 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2125 /* if send set is not empty the assign */
2128 genSend(reverseSet(_G.sendSet));
2134 emitcode ("mov", "psw,#0x%02x",
2135 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2139 emitcode ("ret", "");
2140 emitcode ("", "%05d$:", (rlbl->key + 100));
2145 emitcode ("mov", "psw,#0x%02x",
2146 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2149 /* if we need assign a result value */
2150 if ((IS_ITEMP (IC_RESULT (ic)) &&
2151 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2152 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2153 IS_TRUE_SYMOP (IC_RESULT (ic)))
2157 aopOp (IC_RESULT (ic), ic, FALSE);
2160 assignResultValue (IC_RESULT (ic));
2162 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2165 /* adjust the stack for parameters if
2170 if (ic->parmBytes > 3)
2172 emitcode ("mov", "a,%s", spname);
2173 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2174 emitcode ("mov", "%s,a", spname);
2177 for (i = 0; i < ic->parmBytes; i++)
2178 emitcode ("dec", "%s", spname);
2182 // /* if register bank was saved then unsave them */
2184 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2186 /* if we hade saved some registers then
2188 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2189 unsaveRegisters (ic);
2192 /*-----------------------------------------------------------------*/
2193 /* resultRemat - result is rematerializable */
2194 /*-----------------------------------------------------------------*/
2196 resultRemat (iCode * ic)
2198 if (SKIP_IC (ic) || ic->op == IFX)
2201 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2203 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2204 if (sym->remat && !POINTER_SET (ic))
2211 #if defined(__BORLANDC__) || defined(_MSC_VER)
2212 #define STRCASECMP stricmp
2214 #define STRCASECMP strcasecmp
2217 /*-----------------------------------------------------------------*/
2218 /* inExcludeList - return 1 if the string is in exclude Reg list */
2219 /*-----------------------------------------------------------------*/
2221 inExcludeList (char *s)
2225 if (options.excludeRegs[i] &&
2226 STRCASECMP (options.excludeRegs[i], "none") == 0)
2229 for (i = 0; options.excludeRegs[i]; i++)
2231 if (options.excludeRegs[i] &&
2232 STRCASECMP (s, options.excludeRegs[i]) == 0)
2238 /*-----------------------------------------------------------------*/
2239 /* genFunction - generated code for function entry */
2240 /*-----------------------------------------------------------------*/
2242 genFunction (iCode * ic)
2246 bool switchedPSW = FALSE;
2247 int calleesaves_saved_register = -1;
2250 /* create the function header */
2251 emitcode (";", "-----------------------------------------");
2252 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2253 emitcode (";", "-----------------------------------------");
2255 emitcode ("", "%s:", sym->rname);
2256 ftype = operandType (IC_LEFT (ic));
2258 if (IFFUNC_ISNAKED(ftype))
2260 emitcode(";", "naked function: no prologue.");
2264 /* if critical function then turn interrupts off */
2265 if (IFFUNC_ISCRITICAL (ftype))
2266 emitcode ("clr", "ea");
2268 /* here we need to generate the equates for the
2269 register bank if required */
2270 if (FUNC_REGBANK (ftype) != rbank)
2274 rbank = FUNC_REGBANK (ftype);
2275 for (i = 0; i < mcs51_nRegs; i++)
2277 if (strcmp (regs8051[i].base, "0") == 0)
2278 emitcode ("", "%s = 0x%02x",
2280 8 * rbank + regs8051[i].offset);
2282 emitcode ("", "%s = %s + 0x%02x",
2285 8 * rbank + regs8051[i].offset);
2289 /* if this is an interrupt service routine then
2290 save acc, b, dpl, dph */
2291 if (IFFUNC_ISISR (sym->type))
2294 if (!inExcludeList ("acc"))
2295 emitcode ("push", "acc");
2296 if (!inExcludeList ("b"))
2297 emitcode ("push", "b");
2298 if (!inExcludeList ("dpl"))
2299 emitcode ("push", "dpl");
2300 if (!inExcludeList ("dph"))
2301 emitcode ("push", "dph");
2302 /* if this isr has no bank i.e. is going to
2303 run with bank 0 , then we need to save more
2305 if (!FUNC_REGBANK (sym->type))
2308 /* if this function does not call any other
2309 function then we can be economical and
2310 save only those registers that are used */
2311 if (!IFFUNC_HASFCALL(sym->type))
2315 /* if any registers used */
2318 /* save the registers used */
2319 for (i = 0; i < sym->regsUsed->size; i++)
2321 if (bitVectBitValue (sym->regsUsed, i) ||
2322 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2323 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2331 /* this function has a function call cannot
2332 determines register usage so we will have to push the
2334 saveRBank (0, ic, FALSE);
2335 if (options.parms_in_bank1) {
2337 for (i=0; i < 8 ; i++ ) {
2338 emitcode ("push","%s",rb1regs[i]);
2345 /* This ISR uses a non-zero bank.
2347 * We assume that the bank is available for our
2350 * However, if this ISR calls a function which uses some
2351 * other bank, we must save that bank entirely.
2353 unsigned long banksToSave = 0;
2355 if (IFFUNC_HASFCALL(sym->type))
2358 #define MAX_REGISTER_BANKS 4
2363 for (i = ic; i; i = i->next)
2365 if (i->op == ENDFUNCTION)
2367 /* we got to the end OK. */
2375 dtype = operandType (IC_LEFT(i));
2377 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2379 /* Mark this bank for saving. */
2380 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2382 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2386 banksToSave |= (1 << FUNC_REGBANK(dtype));
2389 /* And note that we don't need to do it in
2397 /* This is a mess; we have no idea what
2398 * register bank the called function might
2401 * The only thing I can think of to do is
2402 * throw a warning and hope.
2404 werror(W_FUNCPTR_IN_USING_ISR);
2408 if (banksToSave && options.useXstack)
2410 /* Since we aren't passing it an ic,
2411 * saveRBank will assume r0 is available to abuse.
2413 * So switch to our (trashable) bank now, so
2414 * the caller's R0 isn't trashed.
2416 emitcode ("push", "psw");
2417 emitcode ("mov", "psw,#0x%02x",
2418 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2422 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2424 if (banksToSave & (1 << ix))
2426 saveRBank(ix, NULL, FALSE);
2430 // jwk: this needs a closer look
2431 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2436 /* if callee-save to be used for this function
2437 then save the registers being used in this function */
2438 if (IFFUNC_CALLEESAVES(sym->type))
2442 /* if any registers used */
2445 /* save the registers used */
2446 for (i = 0; i < sym->regsUsed->size; i++)
2448 if (bitVectBitValue (sym->regsUsed, i) ||
2449 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2451 /* remember one saved register for later usage */
2452 if (calleesaves_saved_register < 0)
2453 calleesaves_saved_register = i;
2454 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2462 /* set the register bank to the desired value */
2463 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2466 emitcode ("push", "psw");
2467 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2470 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2473 if (options.useXstack)
2475 emitcode ("mov", "r0,%s", spname);
2476 emitcode ("mov", "a,_bp");
2477 emitcode ("movx", "@r0,a");
2478 emitcode ("inc", "%s", spname);
2482 /* set up the stack */
2483 emitcode ("push", "_bp"); /* save the callers stack */
2485 emitcode ("mov", "_bp,%s", spname);
2488 /* adjust the stack for the function */
2494 werror (W_STACK_OVERFLOW, sym->name);
2496 if (i > 3 && sym->recvSize < 4)
2499 emitcode ("mov", "a,sp");
2500 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2501 emitcode ("mov", "sp,a");
2506 if (IFFUNC_CALLEESAVES(sym->type))
2508 /* if it's a callee-saves function we need a saved register */
2509 if (calleesaves_saved_register >= 0)
2511 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2512 emitcode ("mov", "a,sp");
2513 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2514 emitcode ("mov", "sp,a");
2515 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2518 /* do it the hard way */
2520 emitcode ("inc", "sp");
2524 /* not callee-saves, we can clobber r0 */
2525 emitcode ("mov", "r0,a");
2526 emitcode ("mov", "a,sp");
2527 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2528 emitcode ("mov", "sp,a");
2529 emitcode ("mov", "a,r0");
2534 emitcode ("inc", "sp");
2540 emitcode ("mov", "a,_spx");
2541 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2542 emitcode ("mov", "_spx,a");
2547 /*-----------------------------------------------------------------*/
2548 /* genEndFunction - generates epilogue for functions */
2549 /*-----------------------------------------------------------------*/
2551 genEndFunction (iCode * ic)
2553 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2555 if (IFFUNC_ISNAKED(sym->type))
2557 emitcode(";", "naked function: no epilogue.");
2561 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2563 emitcode ("mov", "%s,_bp", spname);
2566 /* if use external stack but some variables were
2567 added to the local stack then decrement the
2569 if (options.useXstack && sym->stack)
2571 emitcode ("mov", "a,sp");
2572 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2573 emitcode ("mov", "sp,a");
2577 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2579 if (options.useXstack)
2581 emitcode ("mov", "r0,%s", spname);
2582 emitcode ("movx", "a,@r0");
2583 emitcode ("mov", "_bp,a");
2584 emitcode ("dec", "%s", spname);
2588 emitcode ("pop", "_bp");
2592 /* restore the register bank */
2593 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2595 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2596 || !options.useXstack)
2598 /* Special case of ISR using non-zero bank with useXstack
2601 emitcode ("pop", "psw");
2605 if (IFFUNC_ISISR (sym->type))
2608 /* now we need to restore the registers */
2609 /* if this isr has no bank i.e. is going to
2610 run with bank 0 , then we need to save more
2612 if (!FUNC_REGBANK (sym->type))
2614 /* if this function does not call any other
2615 function then we can be economical and
2616 save only those registers that are used */
2617 if (!IFFUNC_HASFCALL(sym->type))
2621 /* if any registers used */
2624 /* save the registers used */
2625 for (i = sym->regsUsed->size; i >= 0; i--)
2627 if (bitVectBitValue (sym->regsUsed, i) ||
2628 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2629 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2636 if (options.parms_in_bank1) {
2638 for (i = 7 ; i >= 0 ; i-- ) {
2639 emitcode ("pop","%s",rb1regs[i]);
2642 /* this function has a function call cannot
2643 determines register usage so we will have to pop the
2645 unsaveRBank (0, ic, FALSE);
2650 /* This ISR uses a non-zero bank.
2652 * Restore any register banks saved by genFunction
2655 // jwk: this needs a closer look
2656 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2659 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2661 if (savedBanks & (1 << ix))
2663 unsaveRBank(ix, NULL, FALSE);
2667 if (options.useXstack)
2669 /* Restore bank AFTER calling unsaveRBank,
2670 * since it can trash r0.
2672 emitcode ("pop", "psw");
2676 if (!inExcludeList ("dph"))
2677 emitcode ("pop", "dph");
2678 if (!inExcludeList ("dpl"))
2679 emitcode ("pop", "dpl");
2680 if (!inExcludeList ("b"))
2681 emitcode ("pop", "b");
2682 if (!inExcludeList ("acc"))
2683 emitcode ("pop", "acc");
2685 if (IFFUNC_ISCRITICAL (sym->type))
2686 emitcode ("setb", "ea");
2688 /* if debug then send end of function */
2689 if (options.debug && currFunc)
2692 emitcode ("", "C$%s$%d$%d$%d ==.",
2693 FileBaseName (ic->filename), currFunc->lastLine,
2694 ic->level, ic->block);
2695 if (IS_STATIC (currFunc->etype))
2696 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2698 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2702 emitcode ("reti", "");
2706 if (IFFUNC_ISCRITICAL (sym->type))
2707 emitcode ("setb", "ea");
2709 if (IFFUNC_CALLEESAVES(sym->type))
2713 /* if any registers used */
2716 /* save the registers used */
2717 for (i = sym->regsUsed->size; i >= 0; i--)
2719 if (bitVectBitValue (sym->regsUsed, i) ||
2720 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2721 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2727 /* if debug then send end of function */
2728 if (options.debug && currFunc)
2731 emitcode ("", "C$%s$%d$%d$%d ==.",
2732 FileBaseName (ic->filename), currFunc->lastLine,
2733 ic->level, ic->block);
2734 if (IS_STATIC (currFunc->etype))
2735 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2737 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2741 emitcode ("ret", "");
2746 /*-----------------------------------------------------------------*/
2747 /* genRet - generate code for return statement */
2748 /*-----------------------------------------------------------------*/
2752 int size, offset = 0, pushed = 0;
2754 D(emitcode (";", "genRet"));
2756 /* if we have no return value then
2757 just generate the "ret" */
2761 /* we have something to return then
2762 move the return value into place */
2763 aopOp (IC_LEFT (ic), ic, FALSE);
2764 size = AOP_SIZE (IC_LEFT (ic));
2769 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2772 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2774 emitcode ("push", "%s", l);
2779 l = aopGet (AOP (IC_LEFT (ic)), offset,
2781 if (strcmp (fReturn[offset], l))
2782 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2791 if (strcmp (fReturn[pushed], "a"))
2792 emitcode ("pop", fReturn[pushed]);
2794 emitcode ("pop", "acc");
2797 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2800 /* generate a jump to the return label
2801 if the next is not the return statement */
2802 if (!(ic->next && ic->next->op == LABEL &&
2803 IC_LABEL (ic->next) == returnLabel))
2805 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2809 /*-----------------------------------------------------------------*/
2810 /* genLabel - generates a label */
2811 /*-----------------------------------------------------------------*/
2813 genLabel (iCode * ic)
2815 /* special case never generate */
2816 if (IC_LABEL (ic) == entryLabel)
2819 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2822 /*-----------------------------------------------------------------*/
2823 /* genGoto - generates a ljmp */
2824 /*-----------------------------------------------------------------*/
2826 genGoto (iCode * ic)
2828 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2831 /*-----------------------------------------------------------------*/
2832 /* findLabelBackwards: walks back through the iCode chain looking */
2833 /* for the given label. Returns number of iCode instructions */
2834 /* between that label and given ic. */
2835 /* Returns zero if label not found. */
2836 /*-----------------------------------------------------------------*/
2838 findLabelBackwards (iCode * ic, int key)
2847 /* If we have any pushes or pops, we cannot predict the distance.
2848 I don't like this at all, this should be dealt with in the
2850 if (ic->op == IPUSH || ic->op == IPOP) {
2854 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2863 /*-----------------------------------------------------------------*/
2864 /* genPlusIncr :- does addition with increment if possible */
2865 /*-----------------------------------------------------------------*/
2867 genPlusIncr (iCode * ic)
2869 unsigned int icount;
2870 unsigned int size = getDataSize (IC_RESULT (ic));
2872 /* will try to generate an increment */
2873 /* if the right side is not a literal
2875 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2878 /* if the literal value of the right hand side
2879 is greater than 4 then it is not worth it */
2880 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2883 D(emitcode (";", "genPlusIncr"));
2885 /* if increment 16 bits in register */
2886 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
2887 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2895 /* If the next instruction is a goto and the goto target
2896 * is < 10 instructions previous to this, we can generate
2897 * jumps straight to that target.
2899 if (ic->next && ic->next->op == GOTO
2900 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2901 && labelRange <= 10)
2903 emitcode (";", "tail increment optimized");
2904 tlbl = IC_LABEL (ic->next);
2909 tlbl = newiTempLabel (NULL);
2912 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2913 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2914 IS_AOP_PREG (IC_RESULT (ic)))
2915 emitcode ("cjne", "%s,#0x00,%05d$",
2916 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2920 emitcode ("clr", "a");
2921 emitcode ("cjne", "a,%s,%05d$",
2922 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2926 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2929 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2930 IS_AOP_PREG (IC_RESULT (ic)))
2931 emitcode ("cjne", "%s,#0x00,%05d$",
2932 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2935 emitcode ("cjne", "a,%s,%05d$",
2936 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2939 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2943 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2944 IS_AOP_PREG (IC_RESULT (ic)))
2945 emitcode ("cjne", "%s,#0x00,%05d$",
2946 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2950 emitcode ("cjne", "a,%s,%05d$",
2951 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2954 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2959 emitcode ("", "%05d$:", tlbl->key + 100);
2964 /* if the sizes are greater than 1 then we cannot */
2965 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2966 AOP_SIZE (IC_LEFT (ic)) > 1)
2969 /* we can if the aops of the left & result match or
2970 if they are in registers and the registers are the
2972 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2977 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2978 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2979 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2985 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2994 /*-----------------------------------------------------------------*/
2995 /* outBitAcc - output a bit in acc */
2996 /*-----------------------------------------------------------------*/
2998 outBitAcc (operand * result)
3000 symbol *tlbl = newiTempLabel (NULL);
3001 /* if the result is a bit */
3002 if (AOP_TYPE (result) == AOP_CRY)
3004 aopPut (AOP (result), "a", 0);
3008 emitcode ("jz", "%05d$", tlbl->key + 100);
3009 emitcode ("mov", "a,%s", one);
3010 emitcode ("", "%05d$:", tlbl->key + 100);
3015 /*-----------------------------------------------------------------*/
3016 /* genPlusBits - generates code for addition of two bits */
3017 /*-----------------------------------------------------------------*/
3019 genPlusBits (iCode * ic)
3021 D(emitcode (";", "genPlusBits"));
3023 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3025 symbol *lbl = newiTempLabel (NULL);
3026 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3027 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3028 emitcode ("cpl", "c");
3029 emitcode ("", "%05d$:", (lbl->key + 100));
3030 outBitC (IC_RESULT (ic));
3034 emitcode ("clr", "a");
3035 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3036 emitcode ("rlc", "a");
3037 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3038 emitcode ("addc", "a,#0x00");
3039 outAcc (IC_RESULT (ic));
3044 /* This is the original version of this code.
3046 * This is being kept around for reference,
3047 * because I am not entirely sure I got it right...
3050 adjustArithmeticResult (iCode * ic)
3052 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3053 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3054 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3055 aopPut (AOP (IC_RESULT (ic)),
3056 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3059 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3060 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3061 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3062 aopPut (AOP (IC_RESULT (ic)),
3063 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3066 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3067 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3068 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3069 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3070 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3073 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3074 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
3078 /* This is the pure and virtuous version of this code.
3079 * I'm pretty certain it's right, but not enough to toss the old
3083 adjustArithmeticResult (iCode * ic)
3085 if (opIsGptr (IC_RESULT (ic)) &&
3086 opIsGptr (IC_LEFT (ic)) &&
3087 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3089 aopPut (AOP (IC_RESULT (ic)),
3090 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3094 if (opIsGptr (IC_RESULT (ic)) &&
3095 opIsGptr (IC_RIGHT (ic)) &&
3096 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3098 aopPut (AOP (IC_RESULT (ic)),
3099 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3103 if (opIsGptr (IC_RESULT (ic)) &&
3104 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3105 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3106 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3107 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3110 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3111 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
3116 /*-----------------------------------------------------------------*/
3117 /* genPlus - generates code for addition */
3118 /*-----------------------------------------------------------------*/
3120 genPlus (iCode * ic)
3122 int size, offset = 0;
3124 asmop *leftOp, *rightOp;
3126 /* special cases :- */
3128 D(emitcode (";", "genPlus"));
3130 aopOp (IC_LEFT (ic), ic, FALSE);
3131 aopOp (IC_RIGHT (ic), ic, FALSE);
3132 aopOp (IC_RESULT (ic), ic, TRUE);
3134 /* if literal, literal on the right or
3135 if left requires ACC or right is already
3137 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3138 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3139 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3141 operand *t = IC_RIGHT (ic);
3142 IC_RIGHT (ic) = IC_LEFT (ic);
3146 /* if both left & right are in bit
3148 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3149 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3155 /* if left in bit space & right literal */
3156 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3157 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3159 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3160 /* if result in bit space */
3161 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3163 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3164 emitcode ("cpl", "c");
3165 outBitC (IC_RESULT (ic));
3169 size = getDataSize (IC_RESULT (ic));
3172 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3173 emitcode ("addc", "a,#00");
3174 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3180 /* if I can do an increment instead
3181 of add then GOOD for ME */
3182 if (genPlusIncr (ic) == TRUE)
3185 size = getDataSize (IC_RESULT (ic));
3187 leftOp = AOP(IC_LEFT(ic));
3188 rightOp = AOP(IC_RIGHT(ic));
3193 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3195 emitcode("mov", "b,a");
3196 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3197 emitcode("xch", "a,b");
3198 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3199 emitcode (add, "a,b");
3201 else if (aopGetUsesAcc (leftOp, offset))
3203 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3204 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3208 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3209 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3211 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3212 add = "addc"; /* further adds must propagate carry */
3215 adjustArithmeticResult (ic);
3218 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3219 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3220 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3223 /*-----------------------------------------------------------------*/
3224 /* genMinusDec :- does subtraction with deccrement if possible */
3225 /*-----------------------------------------------------------------*/
3227 genMinusDec (iCode * ic)
3229 unsigned int icount;
3230 unsigned int size = getDataSize (IC_RESULT (ic));
3232 /* will try to generate an increment */
3233 /* if the right side is not a literal
3235 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3238 /* if the literal value of the right hand side
3239 is greater than 4 then it is not worth it */
3240 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3243 D(emitcode (";", "genMinusDec"));
3245 /* if decrement 16 bits in register */
3246 if (AOP_TYPE(IC_LEFT(ic)) == AOP_REG &&
3247 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3255 /* If the next instruction is a goto and the goto target
3256 * is <= 10 instructions previous to this, we can generate
3257 * jumps straight to that target.
3259 if (ic->next && ic->next->op == GOTO
3260 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3261 && labelRange <= 10)
3263 emitcode (";", "tail decrement optimized");
3264 tlbl = IC_LABEL (ic->next);
3269 tlbl = newiTempLabel (NULL);
3273 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3274 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3275 IS_AOP_PREG (IC_RESULT (ic)))
3276 emitcode ("cjne", "%s,#0xff,%05d$"
3277 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3281 emitcode ("mov", "a,#0xff");
3282 emitcode ("cjne", "a,%s,%05d$"
3283 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3286 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3289 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3290 IS_AOP_PREG (IC_RESULT (ic)))
3291 emitcode ("cjne", "%s,#0xff,%05d$"
3292 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3296 emitcode ("cjne", "a,%s,%05d$"
3297 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3300 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3304 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3305 IS_AOP_PREG (IC_RESULT (ic)))
3306 emitcode ("cjne", "%s,#0xff,%05d$"
3307 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3311 emitcode ("cjne", "a,%s,%05d$"
3312 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3315 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3319 emitcode ("", "%05d$:", tlbl->key + 100);
3324 /* if the sizes are greater than 1 then we cannot */
3325 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3326 AOP_SIZE (IC_LEFT (ic)) > 1)
3329 /* we can if the aops of the left & result match or
3330 if they are in registers and the registers are the
3332 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3336 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3344 /*-----------------------------------------------------------------*/
3345 /* addSign - complete with sign */
3346 /*-----------------------------------------------------------------*/
3348 addSign (operand * result, int offset, int sign)
3350 int size = (getDataSize (result) - offset);
3355 emitcode ("rlc", "a");
3356 emitcode ("subb", "a,acc");
3358 aopPut (AOP (result), "a", offset++);
3362 aopPut (AOP (result), zero, offset++);
3366 /*-----------------------------------------------------------------*/
3367 /* genMinusBits - generates code for subtraction of two bits */
3368 /*-----------------------------------------------------------------*/
3370 genMinusBits (iCode * ic)
3372 symbol *lbl = newiTempLabel (NULL);
3374 D(emitcode (";", "genMinusBits"));
3376 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3378 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3379 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3380 emitcode ("cpl", "c");
3381 emitcode ("", "%05d$:", (lbl->key + 100));
3382 outBitC (IC_RESULT (ic));
3386 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3387 emitcode ("subb", "a,acc");
3388 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3389 emitcode ("inc", "a");
3390 emitcode ("", "%05d$:", (lbl->key + 100));
3391 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3392 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3396 /*-----------------------------------------------------------------*/
3397 /* genMinus - generates code for subtraction */
3398 /*-----------------------------------------------------------------*/
3400 genMinus (iCode * ic)
3402 int size, offset = 0;
3404 D(emitcode (";", "genMinus"));
3406 aopOp (IC_LEFT (ic), ic, FALSE);
3407 aopOp (IC_RIGHT (ic), ic, FALSE);
3408 aopOp (IC_RESULT (ic), ic, TRUE);
3410 /* special cases :- */
3411 /* if both left & right are in bit space */
3412 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3413 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3419 /* if I can do an decrement instead
3420 of subtract then GOOD for ME */
3421 if (genMinusDec (ic) == TRUE)
3424 size = getDataSize (IC_RESULT (ic));
3426 /* if literal, add a,#-lit, else normal subb */
3427 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3429 unsigned long lit = 0L;
3431 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3436 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3437 /* first add without previous c */
3439 if (!size && lit==-1) {
3440 emitcode ("dec", "a");
3442 emitcode ("add", "a,#0x%02x",
3443 (unsigned int) (lit & 0x0FFL));
3446 emitcode ("addc", "a,#0x%02x",
3447 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3449 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3454 asmop *leftOp, *rightOp;
3456 leftOp = AOP(IC_LEFT(ic));
3457 rightOp = AOP(IC_RIGHT(ic));
3461 if (aopGetUsesAcc(rightOp, offset)) {
3462 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3463 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3465 emitcode( "cpl", "c");
3467 emitcode( "setb", "c");
3469 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3470 emitcode("cpl", "a");
3472 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3475 emitcode ("subb", "a,%s",
3476 aopGet(rightOp, offset, FALSE, TRUE));
3479 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3484 adjustArithmeticResult (ic);
3487 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3488 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3489 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3493 /*-----------------------------------------------------------------*/
3494 /* genMultbits :- multiplication of bits */
3495 /*-----------------------------------------------------------------*/
3497 genMultbits (operand * left,
3501 D(emitcode (";", "genMultbits"));
3503 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3504 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3509 /*-----------------------------------------------------------------*/
3510 /* genMultOneByte : 8*8=8/16 bit multiplication */
3511 /*-----------------------------------------------------------------*/
3513 genMultOneByte (operand * left,
3517 sym_link *opetype = operandType (result);
3519 int size=AOP_SIZE(result);
3521 D(emitcode (";", "genMultOneByte"));
3523 if (size<1 || size>2) {
3524 // this should never happen
3525 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3526 AOP_SIZE(result), __FILE__, lineno);
3530 /* (if two literals: the value is computed before) */
3531 /* if one literal, literal on the right */
3532 if (AOP_TYPE (left) == AOP_LIT)
3537 //emitcode (";", "swapped left and right");
3540 if (SPEC_USIGN(opetype)
3541 // ignore the sign of left and right, what else can we do?
3542 || (SPEC_USIGN(operandType(left)) &&
3543 SPEC_USIGN(operandType(right)))) {
3544 // just an unsigned 8*8=8/16 multiply
3545 //emitcode (";","unsigned");
3546 // TODO: check for accumulator clash between left & right aops?
3547 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3548 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3549 emitcode ("mul", "ab");
3550 aopPut (AOP (result), "a", 0);
3552 aopPut (AOP (result), "b", 1);
3557 // we have to do a signed multiply
3559 //emitcode (";", "signed");
3560 emitcode ("clr", "F0"); // reset sign flag
3561 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3563 lbl=newiTempLabel(NULL);
3564 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3565 // left side is negative, 8-bit two's complement, this fails for -128
3566 emitcode ("setb", "F0"); // set sign flag
3567 emitcode ("cpl", "a");
3568 emitcode ("inc", "a");
3570 emitcode ("", "%05d$:", lbl->key+100);
3573 if (AOP_TYPE(right)==AOP_LIT) {
3574 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3575 /* AND literal negative */
3577 emitcode ("cpl", "F0"); // complement sign flag
3578 emitcode ("mov", "b,#0x%02x", -val);
3580 emitcode ("mov", "b,#0x%02x", val);
3583 lbl=newiTempLabel(NULL);
3584 emitcode ("mov", "b,a");
3585 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3586 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3587 // right side is negative, 8-bit two's complement
3588 emitcode ("cpl", "F0"); // complement sign flag
3589 emitcode ("cpl", "a");
3590 emitcode ("inc", "a");
3591 emitcode ("", "%05d$:", lbl->key+100);
3593 emitcode ("mul", "ab");
3595 lbl=newiTempLabel(NULL);
3596 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3597 // only ONE op was negative, we have to do a 8/16-bit two's complement
3598 emitcode ("cpl", "a"); // lsb
3600 emitcode ("inc", "a");
3602 emitcode ("add", "a,#1");
3603 emitcode ("xch", "a,b");
3604 emitcode ("cpl", "a"); // msb
3605 emitcode ("addc", "a,#0");
3606 emitcode ("xch", "a,b");
3609 emitcode ("", "%05d$:", lbl->key+100);
3610 aopPut (AOP (result), "a", 0);
3612 aopPut (AOP (result), "b", 1);
3616 /*-----------------------------------------------------------------*/
3617 /* genMult - generates code for multiplication */
3618 /*-----------------------------------------------------------------*/
3620 genMult (iCode * ic)
3622 operand *left = IC_LEFT (ic);
3623 operand *right = IC_RIGHT (ic);
3624 operand *result = IC_RESULT (ic);
3626 D(emitcode (";", "genMult"));
3628 /* assign the amsops */
3629 aopOp (left, ic, FALSE);
3630 aopOp (right, ic, FALSE);
3631 aopOp (result, ic, TRUE);
3633 /* special cases first */
3635 if (AOP_TYPE (left) == AOP_CRY &&
3636 AOP_TYPE (right) == AOP_CRY)
3638 genMultbits (left, right, result);
3642 /* if both are of size == 1 */
3643 #if 0 // one of them can be a sloc shared with the result
3644 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3646 if (getSize(operandType(left)) == 1 &&
3647 getSize(operandType(right)) == 1)
3650 genMultOneByte (left, right, result);
3654 /* should have been converted to function call */
3655 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3656 getSize(OP_SYMBOL(right)->type));
3660 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3661 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3662 freeAsmop (result, NULL, ic, TRUE);
3665 /*-----------------------------------------------------------------*/
3666 /* genDivbits :- division of bits */
3667 /*-----------------------------------------------------------------*/
3669 genDivbits (operand * left,
3676 D(emitcode (";", "genDivbits"));
3678 /* the result must be bit */
3679 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3680 l = aopGet (AOP (left), 0, FALSE, FALSE);
3684 emitcode ("div", "ab");
3685 emitcode ("rrc", "a");
3686 aopPut (AOP (result), "c", 0);
3689 /*-----------------------------------------------------------------*/
3690 /* genDivOneByte : 8 bit division */
3691 /*-----------------------------------------------------------------*/
3693 genDivOneByte (operand * left,
3697 sym_link *opetype = operandType (result);
3702 D(emitcode (";", "genDivOneByte"));
3704 size = AOP_SIZE (result) - 1;
3706 /* signed or unsigned */
3707 if (SPEC_USIGN (opetype))
3709 /* unsigned is easy */
3710 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3711 l = aopGet (AOP (left), 0, FALSE, FALSE);
3713 emitcode ("div", "ab");
3714 aopPut (AOP (result), "a", 0);
3716 aopPut (AOP (result), zero, offset++);
3720 /* signed is a little bit more difficult */
3722 /* save the signs of the operands */
3723 l = aopGet (AOP (left), 0, FALSE, FALSE);
3725 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3726 emitcode ("push", "acc"); /* save it on the stack */
3728 /* now sign adjust for both left & right */
3729 l = aopGet (AOP (right), 0, FALSE, FALSE);
3731 lbl = newiTempLabel (NULL);
3732 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3733 emitcode ("cpl", "a");
3734 emitcode ("inc", "a");
3735 emitcode ("", "%05d$:", (lbl->key + 100));
3736 emitcode ("mov", "b,a");
3738 /* sign adjust left side */
3739 l = aopGet (AOP (left), 0, FALSE, FALSE);
3742 lbl = newiTempLabel (NULL);
3743 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3744 emitcode ("cpl", "a");
3745 emitcode ("inc", "a");
3746 emitcode ("", "%05d$:", (lbl->key + 100));
3748 /* now the division */
3749 emitcode ("div", "ab");
3750 /* we are interested in the lower order
3752 emitcode ("mov", "b,a");
3753 lbl = newiTempLabel (NULL);
3754 emitcode ("pop", "acc");
3755 /* if there was an over flow we don't
3756 adjust the sign of the result */
3757 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3758 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3760 emitcode ("clr", "a");
3761 emitcode ("subb", "a,b");
3762 emitcode ("mov", "b,a");
3763 emitcode ("", "%05d$:", (lbl->key + 100));
3765 /* now we are done */
3766 aopPut (AOP (result), "b", 0);
3769 emitcode ("mov", "c,b.7");
3770 emitcode ("subb", "a,acc");
3773 aopPut (AOP (result), "a", offset++);
3777 /*-----------------------------------------------------------------*/
3778 /* genDiv - generates code for division */
3779 /*-----------------------------------------------------------------*/
3783 operand *left = IC_LEFT (ic);
3784 operand *right = IC_RIGHT (ic);
3785 operand *result = IC_RESULT (ic);
3787 D(emitcode (";", "genDiv"));
3789 /* assign the amsops */
3790 aopOp (left, ic, FALSE);
3791 aopOp (right, ic, FALSE);
3792 aopOp (result, ic, TRUE);
3794 /* special cases first */
3796 if (AOP_TYPE (left) == AOP_CRY &&
3797 AOP_TYPE (right) == AOP_CRY)
3799 genDivbits (left, right, result);
3803 /* if both are of size == 1 */
3804 if (AOP_SIZE (left) == 1 &&
3805 AOP_SIZE (right) == 1)
3807 genDivOneByte (left, right, result);
3811 /* should have been converted to function call */
3814 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3815 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3816 freeAsmop (result, NULL, ic, TRUE);
3819 /*-----------------------------------------------------------------*/
3820 /* genModbits :- modulus of bits */
3821 /*-----------------------------------------------------------------*/
3823 genModbits (operand * left,
3830 D(emitcode (";", "genModbits"));
3832 /* the result must be bit */
3833 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3834 l = aopGet (AOP (left), 0, FALSE, FALSE);
3838 emitcode ("div", "ab");
3839 emitcode ("mov", "a,b");
3840 emitcode ("rrc", "a");
3841 aopPut (AOP (result), "c", 0);
3844 /*-----------------------------------------------------------------*/
3845 /* genModOneByte : 8 bit modulus */
3846 /*-----------------------------------------------------------------*/
3848 genModOneByte (operand * left,
3852 sym_link *opetype = operandType (result);
3856 D(emitcode (";", "genModOneByte"));
3858 /* signed or unsigned */
3859 if (SPEC_USIGN (opetype))
3861 /* unsigned is easy */
3862 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3863 l = aopGet (AOP (left), 0, FALSE, FALSE);
3865 emitcode ("div", "ab");
3866 aopPut (AOP (result), "b", 0);
3870 /* signed is a little bit more difficult */
3872 /* save the signs of the operands */
3873 l = aopGet (AOP (left), 0, FALSE, FALSE);
3876 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3877 emitcode ("push", "acc"); /* save it on the stack */
3879 /* now sign adjust for both left & right */
3880 l = aopGet (AOP (right), 0, FALSE, FALSE);
3883 lbl = newiTempLabel (NULL);
3884 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3885 emitcode ("cpl", "a");
3886 emitcode ("inc", "a");
3887 emitcode ("", "%05d$:", (lbl->key + 100));
3888 emitcode ("mov", "b,a");
3890 /* sign adjust left side */
3891 l = aopGet (AOP (left), 0, FALSE, FALSE);
3894 lbl = newiTempLabel (NULL);
3895 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3896 emitcode ("cpl", "a");
3897 emitcode ("inc", "a");
3898 emitcode ("", "%05d$:", (lbl->key + 100));
3900 /* now the multiplication */
3901 emitcode ("div", "ab");
3902 /* we are interested in the lower order
3904 lbl = newiTempLabel (NULL);
3905 emitcode ("pop", "acc");
3906 /* if there was an over flow we don't
3907 adjust the sign of the result */
3908 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3909 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3911 emitcode ("clr", "a");
3912 emitcode ("subb", "a,b");
3913 emitcode ("mov", "b,a");
3914 emitcode ("", "%05d$:", (lbl->key + 100));
3916 /* now we are done */
3917 aopPut (AOP (result), "b", 0);
3921 /*-----------------------------------------------------------------*/
3922 /* genMod - generates code for division */
3923 /*-----------------------------------------------------------------*/
3927 operand *left = IC_LEFT (ic);
3928 operand *right = IC_RIGHT (ic);
3929 operand *result = IC_RESULT (ic);
3931 D(emitcode (";", "genMod"));
3933 /* assign the amsops */
3934 aopOp (left, ic, FALSE);
3935 aopOp (right, ic, FALSE);
3936 aopOp (result, ic, TRUE);
3938 /* special cases first */
3940 if (AOP_TYPE (left) == AOP_CRY &&
3941 AOP_TYPE (right) == AOP_CRY)
3943 genModbits (left, right, result);
3947 /* if both are of size == 1 */
3948 if (AOP_SIZE (left) == 1 &&
3949 AOP_SIZE (right) == 1)
3951 genModOneByte (left, right, result);
3955 /* should have been converted to function call */
3959 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3960 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3961 freeAsmop (result, NULL, ic, TRUE);
3964 /*-----------------------------------------------------------------*/
3965 /* genIfxJump :- will create a jump depending on the ifx */
3966 /*-----------------------------------------------------------------*/
3968 genIfxJump (iCode * ic, char *jval)
3971 symbol *tlbl = newiTempLabel (NULL);
3974 D(emitcode (";", "genIfxJump"));
3976 /* if true label then we jump if condition
3980 jlbl = IC_TRUE (ic);
3981 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3982 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3986 /* false label is present */
3987 jlbl = IC_FALSE (ic);
3988 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3989 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3991 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3992 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3994 emitcode (inst, "%05d$", tlbl->key + 100);
3995 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3996 emitcode ("", "%05d$:", tlbl->key + 100);
3998 /* mark the icode as generated */
4002 /*-----------------------------------------------------------------*/
4003 /* genCmp :- greater or less than comparison */
4004 /*-----------------------------------------------------------------*/
4006 genCmp (operand * left, operand * right,
4007 operand * result, iCode * ifx, int sign, iCode *ic)
4009 int size, offset = 0;
4010 unsigned long lit = 0L;
4012 D(emitcode (";", "genCmp"));
4014 /* if left & right are bit variables */
4015 if (AOP_TYPE (left) == AOP_CRY &&
4016 AOP_TYPE (right) == AOP_CRY)
4018 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4019 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
4023 /* subtract right from left if at the
4024 end the carry flag is set then we know that
4025 left is greater than right */
4026 size = max (AOP_SIZE (left), AOP_SIZE (right));
4028 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4029 if ((size == 1) && !sign &&
4030 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4032 symbol *lbl = newiTempLabel (NULL);
4033 emitcode ("cjne", "%s,%s,%05d$",
4034 aopGet (AOP (left), offset, FALSE, FALSE),
4035 aopGet (AOP (right), offset, FALSE, FALSE),
4037 emitcode ("", "%05d$:", lbl->key + 100);
4041 if (AOP_TYPE (right) == AOP_LIT)
4043 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4044 /* optimize if(x < 0) or if(x >= 0) */
4053 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4054 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4056 genIfxJump (ifx, "acc.7");
4060 emitcode ("rlc", "a");
4068 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4069 if (sign && size == 0)
4071 emitcode ("xrl", "a,#0x80");
4072 if (AOP_TYPE (right) == AOP_LIT)
4074 unsigned long lit = (unsigned long)
4075 floatFromVal (AOP (right)->aopu.aop_lit);
4076 emitcode ("subb", "a,#0x%02x",
4077 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4081 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4082 emitcode ("xrl", "b,#0x80");
4083 emitcode ("subb", "a,b");
4087 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
4093 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4094 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4095 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4101 /* if the result is used in the next
4102 ifx conditional branch then generate
4103 code a little differently */
4105 genIfxJump (ifx, "c");
4108 /* leave the result in acc */
4112 /*-----------------------------------------------------------------*/
4113 /* genCmpGt :- greater than comparison */
4114 /*-----------------------------------------------------------------*/
4116 genCmpGt (iCode * ic, iCode * ifx)
4118 operand *left, *right, *result;
4119 sym_link *letype, *retype;
4122 D(emitcode (";", "genCmpGt"));
4124 left = IC_LEFT (ic);
4125 right = IC_RIGHT (ic);
4126 result = IC_RESULT (ic);
4128 letype = getSpec (operandType (left));
4129 retype = getSpec (operandType (right));
4130 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4131 /* assign the amsops */
4132 aopOp (left, ic, FALSE);
4133 aopOp (right, ic, FALSE);
4134 aopOp (result, ic, TRUE);
4136 genCmp (right, left, result, ifx, sign,ic);
4138 freeAsmop (result, NULL, ic, TRUE);
4141 /*-----------------------------------------------------------------*/
4142 /* genCmpLt - less than comparisons */
4143 /*-----------------------------------------------------------------*/
4145 genCmpLt (iCode * ic, iCode * ifx)
4147 operand *left, *right, *result;
4148 sym_link *letype, *retype;
4151 D(emitcode (";", "genCmpLt"));
4153 left = IC_LEFT (ic);
4154 right = IC_RIGHT (ic);
4155 result = IC_RESULT (ic);
4157 letype = getSpec (operandType (left));
4158 retype = getSpec (operandType (right));
4159 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4161 /* assign the amsops */
4162 aopOp (left, ic, FALSE);
4163 aopOp (right, ic, FALSE);
4164 aopOp (result, ic, TRUE);
4166 genCmp (left, right, result, ifx, sign,ic);
4168 freeAsmop (result, NULL, ic, TRUE);
4171 /*-----------------------------------------------------------------*/
4172 /* gencjneshort - compare and jump if not equal */
4173 /*-----------------------------------------------------------------*/
4175 gencjneshort (operand * left, operand * right, symbol * lbl)
4177 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4179 unsigned long lit = 0L;
4181 /* if the left side is a literal or
4182 if the right is in a pointer register and left
4184 if ((AOP_TYPE (left) == AOP_LIT) ||
4185 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4191 if (AOP_TYPE (right) == AOP_LIT)
4192 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4194 /* if the right side is a literal then anything goes */
4195 if (AOP_TYPE (right) == AOP_LIT &&
4196 AOP_TYPE (left) != AOP_DIR)
4200 emitcode ("cjne", "%s,%s,%05d$",
4201 aopGet (AOP (left), offset, FALSE, FALSE),
4202 aopGet (AOP (right), offset, FALSE, FALSE),
4208 /* if the right side is in a register or in direct space or
4209 if the left is a pointer register & right is not */
4210 else if (AOP_TYPE (right) == AOP_REG ||
4211 AOP_TYPE (right) == AOP_DIR ||
4212 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4213 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4217 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4218 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4219 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4220 emitcode ("jnz", "%05d$", lbl->key + 100);
4222 emitcode ("cjne", "a,%s,%05d$",
4223 aopGet (AOP (right), offset, FALSE, TRUE),
4230 /* right is a pointer reg need both a & b */
4233 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4234 if (strcmp (l, "b"))
4235 emitcode ("mov", "b,%s", l);
4236 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4237 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4243 /*-----------------------------------------------------------------*/
4244 /* gencjne - compare and jump if not equal */
4245 /*-----------------------------------------------------------------*/
4247 gencjne (operand * left, operand * right, symbol * lbl)
4249 symbol *tlbl = newiTempLabel (NULL);
4251 gencjneshort (left, right, lbl);
4253 emitcode ("mov", "a,%s", one);
4254 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4255 emitcode ("", "%05d$:", lbl->key + 100);
4256 emitcode ("clr", "a");
4257 emitcode ("", "%05d$:", tlbl->key + 100);
4260 /*-----------------------------------------------------------------*/
4261 /* genCmpEq - generates code for equal to */
4262 /*-----------------------------------------------------------------*/
4264 genCmpEq (iCode * ic, iCode * ifx)
4266 operand *left, *right, *result;
4268 D(emitcode (";", "genCmpEq"));
4270 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4271 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4272 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4274 /* if literal, literal on the right or
4275 if the right is in a pointer register and left
4277 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4278 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4280 operand *t = IC_RIGHT (ic);
4281 IC_RIGHT (ic) = IC_LEFT (ic);
4285 if (ifx && !AOP_SIZE (result))
4288 /* if they are both bit variables */
4289 if (AOP_TYPE (left) == AOP_CRY &&
4290 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4292 if (AOP_TYPE (right) == AOP_LIT)
4294 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4297 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4298 emitcode ("cpl", "c");
4302 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4306 emitcode ("clr", "c");
4308 /* AOP_TYPE(right) == AOP_CRY */
4312 symbol *lbl = newiTempLabel (NULL);
4313 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4314 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4315 emitcode ("cpl", "c");
4316 emitcode ("", "%05d$:", (lbl->key + 100));
4318 /* if true label then we jump if condition
4320 tlbl = newiTempLabel (NULL);
4323 emitcode ("jnc", "%05d$", tlbl->key + 100);
4324 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4328 emitcode ("jc", "%05d$", tlbl->key + 100);
4329 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4331 emitcode ("", "%05d$:", tlbl->key + 100);
4335 tlbl = newiTempLabel (NULL);
4336 gencjneshort (left, right, tlbl);
4339 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4340 emitcode ("", "%05d$:", tlbl->key + 100);
4344 symbol *lbl = newiTempLabel (NULL);
4345 emitcode ("sjmp", "%05d$", lbl->key + 100);
4346 emitcode ("", "%05d$:", tlbl->key + 100);
4347 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4348 emitcode ("", "%05d$:", lbl->key + 100);
4351 /* mark the icode as generated */
4356 /* if they are both bit variables */
4357 if (AOP_TYPE (left) == AOP_CRY &&
4358 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4360 if (AOP_TYPE (right) == AOP_LIT)
4362 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4365 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4366 emitcode ("cpl", "c");
4370 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4374 emitcode ("clr", "c");
4376 /* AOP_TYPE(right) == AOP_CRY */
4380 symbol *lbl = newiTempLabel (NULL);
4381 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4382 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4383 emitcode ("cpl", "c");
4384 emitcode ("", "%05d$:", (lbl->key + 100));
4387 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4394 genIfxJump (ifx, "c");
4397 /* if the result is used in an arithmetic operation
4398 then put the result in place */
4403 gencjne (left, right, newiTempLabel (NULL));
4404 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4406 aopPut (AOP (result), "a", 0);
4411 genIfxJump (ifx, "a");
4414 /* if the result is used in an arithmetic operation
4415 then put the result in place */
4416 if (AOP_TYPE (result) != AOP_CRY)
4418 /* leave the result in acc */
4422 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4423 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4424 freeAsmop (result, NULL, ic, TRUE);
4427 /*-----------------------------------------------------------------*/
4428 /* ifxForOp - returns the icode containing the ifx for operand */
4429 /*-----------------------------------------------------------------*/
4431 ifxForOp (operand * op, iCode * ic)
4433 /* if true symbol then needs to be assigned */
4434 if (IS_TRUE_SYMOP (op))
4437 /* if this has register type condition and
4438 the next instruction is ifx with the same operand
4439 and live to of the operand is upto the ifx only then */
4441 ic->next->op == IFX &&
4442 IC_COND (ic->next)->key == op->key &&
4443 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4449 /*-----------------------------------------------------------------*/
4450 /* hasInc - operand is incremented before any other use */
4451 /*-----------------------------------------------------------------*/
4453 hasInc (operand *op, iCode *ic,int osize)
4455 sym_link *type = operandType(op);
4456 sym_link *retype = getSpec (type);
4457 iCode *lic = ic->next;
4460 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4461 if (!IS_SYMOP(op)) return NULL;
4463 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4464 if (IS_AGGREGATE(type->next)) return NULL;
4465 if (osize != (isize = getSize(type->next))) return NULL;
4468 /* if operand of the form op = op + <sizeof *op> */
4469 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4470 isOperandEqual(IC_RESULT(lic),op) &&
4471 isOperandLiteral(IC_RIGHT(lic)) &&
4472 operandLitValue(IC_RIGHT(lic)) == isize) {
4475 /* if the operand used or deffed */
4476 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4479 /* if GOTO or IFX */
4480 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4486 /*-----------------------------------------------------------------*/
4487 /* genAndOp - for && operation */
4488 /*-----------------------------------------------------------------*/
4490 genAndOp (iCode * ic)
4492 operand *left, *right, *result;
4495 D(emitcode (";", "genAndOp"));
4497 /* note here that && operations that are in an
4498 if statement are taken away by backPatchLabels
4499 only those used in arthmetic operations remain */
4500 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4501 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4502 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4504 /* if both are bit variables */
4505 if (AOP_TYPE (left) == AOP_CRY &&
4506 AOP_TYPE (right) == AOP_CRY)
4508 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4509 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4514 tlbl = newiTempLabel (NULL);
4516 emitcode ("jz", "%05d$", tlbl->key + 100);
4518 emitcode ("", "%05d$:", tlbl->key + 100);
4522 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4523 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4524 freeAsmop (result, NULL, ic, TRUE);
4528 /*-----------------------------------------------------------------*/
4529 /* genOrOp - for || operation */
4530 /*-----------------------------------------------------------------*/
4532 genOrOp (iCode * ic)
4534 operand *left, *right, *result;
4537 D(emitcode (";", "genOrOp"));
4539 /* note here that || operations that are in an
4540 if statement are taken away by backPatchLabels
4541 only those used in arthmetic operations remain */
4542 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4543 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4544 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4546 /* if both are bit variables */
4547 if (AOP_TYPE (left) == AOP_CRY &&
4548 AOP_TYPE (right) == AOP_CRY)
4550 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4551 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4556 tlbl = newiTempLabel (NULL);
4558 emitcode ("jnz", "%05d$", tlbl->key + 100);
4560 emitcode ("", "%05d$:", tlbl->key + 100);
4564 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4565 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4566 freeAsmop (result, NULL, ic, TRUE);
4569 /*-----------------------------------------------------------------*/
4570 /* isLiteralBit - test if lit == 2^n */
4571 /*-----------------------------------------------------------------*/
4573 isLiteralBit (unsigned long lit)
4575 unsigned long pw[32] =
4576 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4577 0x100L, 0x200L, 0x400L, 0x800L,
4578 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4579 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4580 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4581 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4582 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4585 for (idx = 0; idx < 32; idx++)
4591 /*-----------------------------------------------------------------*/
4592 /* continueIfTrue - */
4593 /*-----------------------------------------------------------------*/
4595 continueIfTrue (iCode * ic)
4598 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4602 /*-----------------------------------------------------------------*/
4604 /*-----------------------------------------------------------------*/
4606 jumpIfTrue (iCode * ic)
4609 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4613 /*-----------------------------------------------------------------*/
4614 /* jmpTrueOrFalse - */
4615 /*-----------------------------------------------------------------*/
4617 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4619 // ugly but optimized by peephole
4622 symbol *nlbl = newiTempLabel (NULL);
4623 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4624 emitcode ("", "%05d$:", tlbl->key + 100);
4625 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4626 emitcode ("", "%05d$:", nlbl->key + 100);
4630 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4631 emitcode ("", "%05d$:", tlbl->key + 100);
4636 /*-----------------------------------------------------------------*/
4637 /* genAnd - code for and */
4638 /*-----------------------------------------------------------------*/
4640 genAnd (iCode * ic, iCode * ifx)
4642 operand *left, *right, *result;
4643 int size, offset = 0;
4644 unsigned long lit = 0L;
4648 D(emitcode (";", "genAnd"));
4650 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4651 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4652 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4655 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4657 AOP_TYPE (left), AOP_TYPE (right));
4658 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4660 AOP_SIZE (left), AOP_SIZE (right));
4663 /* if left is a literal & right is not then exchange them */
4664 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4665 AOP_NEEDSACC (left))
4667 operand *tmp = right;
4672 /* if result = right then exchange them */
4673 if (sameRegs (AOP (result), AOP (right)))
4675 operand *tmp = right;
4680 /* if right is bit then exchange them */
4681 if (AOP_TYPE (right) == AOP_CRY &&
4682 AOP_TYPE (left) != AOP_CRY)
4684 operand *tmp = right;
4688 if (AOP_TYPE (right) == AOP_LIT)
4689 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4691 size = AOP_SIZE (result);
4694 // result = bit & yy;
4695 if (AOP_TYPE (left) == AOP_CRY)
4697 // c = bit & literal;
4698 if (AOP_TYPE (right) == AOP_LIT)
4702 if (size && sameRegs (AOP (result), AOP (left)))
4705 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4710 if (size && (AOP_TYPE (result) == AOP_CRY))
4712 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4715 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4720 emitcode ("clr", "c");
4725 if (AOP_TYPE (right) == AOP_CRY)
4728 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4729 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4734 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4736 emitcode ("rrc", "a");
4737 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4745 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4746 genIfxJump (ifx, "c");
4750 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4751 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4752 if ((AOP_TYPE (right) == AOP_LIT) &&
4753 (AOP_TYPE (result) == AOP_CRY) &&
4754 (AOP_TYPE (left) != AOP_CRY))
4756 int posbit = isLiteralBit (lit);
4761 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4764 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4770 sprintf (buffer, "acc.%d", posbit & 0x07);
4771 genIfxJump (ifx, buffer);
4778 symbol *tlbl = newiTempLabel (NULL);
4779 int sizel = AOP_SIZE (left);
4781 emitcode ("setb", "c");
4784 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4786 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4788 if ((posbit = isLiteralBit (bytelit)) != 0)
4789 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4792 if (bytelit != 0x0FFL)
4793 emitcode ("anl", "a,%s",
4794 aopGet (AOP (right), offset, FALSE, TRUE));
4795 emitcode ("jnz", "%05d$", tlbl->key + 100);
4800 // bit = left & literal
4803 emitcode ("clr", "c");
4804 emitcode ("", "%05d$:", tlbl->key + 100);
4806 // if(left & literal)
4810 jmpTrueOrFalse (ifx, tlbl);
4818 /* if left is same as result */
4819 if (sameRegs (AOP (result), AOP (left)))
4821 for (; size--; offset++)
4823 if (AOP_TYPE (right) == AOP_LIT)
4825 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4827 else if (bytelit == 0)
4828 aopPut (AOP (result), zero, offset);
4829 else if (IS_AOP_PREG (result))
4831 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4832 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4833 aopPut (AOP (result), "a", offset);
4836 emitcode ("anl", "%s,%s",
4837 aopGet (AOP (left), offset, FALSE, TRUE),
4838 aopGet (AOP (right), offset, FALSE, FALSE));
4842 if (AOP_TYPE (left) == AOP_ACC)
4843 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4846 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4847 if (IS_AOP_PREG (result))
4849 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4850 aopPut (AOP (result), "a", offset);
4854 emitcode ("anl", "%s,a",
4855 aopGet (AOP (left), offset, FALSE, TRUE));
4862 // left & result in different registers
4863 if (AOP_TYPE (result) == AOP_CRY)
4866 // if(size), result in bit
4867 // if(!size && ifx), conditional oper: if(left & right)
4868 symbol *tlbl = newiTempLabel (NULL);
4869 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4871 emitcode ("setb", "c");
4874 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4875 emitcode ("anl", "a,%s",
4876 aopGet (AOP (right), offset, FALSE, FALSE));
4878 if (AOP_TYPE(left)==AOP_ACC) {
4879 emitcode("mov", "b,a");
4880 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4881 emitcode("anl", "a,b");
4883 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4884 emitcode ("anl", "a,%s",
4885 aopGet (AOP (left), offset, FALSE, FALSE));
4888 emitcode ("jnz", "%05d$", tlbl->key + 100);
4894 emitcode ("", "%05d$:", tlbl->key + 100);
4898 jmpTrueOrFalse (ifx, tlbl);
4902 for (; (size--); offset++)
4905 // result = left & right
4906 if (AOP_TYPE (right) == AOP_LIT)
4908 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4910 aopPut (AOP (result),
4911 aopGet (AOP (left), offset, FALSE, FALSE),
4915 else if (bytelit == 0)
4917 aopPut (AOP (result), zero, offset);
4921 // faster than result <- left, anl result,right
4922 // and better if result is SFR
4923 if (AOP_TYPE (left) == AOP_ACC)
4924 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4927 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4928 emitcode ("anl", "a,%s",
4929 aopGet (AOP (left), offset, FALSE, FALSE));
4931 aopPut (AOP (result), "a", offset);
4937 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4938 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4939 freeAsmop (result, NULL, ic, TRUE);
4942 /*-----------------------------------------------------------------*/
4943 /* genOr - code for or */
4944 /*-----------------------------------------------------------------*/
4946 genOr (iCode * ic, iCode * ifx)
4948 operand *left, *right, *result;
4949 int size, offset = 0;
4950 unsigned long lit = 0L;
4952 D(emitcode (";", "genOr"));
4954 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4955 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4956 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4959 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4961 AOP_TYPE (left), AOP_TYPE (right));
4962 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4964 AOP_SIZE (left), AOP_SIZE (right));
4967 /* if left is a literal & right is not then exchange them */
4968 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4969 AOP_NEEDSACC (left))
4971 operand *tmp = right;
4976 /* if result = right then exchange them */
4977 if (sameRegs (AOP (result), AOP (right)))
4979 operand *tmp = right;
4984 /* if right is bit then exchange them */
4985 if (AOP_TYPE (right) == AOP_CRY &&
4986 AOP_TYPE (left) != AOP_CRY)
4988 operand *tmp = right;
4992 if (AOP_TYPE (right) == AOP_LIT)
4993 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4995 size = AOP_SIZE (result);
4999 if (AOP_TYPE (left) == AOP_CRY)
5001 if (AOP_TYPE (right) == AOP_LIT)
5003 // c = bit | literal;
5006 // lit != 0 => result = 1
5007 if (AOP_TYPE (result) == AOP_CRY)
5010 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5012 continueIfTrue (ifx);
5015 emitcode ("setb", "c");
5019 // lit == 0 => result = left
5020 if (size && sameRegs (AOP (result), AOP (left)))
5022 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5027 if (AOP_TYPE (right) == AOP_CRY)
5030 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5031 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5036 symbol *tlbl = newiTempLabel (NULL);
5037 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5038 emitcode ("setb", "c");
5039 emitcode ("jb", "%s,%05d$",
5040 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5042 emitcode ("jnz", "%05d$", tlbl->key + 100);
5043 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5045 jmpTrueOrFalse (ifx, tlbl);
5051 emitcode ("", "%05d$:", tlbl->key + 100);
5060 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5061 genIfxJump (ifx, "c");
5065 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5066 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5067 if ((AOP_TYPE (right) == AOP_LIT) &&
5068 (AOP_TYPE (result) == AOP_CRY) &&
5069 (AOP_TYPE (left) != AOP_CRY))
5075 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5077 continueIfTrue (ifx);
5082 // lit = 0, result = boolean(left)
5084 emitcode ("setb", "c");
5088 symbol *tlbl = newiTempLabel (NULL);
5089 emitcode ("jnz", "%05d$", tlbl->key + 100);
5091 emitcode ("", "%05d$:", tlbl->key + 100);
5095 genIfxJump (ifx, "a");
5103 /* if left is same as result */
5104 if (sameRegs (AOP (result), AOP (left)))
5106 for (; size--; offset++)
5108 if (AOP_TYPE (right) == AOP_LIT)
5110 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5112 else if (IS_AOP_PREG (left))
5114 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5115 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5116 aopPut (AOP (result), "a", offset);
5119 emitcode ("orl", "%s,%s",
5120 aopGet (AOP (left), offset, FALSE, TRUE),
5121 aopGet (AOP (right), offset, FALSE, FALSE));
5125 if (AOP_TYPE (left) == AOP_ACC)
5126 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5129 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5130 if (IS_AOP_PREG (left))
5132 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5133 aopPut (AOP (result), "a", offset);
5136 emitcode ("orl", "%s,a",
5137 aopGet (AOP (left), offset, FALSE, TRUE));
5144 // left & result in different registers
5145 if (AOP_TYPE (result) == AOP_CRY)
5148 // if(size), result in bit
5149 // if(!size && ifx), conditional oper: if(left | right)
5150 symbol *tlbl = newiTempLabel (NULL);
5151 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5153 emitcode ("setb", "c");
5156 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5157 emitcode ("orl", "a,%s",
5158 aopGet (AOP (right), offset, FALSE, FALSE));
5160 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5161 emitcode ("orl", "a,%s",
5162 aopGet (AOP (left), offset, FALSE, FALSE));
5164 emitcode ("jnz", "%05d$", tlbl->key + 100);
5170 emitcode ("", "%05d$:", tlbl->key + 100);
5174 jmpTrueOrFalse (ifx, tlbl);
5177 for (; (size--); offset++)
5180 // result = left & right
5181 if (AOP_TYPE (right) == AOP_LIT)
5183 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5185 aopPut (AOP (result),
5186 aopGet (AOP (left), offset, FALSE, FALSE),
5191 // faster than result <- left, anl result,right
5192 // and better if result is SFR
5193 if (AOP_TYPE (left) == AOP_ACC)
5194 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5197 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5198 emitcode ("orl", "a,%s",
5199 aopGet (AOP (left), offset, FALSE, FALSE));
5201 aopPut (AOP (result), "a", offset);
5206 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5207 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5208 freeAsmop (result, NULL, ic, TRUE);
5211 /*-----------------------------------------------------------------*/
5212 /* genXor - code for xclusive or */
5213 /*-----------------------------------------------------------------*/
5215 genXor (iCode * ic, iCode * ifx)
5217 operand *left, *right, *result;
5218 int size, offset = 0;
5219 unsigned long lit = 0L;
5221 D(emitcode (";", "genXor"));
5223 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5224 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5225 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5228 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5230 AOP_TYPE (left), AOP_TYPE (right));
5231 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5233 AOP_SIZE (left), AOP_SIZE (right));
5236 /* if left is a literal & right is not ||
5237 if left needs acc & right does not */
5238 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5239 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5241 operand *tmp = right;
5246 /* if result = right then exchange them */
5247 if (sameRegs (AOP (result), AOP (right)))
5249 operand *tmp = right;
5254 /* if right is bit then exchange them */
5255 if (AOP_TYPE (right) == AOP_CRY &&
5256 AOP_TYPE (left) != AOP_CRY)
5258 operand *tmp = right;
5262 if (AOP_TYPE (right) == AOP_LIT)
5263 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5265 size = AOP_SIZE (result);
5269 if (AOP_TYPE (left) == AOP_CRY)
5271 if (AOP_TYPE (right) == AOP_LIT)
5273 // c = bit & literal;
5276 // lit>>1 != 0 => result = 1
5277 if (AOP_TYPE (result) == AOP_CRY)
5280 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5282 continueIfTrue (ifx);
5285 emitcode ("setb", "c");
5292 // lit == 0, result = left
5293 if (size && sameRegs (AOP (result), AOP (left)))
5295 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5299 // lit == 1, result = not(left)
5300 if (size && sameRegs (AOP (result), AOP (left)))
5302 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5307 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5308 emitcode ("cpl", "c");
5317 symbol *tlbl = newiTempLabel (NULL);
5318 if (AOP_TYPE (right) == AOP_CRY)
5321 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5325 int sizer = AOP_SIZE (right);
5327 // if val>>1 != 0, result = 1
5328 emitcode ("setb", "c");
5331 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5333 // test the msb of the lsb
5334 emitcode ("anl", "a,#0xfe");
5335 emitcode ("jnz", "%05d$", tlbl->key + 100);
5339 emitcode ("rrc", "a");
5341 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5342 emitcode ("cpl", "c");
5343 emitcode ("", "%05d$:", (tlbl->key + 100));
5350 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5351 genIfxJump (ifx, "c");
5355 if (sameRegs (AOP (result), AOP (left)))
5357 /* if left is same as result */
5358 for (; size--; offset++)
5360 if (AOP_TYPE (right) == AOP_LIT)
5362 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5364 else if (IS_AOP_PREG (left))
5366 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5367 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5368 aopPut (AOP (result), "a", offset);
5371 emitcode ("xrl", "%s,%s",
5372 aopGet (AOP (left), offset, FALSE, TRUE),
5373 aopGet (AOP (right), offset, FALSE, FALSE));
5377 if (AOP_TYPE (left) == AOP_ACC)
5378 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5381 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5382 if (IS_AOP_PREG (left))
5384 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5385 aopPut (AOP (result), "a", offset);
5388 emitcode ("xrl", "%s,a",
5389 aopGet (AOP (left), offset, FALSE, TRUE));
5396 // left & result in different registers
5397 if (AOP_TYPE (result) == AOP_CRY)
5400 // if(size), result in bit
5401 // if(!size && ifx), conditional oper: if(left ^ right)
5402 symbol *tlbl = newiTempLabel (NULL);
5403 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5405 emitcode ("setb", "c");
5408 if ((AOP_TYPE (right) == AOP_LIT) &&
5409 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5411 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5415 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5416 emitcode ("xrl", "a,%s",
5417 aopGet (AOP (right), offset, FALSE, FALSE));
5419 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5420 emitcode ("xrl", "a,%s",
5421 aopGet (AOP (left), offset, FALSE, FALSE));
5424 emitcode ("jnz", "%05d$", tlbl->key + 100);
5430 emitcode ("", "%05d$:", tlbl->key + 100);
5434 jmpTrueOrFalse (ifx, tlbl);
5437 for (; (size--); offset++)
5440 // result = left & right
5441 if (AOP_TYPE (right) == AOP_LIT)
5443 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5445 aopPut (AOP (result),
5446 aopGet (AOP (left), offset, FALSE, FALSE),
5451 // faster than result <- left, anl result,right
5452 // and better if result is SFR
5453 if (AOP_TYPE (left) == AOP_ACC)
5454 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5457 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5458 emitcode ("xrl", "a,%s",
5459 aopGet (AOP (left), offset, FALSE, TRUE));
5461 aopPut (AOP (result), "a", offset);
5466 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5467 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5468 freeAsmop (result, NULL, ic, TRUE);
5471 /*-----------------------------------------------------------------*/
5472 /* genInline - write the inline code out */
5473 /*-----------------------------------------------------------------*/
5475 genInline (iCode * ic)
5477 char *buffer, *bp, *bp1;
5479 D(emitcode (";", "genInline"));
5481 _G.inLine += (!options.asmpeep);
5483 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5484 strcpy (buffer, IC_INLINE (ic));
5486 /* emit each line as a code */
5511 /* emitcode("",buffer); */
5512 _G.inLine -= (!options.asmpeep);
5515 /*-----------------------------------------------------------------*/
5516 /* genRRC - rotate right with carry */
5517 /*-----------------------------------------------------------------*/
5521 operand *left, *result;
5522 int size, offset = 0;
5525 D(emitcode (";", "genRRC"));
5527 /* rotate right with carry */
5528 left = IC_LEFT (ic);
5529 result = IC_RESULT (ic);
5530 aopOp (left, ic, FALSE);
5531 aopOp (result, ic, FALSE);
5533 /* move it to the result */
5534 size = AOP_SIZE (result);
5536 if (size == 1) { /* special case for 1 byte */
5537 l = aopGet (AOP (left), offset, FALSE, FALSE);
5539 emitcode ("rr", "a");
5545 l = aopGet (AOP (left), offset, FALSE, FALSE);
5547 emitcode ("rrc", "a");
5548 if (AOP_SIZE (result) > 1)
5549 aopPut (AOP (result), "a", offset--);
5551 /* now we need to put the carry into the
5552 highest order byte of the result */
5553 if (AOP_SIZE (result) > 1)
5555 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5558 emitcode ("mov", "acc.7,c");
5560 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5561 freeAsmop (left, NULL, ic, TRUE);
5562 freeAsmop (result, NULL, ic, TRUE);
5565 /*-----------------------------------------------------------------*/
5566 /* genRLC - generate code for rotate left with carry */
5567 /*-----------------------------------------------------------------*/
5571 operand *left, *result;
5572 int size, offset = 0;
5575 D(emitcode (";", "genRLC"));
5577 /* rotate right with carry */
5578 left = IC_LEFT (ic);
5579 result = IC_RESULT (ic);
5580 aopOp (left, ic, FALSE);
5581 aopOp (result, ic, FALSE);
5583 /* move it to the result */
5584 size = AOP_SIZE (result);
5588 l = aopGet (AOP (left), offset, FALSE, FALSE);
5590 if (size == 0) { /* special case for 1 byte */
5594 emitcode ("add", "a,acc");
5595 if (AOP_SIZE (result) > 1)
5596 aopPut (AOP (result), "a", offset++);
5599 l = aopGet (AOP (left), offset, FALSE, FALSE);
5601 emitcode ("rlc", "a");
5602 if (AOP_SIZE (result) > 1)
5603 aopPut (AOP (result), "a", offset++);
5606 /* now we need to put the carry into the
5607 highest order byte of the result */
5608 if (AOP_SIZE (result) > 1)
5610 l = aopGet (AOP (result), 0, FALSE, FALSE);
5613 emitcode ("mov", "acc.0,c");
5615 aopPut (AOP (result), "a", 0);
5616 freeAsmop (left, NULL, ic, TRUE);
5617 freeAsmop (result, NULL, ic, TRUE);
5620 /*-----------------------------------------------------------------*/
5621 /* genGetHbit - generates code get highest order bit */
5622 /*-----------------------------------------------------------------*/
5624 genGetHbit (iCode * ic)
5626 operand *left, *result;
5628 D(emitcode (";", "genGetHbit"));
5630 left = IC_LEFT (ic);
5631 result = IC_RESULT (ic);
5632 aopOp (left, ic, FALSE);
5633 aopOp (result, ic, FALSE);
5635 /* get the highest order byte into a */
5636 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5637 if (AOP_TYPE (result) == AOP_CRY)
5639 emitcode ("rlc", "a");
5644 emitcode ("rl", "a");
5645 emitcode ("anl", "a,#0x01");
5650 freeAsmop (left, NULL, ic, TRUE);
5651 freeAsmop (result, NULL, ic, TRUE);
5654 /*-----------------------------------------------------------------*/
5655 /* AccRol - rotate left accumulator by known count */
5656 /*-----------------------------------------------------------------*/
5658 AccRol (int shCount)
5660 shCount &= 0x0007; // shCount : 0..7
5667 emitcode ("rl", "a");
5670 emitcode ("rl", "a");
5671 emitcode ("rl", "a");
5674 emitcode ("swap", "a");
5675 emitcode ("rr", "a");
5678 emitcode ("swap", "a");
5681 emitcode ("swap", "a");
5682 emitcode ("rl", "a");
5685 emitcode ("rr", "a");
5686 emitcode ("rr", "a");
5689 emitcode ("rr", "a");
5694 /*-----------------------------------------------------------------*/
5695 /* AccLsh - left shift accumulator by known count */
5696 /*-----------------------------------------------------------------*/
5698 AccLsh (int shCount)
5703 emitcode ("add", "a,acc");
5704 else if (shCount == 2)
5706 emitcode ("add", "a,acc");
5707 emitcode ("add", "a,acc");
5711 /* rotate left accumulator */
5713 /* and kill the lower order bits */
5714 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5719 /*-----------------------------------------------------------------*/
5720 /* AccRsh - right shift accumulator by known count */
5721 /*-----------------------------------------------------------------*/
5723 AccRsh (int shCount)
5730 emitcode ("rrc", "a");
5734 /* rotate right accumulator */
5735 AccRol (8 - shCount);
5736 /* and kill the higher order bits */
5737 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5742 /*-----------------------------------------------------------------*/
5743 /* AccSRsh - signed right shift accumulator by known count */
5744 /*-----------------------------------------------------------------*/
5746 AccSRsh (int shCount)
5753 emitcode ("mov", "c,acc.7");
5754 emitcode ("rrc", "a");
5756 else if (shCount == 2)
5758 emitcode ("mov", "c,acc.7");
5759 emitcode ("rrc", "a");
5760 emitcode ("mov", "c,acc.7");
5761 emitcode ("rrc", "a");
5765 tlbl = newiTempLabel (NULL);
5766 /* rotate right accumulator */
5767 AccRol (8 - shCount);
5768 /* and kill the higher order bits */
5769 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5770 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5771 emitcode ("orl", "a,#0x%02x",
5772 (unsigned char) ~SRMask[shCount]);
5773 emitcode ("", "%05d$:", tlbl->key + 100);
5778 /*-----------------------------------------------------------------*/
5779 /* shiftR1Left2Result - shift right one byte from left to result */
5780 /*-----------------------------------------------------------------*/
5782 shiftR1Left2Result (operand * left, int offl,
5783 operand * result, int offr,
5784 int shCount, int sign)
5786 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5787 /* shift right accumulator */
5792 aopPut (AOP (result), "a", offr);
5795 /*-----------------------------------------------------------------*/
5796 /* shiftL1Left2Result - shift left one byte from left to result */
5797 /*-----------------------------------------------------------------*/
5799 shiftL1Left2Result (operand * left, int offl,
5800 operand * result, int offr, int shCount)
5803 l = aopGet (AOP (left), offl, FALSE, FALSE);
5805 /* shift left accumulator */
5807 aopPut (AOP (result), "a", offr);
5810 /*-----------------------------------------------------------------*/
5811 /* movLeft2Result - move byte from left to result */
5812 /*-----------------------------------------------------------------*/
5814 movLeft2Result (operand * left, int offl,
5815 operand * result, int offr, int sign)
5818 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5820 l = aopGet (AOP (left), offl, FALSE, FALSE);
5822 if (*l == '@' && (IS_AOP_PREG (result)))
5824 emitcode ("mov", "a,%s", l);
5825 aopPut (AOP (result), "a", offr);
5830 aopPut (AOP (result), l, offr);
5833 /* MSB sign in acc.7 ! */
5834 if (getDataSize (left) == offl + 1)
5836 emitcode ("mov", "a,%s", l);
5837 aopPut (AOP (result), "a", offr);
5844 /*-----------------------------------------------------------------*/
5845 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5846 /*-----------------------------------------------------------------*/
5850 emitcode ("rrc", "a");
5851 emitcode ("xch", "a,%s", x);
5852 emitcode ("rrc", "a");
5853 emitcode ("xch", "a,%s", x);
5856 /*-----------------------------------------------------------------*/
5857 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5858 /*-----------------------------------------------------------------*/
5862 emitcode ("xch", "a,%s", x);
5863 emitcode ("rlc", "a");
5864 emitcode ("xch", "a,%s", x);
5865 emitcode ("rlc", "a");
5868 /*-----------------------------------------------------------------*/
5869 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5870 /*-----------------------------------------------------------------*/
5874 emitcode ("xch", "a,%s", x);
5875 emitcode ("add", "a,acc");
5876 emitcode ("xch", "a,%s", x);
5877 emitcode ("rlc", "a");
5880 /*-----------------------------------------------------------------*/
5881 /* AccAXLsh - left shift a:x by known count (0..7) */
5882 /*-----------------------------------------------------------------*/
5884 AccAXLsh (char *x, int shCount)
5899 case 5: // AAAAABBB:CCCCCDDD
5901 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5903 emitcode ("anl", "a,#0x%02x",
5904 SLMask[shCount]); // BBB00000:CCCCCDDD
5906 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5908 AccRol (shCount); // DDDCCCCC:BBB00000
5910 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5912 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5914 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5916 emitcode ("anl", "a,#0x%02x",
5917 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5919 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5921 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5924 case 6: // AAAAAABB:CCCCCCDD
5925 emitcode ("anl", "a,#0x%02x",
5926 SRMask[shCount]); // 000000BB:CCCCCCDD
5927 emitcode ("mov", "c,acc.0"); // c = B
5928 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5930 AccAXRrl1 (x); // BCCCCCCD:D000000B
5931 AccAXRrl1 (x); // BBCCCCCC:DD000000
5933 emitcode("rrc","a");
5934 emitcode("xch","a,%s", x);
5935 emitcode("rrc","a");
5936 emitcode("mov","c,acc.0"); //<< get correct bit
5937 emitcode("xch","a,%s", x);
5939 emitcode("rrc","a");
5940 emitcode("xch","a,%s", x);
5941 emitcode("rrc","a");
5942 emitcode("xch","a,%s", x);
5945 case 7: // a:x <<= 7
5947 emitcode ("anl", "a,#0x%02x",
5948 SRMask[shCount]); // 0000000B:CCCCCCCD
5950 emitcode ("mov", "c,acc.0"); // c = B
5952 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5954 AccAXRrl1 (x); // BCCCCCCC:D0000000
5962 /*-----------------------------------------------------------------*/
5963 /* AccAXRsh - right shift a:x known count (0..7) */
5964 /*-----------------------------------------------------------------*/
5966 AccAXRsh (char *x, int shCount)
5974 AccAXRrl1 (x); // 0->a:x
5979 AccAXRrl1 (x); // 0->a:x
5982 AccAXRrl1 (x); // 0->a:x
5987 case 5: // AAAAABBB:CCCCCDDD = a:x
5989 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5991 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5993 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5995 emitcode ("anl", "a,#0x%02x",
5996 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5998 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6000 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6002 emitcode ("anl", "a,#0x%02x",
6003 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6005 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6007 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6009 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6012 case 6: // AABBBBBB:CCDDDDDD
6014 emitcode ("mov", "c,acc.7");
6015 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6017 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6019 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6021 emitcode ("anl", "a,#0x%02x",
6022 SRMask[shCount]); // 000000AA:BBBBBBCC
6025 case 7: // ABBBBBBB:CDDDDDDD
6027 emitcode ("mov", "c,acc.7"); // c = A
6029 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6031 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6033 emitcode ("anl", "a,#0x%02x",
6034 SRMask[shCount]); // 0000000A:BBBBBBBC
6042 /*-----------------------------------------------------------------*/
6043 /* AccAXRshS - right shift signed a:x known count (0..7) */
6044 /*-----------------------------------------------------------------*/
6046 AccAXRshS (char *x, int shCount)
6054 emitcode ("mov", "c,acc.7");
6055 AccAXRrl1 (x); // s->a:x
6059 emitcode ("mov", "c,acc.7");
6060 AccAXRrl1 (x); // s->a:x
6062 emitcode ("mov", "c,acc.7");
6063 AccAXRrl1 (x); // s->a:x
6068 case 5: // AAAAABBB:CCCCCDDD = a:x
6070 tlbl = newiTempLabel (NULL);
6071 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6073 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6075 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6077 emitcode ("anl", "a,#0x%02x",
6078 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6080 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6082 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6084 emitcode ("anl", "a,#0x%02x",
6085 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6087 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6089 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6091 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6093 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6094 emitcode ("orl", "a,#0x%02x",
6095 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6097 emitcode ("", "%05d$:", tlbl->key + 100);
6098 break; // SSSSAAAA:BBBCCCCC
6100 case 6: // AABBBBBB:CCDDDDDD
6102 tlbl = newiTempLabel (NULL);
6103 emitcode ("mov", "c,acc.7");
6104 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6106 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6108 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6110 emitcode ("anl", "a,#0x%02x",
6111 SRMask[shCount]); // 000000AA:BBBBBBCC
6113 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6114 emitcode ("orl", "a,#0x%02x",
6115 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6117 emitcode ("", "%05d$:", tlbl->key + 100);
6119 case 7: // ABBBBBBB:CDDDDDDD
6121 tlbl = newiTempLabel (NULL);
6122 emitcode ("mov", "c,acc.7"); // c = A
6124 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6126 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6128 emitcode ("anl", "a,#0x%02x",
6129 SRMask[shCount]); // 0000000A:BBBBBBBC
6131 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6132 emitcode ("orl", "a,#0x%02x",
6133 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6135 emitcode ("", "%05d$:", tlbl->key + 100);
6142 /*-----------------------------------------------------------------*/
6143 /* shiftL2Left2Result - shift left two bytes from left to result */
6144 /*-----------------------------------------------------------------*/
6146 shiftL2Left2Result (operand * left, int offl,
6147 operand * result, int offr, int shCount)
6149 if (sameRegs (AOP (result), AOP (left)) &&
6150 ((offl + MSB16) == offr))
6152 /* don't crash result[offr] */
6153 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6154 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6158 movLeft2Result (left, offl, result, offr, 0);
6159 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6161 /* ax << shCount (x = lsb(result)) */
6162 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6163 aopPut (AOP (result), "a", offr + MSB16);
6167 /*-----------------------------------------------------------------*/
6168 /* shiftR2Left2Result - shift right two bytes from left to result */
6169 /*-----------------------------------------------------------------*/
6171 shiftR2Left2Result (operand * left, int offl,
6172 operand * result, int offr,
6173 int shCount, int sign)
6175 if (sameRegs (AOP (result), AOP (left)) &&
6176 ((offl + MSB16) == offr))
6178 /* don't crash result[offr] */
6179 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6180 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6184 movLeft2Result (left, offl, result, offr, 0);
6185 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6187 /* a:x >> shCount (x = lsb(result)) */
6189 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6191 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6192 if (getDataSize (result) > 1)
6193 aopPut (AOP (result), "a", offr + MSB16);
6196 /*-----------------------------------------------------------------*/
6197 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6198 /*-----------------------------------------------------------------*/
6200 shiftLLeftOrResult (operand * left, int offl,
6201 operand * result, int offr, int shCount)
6203 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6204 /* shift left accumulator */
6206 /* or with result */
6207 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6208 /* back to result */
6209 aopPut (AOP (result), "a", offr);
6212 /*-----------------------------------------------------------------*/
6213 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6214 /*-----------------------------------------------------------------*/
6216 shiftRLeftOrResult (operand * left, int offl,
6217 operand * result, int offr, int shCount)
6219 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6220 /* shift right accumulator */
6222 /* or with result */
6223 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6224 /* back to result */
6225 aopPut (AOP (result), "a", offr);
6228 /*-----------------------------------------------------------------*/
6229 /* genlshOne - left shift a one byte quantity by known count */
6230 /*-----------------------------------------------------------------*/
6232 genlshOne (operand * result, operand * left, int shCount)
6234 D(emitcode (";", "genlshOne"));
6236 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6239 /*-----------------------------------------------------------------*/
6240 /* genlshTwo - left shift two bytes by known amount != 0 */
6241 /*-----------------------------------------------------------------*/
6243 genlshTwo (operand * result, operand * left, int shCount)
6247 D(emitcode (";", "genlshTwo"));
6249 size = getDataSize (result);
6251 /* if shCount >= 8 */
6259 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6261 movLeft2Result (left, LSB, result, MSB16, 0);
6263 aopPut (AOP (result), zero, LSB);
6266 /* 1 <= shCount <= 7 */
6270 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6272 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6276 /*-----------------------------------------------------------------*/
6277 /* shiftLLong - shift left one long from left to result */
6278 /* offl = LSB or MSB16 */
6279 /*-----------------------------------------------------------------*/
6281 shiftLLong (operand * left, operand * result, int offr)
6284 int size = AOP_SIZE (result);
6286 if (size >= LSB + offr)
6288 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6290 emitcode ("add", "a,acc");
6291 if (sameRegs (AOP (left), AOP (result)) &&
6292 size >= MSB16 + offr && offr != LSB)
6293 emitcode ("xch", "a,%s",
6294 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6296 aopPut (AOP (result), "a", LSB + offr);
6299 if (size >= MSB16 + offr)
6301 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6303 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6306 emitcode ("rlc", "a");
6307 if (sameRegs (AOP (left), AOP (result)) &&
6308 size >= MSB24 + offr && offr != LSB)
6309 emitcode ("xch", "a,%s",
6310 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6312 aopPut (AOP (result), "a", MSB16 + offr);
6315 if (size >= MSB24 + offr)
6317 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6319 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6322 emitcode ("rlc", "a");
6323 if (sameRegs (AOP (left), AOP (result)) &&
6324 size >= MSB32 + offr && offr != LSB)
6325 emitcode ("xch", "a,%s",
6326 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6328 aopPut (AOP (result), "a", MSB24 + offr);
6331 if (size > MSB32 + offr)
6333 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6335 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6338 emitcode ("rlc", "a");
6339 aopPut (AOP (result), "a", MSB32 + offr);
6342 aopPut (AOP (result), zero, LSB);
6345 /*-----------------------------------------------------------------*/
6346 /* genlshFour - shift four byte by a known amount != 0 */
6347 /*-----------------------------------------------------------------*/
6349 genlshFour (operand * result, operand * left, int shCount)
6353 D(emitcode (";", "genlshFour"));
6355 size = AOP_SIZE (result);
6357 /* if shifting more that 3 bytes */
6362 /* lowest order of left goes to the highest
6363 order of the destination */
6364 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6366 movLeft2Result (left, LSB, result, MSB32, 0);
6367 aopPut (AOP (result), zero, LSB);
6368 aopPut (AOP (result), zero, MSB16);
6369 aopPut (AOP (result), zero, MSB24);
6373 /* more than two bytes */
6374 else if (shCount >= 16)
6376 /* lower order two bytes goes to higher order two bytes */
6378 /* if some more remaining */
6380 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6383 movLeft2Result (left, MSB16, result, MSB32, 0);
6384 movLeft2Result (left, LSB, result, MSB24, 0);
6386 aopPut (AOP (result), zero, MSB16);
6387 aopPut (AOP (result), zero, LSB);
6391 /* if more than 1 byte */
6392 else if (shCount >= 8)
6394 /* lower order three bytes goes to higher order three bytes */
6399 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6401 movLeft2Result (left, LSB, result, MSB16, 0);
6407 movLeft2Result (left, MSB24, result, MSB32, 0);
6408 movLeft2Result (left, MSB16, result, MSB24, 0);
6409 movLeft2Result (left, LSB, result, MSB16, 0);
6410 aopPut (AOP (result), zero, LSB);
6412 else if (shCount == 1)
6413 shiftLLong (left, result, MSB16);
6416 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6417 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6418 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6419 aopPut (AOP (result), zero, LSB);
6424 /* 1 <= shCount <= 7 */
6425 else if (shCount <= 2)
6427 shiftLLong (left, result, LSB);
6429 shiftLLong (result, result, LSB);
6431 /* 3 <= shCount <= 7, optimize */
6434 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6435 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6436 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6440 /*-----------------------------------------------------------------*/
6441 /* genLeftShiftLiteral - left shifting by known count */
6442 /*-----------------------------------------------------------------*/
6444 genLeftShiftLiteral (operand * left,
6449 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6452 D(emitcode (";", "genLeftShiftLiteral"));
6454 freeAsmop (right, NULL, ic, TRUE);
6456 aopOp (left, ic, FALSE);
6457 aopOp (result, ic, FALSE);
6459 size = getSize (operandType (result));
6462 emitcode ("; shift left ", "result %d, left %d", size,
6466 /* I suppose that the left size >= result size */
6471 movLeft2Result (left, size, result, size, 0);
6475 else if (shCount >= (size * 8))
6477 aopPut (AOP (result), zero, size);
6483 genlshOne (result, left, shCount);
6487 genlshTwo (result, left, shCount);
6491 genlshFour (result, left, shCount);
6494 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6495 "*** ack! mystery literal shift!\n");
6499 freeAsmop (left, NULL, ic, TRUE);
6500 freeAsmop (result, NULL, ic, TRUE);
6503 /*-----------------------------------------------------------------*/
6504 /* genLeftShift - generates code for left shifting */
6505 /*-----------------------------------------------------------------*/
6507 genLeftShift (iCode * ic)
6509 operand *left, *right, *result;
6512 symbol *tlbl, *tlbl1;
6514 D(emitcode (";", "genLeftShift"));
6516 right = IC_RIGHT (ic);
6517 left = IC_LEFT (ic);
6518 result = IC_RESULT (ic);
6520 aopOp (right, ic, FALSE);
6522 /* if the shift count is known then do it
6523 as efficiently as possible */
6524 if (AOP_TYPE (right) == AOP_LIT)
6526 genLeftShiftLiteral (left, right, result, ic);
6530 /* shift count is unknown then we have to form
6531 a loop get the loop count in B : Note: we take
6532 only the lower order byte since shifting
6533 more that 32 bits make no sense anyway, ( the
6534 largest size of an object can be only 32 bits ) */
6536 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6537 emitcode ("inc", "b");
6538 freeAsmop (right, NULL, ic, TRUE);
6539 aopOp (left, ic, FALSE);
6540 aopOp (result, ic, FALSE);
6542 /* now move the left to the result if they are not the
6544 if (!sameRegs (AOP (left), AOP (result)) &&
6545 AOP_SIZE (result) > 1)
6548 size = AOP_SIZE (result);
6552 l = aopGet (AOP (left), offset, FALSE, TRUE);
6553 if (*l == '@' && (IS_AOP_PREG (result)))
6556 emitcode ("mov", "a,%s", l);
6557 aopPut (AOP (result), "a", offset);
6560 aopPut (AOP (result), l, offset);
6565 tlbl = newiTempLabel (NULL);
6566 size = AOP_SIZE (result);
6568 tlbl1 = newiTempLabel (NULL);
6570 /* if it is only one byte then */
6573 symbol *tlbl1 = newiTempLabel (NULL);
6575 l = aopGet (AOP (left), 0, FALSE, FALSE);
6577 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6578 emitcode ("", "%05d$:", tlbl->key + 100);
6579 emitcode ("add", "a,acc");
6580 emitcode ("", "%05d$:", tlbl1->key + 100);
6581 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6582 aopPut (AOP (result), "a", 0);
6586 reAdjustPreg (AOP (result));
6588 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6589 emitcode ("", "%05d$:", tlbl->key + 100);
6590 l = aopGet (AOP (result), offset, FALSE, FALSE);
6592 emitcode ("add", "a,acc");
6593 aopPut (AOP (result), "a", offset++);
6596 l = aopGet (AOP (result), offset, FALSE, FALSE);
6598 emitcode ("rlc", "a");
6599 aopPut (AOP (result), "a", offset++);
6601 reAdjustPreg (AOP (result));
6603 emitcode ("", "%05d$:", tlbl1->key + 100);
6604 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6606 freeAsmop (left, NULL, ic, TRUE);
6607 freeAsmop (result, NULL, ic, TRUE);
6610 /*-----------------------------------------------------------------*/
6611 /* genrshOne - right shift a one byte quantity by known count */
6612 /*-----------------------------------------------------------------*/
6614 genrshOne (operand * result, operand * left,
6615 int shCount, int sign)
6617 D(emitcode (";", "genrshOne"));
6619 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6622 /*-----------------------------------------------------------------*/
6623 /* genrshTwo - right shift two bytes by known amount != 0 */
6624 /*-----------------------------------------------------------------*/
6626 genrshTwo (operand * result, operand * left,
6627 int shCount, int sign)
6629 D(emitcode (";", "genrshTwo"));
6631 /* if shCount >= 8 */
6636 shiftR1Left2Result (left, MSB16, result, LSB,
6639 movLeft2Result (left, MSB16, result, LSB, sign);
6640 addSign (result, MSB16, sign);
6643 /* 1 <= shCount <= 7 */
6645 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6648 /*-----------------------------------------------------------------*/
6649 /* shiftRLong - shift right one long from left to result */
6650 /* offl = LSB or MSB16 */
6651 /*-----------------------------------------------------------------*/
6653 shiftRLong (operand * left, int offl,
6654 operand * result, int sign)
6656 int isSameRegs=sameRegs(AOP(left),AOP(result));
6658 if (isSameRegs && offl>1) {
6659 // we are in big trouble, but this shouldn't happen
6660 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6663 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6668 emitcode ("rlc", "a");
6669 emitcode ("subb", "a,acc");
6670 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6672 aopPut (AOP(result), zero, MSB32);
6677 emitcode ("clr", "c");
6679 emitcode ("mov", "c,acc.7");
6682 emitcode ("rrc", "a");
6684 if (isSameRegs && offl==MSB16) {
6685 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6687 aopPut (AOP (result), "a", MSB32);
6688 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6691 emitcode ("rrc", "a");
6692 if (isSameRegs && offl==1) {
6693 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6695 aopPut (AOP (result), "a", MSB24);
6696 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6698 emitcode ("rrc", "a");
6699 aopPut (AOP (result), "a", MSB16 - offl);
6703 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6704 emitcode ("rrc", "a");
6705 aopPut (AOP (result), "a", LSB);
6709 /*-----------------------------------------------------------------*/
6710 /* genrshFour - shift four byte by a known amount != 0 */
6711 /*-----------------------------------------------------------------*/
6713 genrshFour (operand * result, operand * left,
6714 int shCount, int sign)
6716 D(emitcode (";", "genrshFour"));
6718 /* if shifting more that 3 bytes */
6723 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6725 movLeft2Result (left, MSB32, result, LSB, sign);
6726 addSign (result, MSB16, sign);
6728 else if (shCount >= 16)
6732 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6735 movLeft2Result (left, MSB24, result, LSB, 0);
6736 movLeft2Result (left, MSB32, result, MSB16, sign);
6738 addSign (result, MSB24, sign);
6740 else if (shCount >= 8)
6744 shiftRLong (left, MSB16, result, sign);
6745 else if (shCount == 0)
6747 movLeft2Result (left, MSB16, result, LSB, 0);
6748 movLeft2Result (left, MSB24, result, MSB16, 0);
6749 movLeft2Result (left, MSB32, result, MSB24, sign);
6750 addSign (result, MSB32, sign);
6754 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6755 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6756 /* the last shift is signed */
6757 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6758 addSign (result, MSB32, sign);
6762 { /* 1 <= shCount <= 7 */
6765 shiftRLong (left, LSB, result, sign);
6767 shiftRLong (result, LSB, result, sign);
6771 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6772 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6773 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6778 /*-----------------------------------------------------------------*/
6779 /* genRightShiftLiteral - right shifting by known count */
6780 /*-----------------------------------------------------------------*/
6782 genRightShiftLiteral (operand * left,
6788 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6791 D(emitcode (";", "genRightShiftLiteral"));
6793 freeAsmop (right, NULL, ic, TRUE);
6795 aopOp (left, ic, FALSE);
6796 aopOp (result, ic, FALSE);
6799 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6803 size = getDataSize (left);
6804 /* test the LEFT size !!! */
6806 /* I suppose that the left size >= result size */
6809 size = getDataSize (result);
6811 movLeft2Result (left, size, result, size, 0);
6814 else if (shCount >= (size * 8))
6817 /* get sign in acc.7 */
6818 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6819 addSign (result, LSB, sign);
6826 genrshOne (result, left, shCount, sign);
6830 genrshTwo (result, left, shCount, sign);
6834 genrshFour (result, left, shCount, sign);
6840 freeAsmop (left, NULL, ic, TRUE);
6841 freeAsmop (result, NULL, ic, TRUE);
6845 /*-----------------------------------------------------------------*/
6846 /* genSignedRightShift - right shift of signed number */
6847 /*-----------------------------------------------------------------*/
6849 genSignedRightShift (iCode * ic)
6851 operand *right, *left, *result;
6854 symbol *tlbl, *tlbl1;
6856 D(emitcode (";", "genSignedRightShift"));
6858 /* we do it the hard way put the shift count in b
6859 and loop thru preserving the sign */
6861 right = IC_RIGHT (ic);
6862 left = IC_LEFT (ic);
6863 result = IC_RESULT (ic);
6865 aopOp (right, ic, FALSE);
6868 if (AOP_TYPE (right) == AOP_LIT)
6870 genRightShiftLiteral (left, right, result, ic, 1);
6873 /* shift count is unknown then we have to form
6874 a loop get the loop count in B : Note: we take
6875 only the lower order byte since shifting
6876 more that 32 bits make no sense anyway, ( the
6877 largest size of an object can be only 32 bits ) */
6879 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6880 emitcode ("inc", "b");
6881 freeAsmop (right, NULL, ic, TRUE);
6882 aopOp (left, ic, FALSE);
6883 aopOp (result, ic, FALSE);
6885 /* now move the left to the result if they are not the
6887 if (!sameRegs (AOP (left), AOP (result)) &&
6888 AOP_SIZE (result) > 1)
6891 size = AOP_SIZE (result);
6895 l = aopGet (AOP (left), offset, FALSE, TRUE);
6896 if (*l == '@' && IS_AOP_PREG (result))
6899 emitcode ("mov", "a,%s", l);
6900 aopPut (AOP (result), "a", offset);
6903 aopPut (AOP (result), l, offset);
6908 /* mov the highest order bit to OVR */
6909 tlbl = newiTempLabel (NULL);
6910 tlbl1 = newiTempLabel (NULL);
6912 size = AOP_SIZE (result);
6914 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6915 emitcode ("rlc", "a");
6916 emitcode ("mov", "ov,c");
6917 /* if it is only one byte then */
6920 l = aopGet (AOP (left), 0, FALSE, FALSE);
6922 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6923 emitcode ("", "%05d$:", tlbl->key + 100);
6924 emitcode ("mov", "c,ov");
6925 emitcode ("rrc", "a");
6926 emitcode ("", "%05d$:", tlbl1->key + 100);
6927 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6928 aopPut (AOP (result), "a", 0);
6932 reAdjustPreg (AOP (result));
6933 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6934 emitcode ("", "%05d$:", tlbl->key + 100);
6935 emitcode ("mov", "c,ov");
6938 l = aopGet (AOP (result), offset, FALSE, FALSE);
6940 emitcode ("rrc", "a");
6941 aopPut (AOP (result), "a", offset--);
6943 reAdjustPreg (AOP (result));
6944 emitcode ("", "%05d$:", tlbl1->key + 100);
6945 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6948 freeAsmop (left, NULL, ic, TRUE);
6949 freeAsmop (result, NULL, ic, TRUE);
6952 /*-----------------------------------------------------------------*/
6953 /* genRightShift - generate code for right shifting */
6954 /*-----------------------------------------------------------------*/
6956 genRightShift (iCode * ic)
6958 operand *right, *left, *result;
6962 symbol *tlbl, *tlbl1;
6964 D(emitcode (";", "genRightShift"));
6966 /* if signed then we do it the hard way preserve the
6967 sign bit moving it inwards */
6968 retype = getSpec (operandType (IC_RESULT (ic)));
6970 if (!SPEC_USIGN (retype))
6972 genSignedRightShift (ic);
6976 /* signed & unsigned types are treated the same : i.e. the
6977 signed is NOT propagated inwards : quoting from the
6978 ANSI - standard : "for E1 >> E2, is equivalent to division
6979 by 2**E2 if unsigned or if it has a non-negative value,
6980 otherwise the result is implementation defined ", MY definition
6981 is that the sign does not get propagated */
6983 right = IC_RIGHT (ic);
6984 left = IC_LEFT (ic);
6985 result = IC_RESULT (ic);
6987 aopOp (right, ic, FALSE);
6989 /* if the shift count is known then do it
6990 as efficiently as possible */
6991 if (AOP_TYPE (right) == AOP_LIT)
6993 genRightShiftLiteral (left, right, result, ic, 0);
6997 /* shift count is unknown then we have to form
6998 a loop get the loop count in B : Note: we take
6999 only the lower order byte since shifting
7000 more that 32 bits make no sense anyway, ( the
7001 largest size of an object can be only 32 bits ) */
7003 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7004 emitcode ("inc", "b");
7005 freeAsmop (right, NULL, ic, TRUE);
7006 aopOp (left, ic, FALSE);
7007 aopOp (result, ic, FALSE);
7009 /* now move the left to the result if they are not the
7011 if (!sameRegs (AOP (left), AOP (result)) &&
7012 AOP_SIZE (result) > 1)
7015 size = AOP_SIZE (result);
7019 l = aopGet (AOP (left), offset, FALSE, TRUE);
7020 if (*l == '@' && IS_AOP_PREG (result))
7023 emitcode ("mov", "a,%s", l);
7024 aopPut (AOP (result), "a", offset);
7027 aopPut (AOP (result), l, offset);
7032 tlbl = newiTempLabel (NULL);
7033 tlbl1 = newiTempLabel (NULL);
7034 size = AOP_SIZE (result);
7037 /* if it is only one byte then */
7040 l = aopGet (AOP (left), 0, FALSE, FALSE);
7042 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7043 emitcode ("", "%05d$:", tlbl->key + 100);
7045 emitcode ("rrc", "a");
7046 emitcode ("", "%05d$:", tlbl1->key + 100);
7047 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7048 aopPut (AOP (result), "a", 0);
7052 reAdjustPreg (AOP (result));
7053 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7054 emitcode ("", "%05d$:", tlbl->key + 100);
7058 l = aopGet (AOP (result), offset, FALSE, FALSE);
7060 emitcode ("rrc", "a");
7061 aopPut (AOP (result), "a", offset--);
7063 reAdjustPreg (AOP (result));
7065 emitcode ("", "%05d$:", tlbl1->key + 100);
7066 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7069 freeAsmop (left, NULL, ic, TRUE);
7070 freeAsmop (result, NULL, ic, TRUE);
7073 /*-----------------------------------------------------------------*/
7074 /* genUnpackBits - generates code for unpacking bits */
7075 /*-----------------------------------------------------------------*/
7077 genUnpackBits (operand * result, char *rname, int ptype)
7085 D(emitcode (";", "genUnpackBits"));
7087 etype = getSpec (operandType (result));
7088 rsize = getSize (operandType (result));
7089 /* read the first byte */
7095 emitcode ("mov", "a,@%s", rname);
7099 emitcode ("movx", "a,@%s", rname);
7103 emitcode ("movx", "a,@dptr");
7107 emitcode ("clr", "a");
7108 emitcode ("movc", "a,@a+dptr");
7112 emitcode ("lcall", "__gptrget");
7116 rlen = SPEC_BLEN (etype);
7118 /* if we have bitdisplacement then it fits */
7119 /* into this byte completely or if length is */
7120 /* less than a byte */
7121 if ((shCnt = SPEC_BSTR (etype)) ||
7122 (SPEC_BLEN (etype) <= 8))
7125 /* shift right acc */
7128 emitcode ("anl", "a,#0x%02x",
7129 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7130 aopPut (AOP (result), "a", offset++);
7134 /* bit field did not fit in a byte */
7135 aopPut (AOP (result), "a", offset++);
7144 emitcode ("inc", "%s", rname);
7145 emitcode ("mov", "a,@%s", rname);
7149 emitcode ("inc", "%s", rname);
7150 emitcode ("movx", "a,@%s", rname);
7154 emitcode ("inc", "dptr");
7155 emitcode ("movx", "a,@dptr");
7159 emitcode ("clr", "a");
7160 emitcode ("inc", "dptr");
7161 emitcode ("movc", "a,@a+dptr");
7165 emitcode ("inc", "dptr");
7166 emitcode ("lcall", "__gptrget");
7171 /* if we are done */
7175 aopPut (AOP (result), "a", offset++);
7181 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7183 aopPut (AOP (result), "a", offset++);
7191 aopPut (AOP (result), zero, offset++);
7197 /*-----------------------------------------------------------------*/
7198 /* genDataPointerGet - generates code when ptr offset is known */
7199 /*-----------------------------------------------------------------*/
7201 genDataPointerGet (operand * left,
7207 int size, offset = 0;
7209 D(emitcode (";", "genDataPointerGet"));
7211 aopOp (result, ic, TRUE);
7213 /* get the string representation of the name */
7214 l = aopGet (AOP (left), 0, FALSE, TRUE);
7215 size = AOP_SIZE (result);
7219 sprintf (buffer, "(%s + %d)", l + 1, offset);
7221 sprintf (buffer, "%s", l + 1);
7222 aopPut (AOP (result), buffer, offset++);
7225 freeAsmop (left, NULL, ic, TRUE);
7226 freeAsmop (result, NULL, ic, TRUE);
7229 /*-----------------------------------------------------------------*/
7230 /* genNearPointerGet - emitcode for near pointer fetch */
7231 /*-----------------------------------------------------------------*/
7233 genNearPointerGet (operand * left,
7241 sym_link *rtype, *retype;
7242 sym_link *ltype = operandType (left);
7245 D(emitcode (";", "genNearPointerGet"));
7247 rtype = operandType (result);
7248 retype = getSpec (rtype);
7250 aopOp (left, ic, FALSE);
7252 /* if left is rematerialisable and
7253 result is not bit variable type and
7254 the left is pointer to data space i.e
7255 lower 128 bytes of space */
7256 if (AOP_TYPE (left) == AOP_IMMD &&
7257 !IS_BITVAR (retype) &&
7258 DCL_TYPE (ltype) == POINTER)
7260 genDataPointerGet (left, result, ic);
7264 /* if the value is already in a pointer register
7265 then don't need anything more */
7266 if (!AOP_INPREG (AOP (left)))
7268 /* otherwise get a free pointer register */
7270 preg = getFreePtr (ic, &aop, FALSE);
7271 emitcode ("mov", "%s,%s",
7273 aopGet (AOP (left), 0, FALSE, TRUE));
7277 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7279 //aopOp (result, ic, FALSE);
7280 aopOp (result, ic, result?TRUE:FALSE);
7282 /* if bitfield then unpack the bits */
7283 if (IS_BITVAR (retype))
7284 genUnpackBits (result, rname, POINTER);
7287 /* we have can just get the values */
7288 int size = AOP_SIZE (result);
7293 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7296 emitcode ("mov", "a,@%s", rname);
7297 aopPut (AOP (result), "a", offset);
7301 sprintf (buffer, "@%s", rname);
7302 aopPut (AOP (result), buffer, offset);
7306 emitcode ("inc", "%s", rname);
7310 /* now some housekeeping stuff */
7311 if (aop) /* we had to allocate for this iCode */
7313 if (pi) { /* post increment present */
7314 aopPut(AOP ( left ),rname,0);
7316 freeAsmop (NULL, aop, ic, TRUE);
7320 /* we did not allocate which means left
7321 already in a pointer register, then
7322 if size > 0 && this could be used again
7323 we have to point it back to where it
7325 if ((AOP_SIZE (result) > 1 &&
7326 !OP_SYMBOL (left)->remat &&
7327 (OP_SYMBOL (left)->liveTo > ic->seq ||
7331 int size = AOP_SIZE (result) - 1;
7333 emitcode ("dec", "%s", rname);
7338 freeAsmop (left, NULL, ic, TRUE);
7339 freeAsmop (result, NULL, ic, TRUE);
7340 if (pi) pi->generated = 1;
7343 /*-----------------------------------------------------------------*/
7344 /* genPagedPointerGet - emitcode for paged pointer fetch */
7345 /*-----------------------------------------------------------------*/
7347 genPagedPointerGet (operand * left,
7355 sym_link *rtype, *retype;
7357 D(emitcode (";", "genPagedPointerGet"));
7359 rtype = operandType (result);
7360 retype = getSpec (rtype);
7362 aopOp (left, ic, FALSE);
7364 /* if the value is already in a pointer register
7365 then don't need anything more */
7366 if (!AOP_INPREG (AOP (left)))
7368 /* otherwise get a free pointer register */
7370 preg = getFreePtr (ic, &aop, FALSE);
7371 emitcode ("mov", "%s,%s",
7373 aopGet (AOP (left), 0, FALSE, TRUE));
7377 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7379 aopOp (result, ic, FALSE);
7381 /* if bitfield then unpack the bits */
7382 if (IS_BITVAR (retype))
7383 genUnpackBits (result, rname, PPOINTER);
7386 /* we have can just get the values */
7387 int size = AOP_SIZE (result);
7393 emitcode ("movx", "a,@%s", rname);
7394 aopPut (AOP (result), "a", offset);
7399 emitcode ("inc", "%s", rname);
7403 /* now some housekeeping stuff */
7404 if (aop) /* we had to allocate for this iCode */
7406 if (pi) aopPut ( AOP (left), rname, 0);
7407 freeAsmop (NULL, aop, ic, TRUE);
7411 /* we did not allocate which means left
7412 already in a pointer register, then
7413 if size > 0 && this could be used again
7414 we have to point it back to where it
7416 if ((AOP_SIZE (result) > 1 &&
7417 !OP_SYMBOL (left)->remat &&
7418 (OP_SYMBOL (left)->liveTo > ic->seq ||
7422 int size = AOP_SIZE (result) - 1;
7424 emitcode ("dec", "%s", rname);
7429 freeAsmop (left, NULL, ic, TRUE);
7430 freeAsmop (result, NULL, ic, TRUE);
7431 if (pi) pi->generated = 1;
7435 /*-----------------------------------------------------------------*/
7436 /* genFarPointerGet - gget value from far space */
7437 /*-----------------------------------------------------------------*/
7439 genFarPointerGet (operand * left,
7440 operand * result, iCode * ic, iCode * pi)
7443 sym_link *retype = getSpec (operandType (result));
7445 D(emitcode (";", "genFarPointerGet"));
7447 aopOp (left, ic, FALSE);
7449 /* if the operand is already in dptr
7450 then we do nothing else we move the value to dptr */
7451 if (AOP_TYPE (left) != AOP_STR)
7453 /* if this is remateriazable */
7454 if (AOP_TYPE (left) == AOP_IMMD)
7455 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7457 { /* we need to get it byte by byte */
7458 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7459 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7462 /* so dptr know contains the address */
7463 aopOp (result, ic, FALSE);
7465 /* if bit then unpack */
7466 if (IS_BITVAR (retype))
7467 genUnpackBits (result, "dptr", FPOINTER);
7470 size = AOP_SIZE (result);
7475 emitcode ("movx", "a,@dptr");
7476 aopPut (AOP (result), "a", offset++);
7478 emitcode ("inc", "dptr");
7482 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7483 aopPut ( AOP (left), "dpl", 0);
7484 aopPut ( AOP (left), "dph", 1);
7487 freeAsmop (left, NULL, ic, TRUE);
7488 freeAsmop (result, NULL, ic, TRUE);
7491 /*-----------------------------------------------------------------*/
7492 /* genCodePointerGet - gget value from code space */
7493 /*-----------------------------------------------------------------*/
7495 genCodePointerGet (operand * left,
7496 operand * result, iCode * ic, iCode *pi)
7499 sym_link *retype = getSpec (operandType (result));
7501 D(emitcode (";", "genCodePointerGet"));
7503 aopOp (left, ic, FALSE);
7505 /* if the operand is already in dptr
7506 then we do nothing else we move the value to dptr */
7507 if (AOP_TYPE (left) != AOP_STR)
7509 /* if this is remateriazable */
7510 if (AOP_TYPE (left) == AOP_IMMD)
7511 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7513 { /* we need to get it byte by byte */
7514 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7515 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7518 /* so dptr know contains the address */
7519 aopOp (result, ic, FALSE);
7521 /* if bit then unpack */
7522 if (IS_BITVAR (retype))
7523 genUnpackBits (result, "dptr", CPOINTER);
7526 size = AOP_SIZE (result);
7531 emitcode ("clr", "a");
7532 emitcode ("movc", "a,@a+dptr");
7533 aopPut (AOP (result), "a", offset++);
7535 emitcode ("inc", "dptr");
7539 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7540 aopPut ( AOP (left), "dpl", 0);
7541 aopPut ( AOP (left), "dph", 1);
7544 freeAsmop (left, NULL, ic, TRUE);
7545 freeAsmop (result, NULL, ic, TRUE);
7548 /*-----------------------------------------------------------------*/
7549 /* genGenPointerGet - gget value from generic pointer space */
7550 /*-----------------------------------------------------------------*/
7552 genGenPointerGet (operand * left,
7553 operand * result, iCode * ic, iCode *pi)
7556 sym_link *retype = getSpec (operandType (result));
7558 D(emitcode (";", "genGenPointerGet"));
7560 aopOp (left, ic, FALSE);
7562 /* if the operand is already in dptr
7563 then we do nothing else we move the value to dptr */
7564 if (AOP_TYPE (left) != AOP_STR)
7566 /* if this is remateriazable */
7567 if (AOP_TYPE (left) == AOP_IMMD)
7569 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7570 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7571 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7573 emitcode ("mov", "b,#%d", pointerCode (retype));
7576 { /* we need to get it byte by byte */
7577 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7578 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7579 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7582 /* so dptr know contains the address */
7583 aopOp (result, ic, FALSE);
7585 /* if bit then unpack */
7586 if (IS_BITVAR (retype))
7587 genUnpackBits (result, "dptr", GPOINTER);
7590 size = AOP_SIZE (result);
7595 emitcode ("lcall", "__gptrget");
7596 aopPut (AOP (result), "a", offset++);
7598 emitcode ("inc", "dptr");
7602 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7603 aopPut ( AOP (left), "dpl", 0);
7604 aopPut ( AOP (left), "dph", 1);
7605 aopPut ( AOP (left), "b", 2);
7608 freeAsmop (left, NULL, ic, TRUE);
7609 freeAsmop (result, NULL, ic, TRUE);
7612 /*-----------------------------------------------------------------*/
7613 /* genPointerGet - generate code for pointer get */
7614 /*-----------------------------------------------------------------*/
7616 genPointerGet (iCode * ic, iCode *pi)
7618 operand *left, *result;
7619 sym_link *type, *etype;
7622 D(emitcode (";", "genPointerGet"));
7624 left = IC_LEFT (ic);
7625 result = IC_RESULT (ic);
7627 /* depending on the type of pointer we need to
7628 move it to the correct pointer register */
7629 type = operandType (left);
7630 etype = getSpec (type);
7631 /* if left is of type of pointer then it is simple */
7632 if (IS_PTR (type) && !IS_FUNC (type->next))
7633 p_type = DCL_TYPE (type);
7636 /* we have to go by the storage class */
7637 p_type = PTR_TYPE (SPEC_OCLS (etype));
7640 /* special case when cast remat */
7641 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7642 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7643 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7644 type = operandType (left);
7645 p_type = DCL_TYPE (type);
7647 /* now that we have the pointer type we assign
7648 the pointer values */
7654 genNearPointerGet (left, result, ic, pi);
7658 genPagedPointerGet (left, result, ic, pi);
7662 genFarPointerGet (left, result, ic, pi);
7666 genCodePointerGet (left, result, ic, pi);
7670 genGenPointerGet (left, result, ic, pi);
7676 /*-----------------------------------------------------------------*/
7677 /* genPackBits - generates code for packed bit storage */
7678 /*-----------------------------------------------------------------*/
7680 genPackBits (sym_link * etype,
7682 char *rname, int p_type)
7690 D(emitcode (";", "genPackBits"));
7692 blen = SPEC_BLEN (etype);
7693 bstr = SPEC_BSTR (etype);
7695 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7698 /* if the bit lenth is less than or */
7699 /* it exactly fits a byte then */
7700 if (SPEC_BLEN (etype) <= 8)
7702 shCount = SPEC_BSTR (etype);
7704 /* shift left acc */
7707 if (SPEC_BLEN (etype) < 8)
7708 { /* if smaller than a byte */
7714 emitcode ("mov", "b,a");
7715 emitcode ("mov", "a,@%s", rname);
7719 emitcode ("mov", "b,a");
7720 emitcode ("movx", "a,@dptr");
7724 emitcode ("push", "b");
7725 emitcode ("push", "acc");
7726 emitcode ("lcall", "__gptrget");
7727 emitcode ("pop", "b");
7731 emitcode ("anl", "a,#0x%02x", (unsigned char)
7732 ((unsigned char) (0xFF << (blen + bstr)) |
7733 (unsigned char) (0xFF >> (8 - bstr))));
7734 emitcode ("orl", "a,b");
7735 if (p_type == GPOINTER)
7736 emitcode ("pop", "b");
7743 emitcode ("mov", "@%s,a", rname);
7747 emitcode ("movx", "@dptr,a");
7751 emitcode ("lcall", "__gptrput");
7756 if (SPEC_BLEN (etype) <= 8)
7759 emitcode ("inc", "%s", rname);
7760 rLen = SPEC_BLEN (etype);
7762 /* now generate for lengths greater than one byte */
7766 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7778 emitcode ("mov", "@%s,a", rname);
7781 emitcode ("mov", "@%s,%s", rname, l);
7786 emitcode ("movx", "@dptr,a");
7791 emitcode ("lcall", "__gptrput");
7794 emitcode ("inc", "%s", rname);
7799 /* last last was not complete */
7802 /* save the byte & read byte */
7806 emitcode ("mov", "b,a");
7807 emitcode ("mov", "a,@%s", rname);
7811 emitcode ("mov", "b,a");
7812 emitcode ("movx", "a,@dptr");
7816 emitcode ("push", "b");
7817 emitcode ("push", "acc");
7818 emitcode ("lcall", "__gptrget");
7819 emitcode ("pop", "b");
7823 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7824 emitcode ("orl", "a,b");
7827 if (p_type == GPOINTER)
7828 emitcode ("pop", "b");
7834 emitcode ("mov", "@%s,a", rname);
7838 emitcode ("movx", "@dptr,a");
7842 emitcode ("lcall", "__gptrput");
7846 /*-----------------------------------------------------------------*/
7847 /* genDataPointerSet - remat pointer to data space */
7848 /*-----------------------------------------------------------------*/
7850 genDataPointerSet (operand * right,
7854 int size, offset = 0;
7855 char *l, buffer[256];
7857 D(emitcode (";", "genDataPointerSet"));
7859 aopOp (right, ic, FALSE);
7861 l = aopGet (AOP (result), 0, FALSE, TRUE);
7862 size = AOP_SIZE (right);
7866 sprintf (buffer, "(%s + %d)", l + 1, offset);
7868 sprintf (buffer, "%s", l + 1);
7869 emitcode ("mov", "%s,%s", buffer,
7870 aopGet (AOP (right), offset++, FALSE, FALSE));
7873 freeAsmop (right, NULL, ic, TRUE);
7874 freeAsmop (result, NULL, ic, TRUE);
7877 /*-----------------------------------------------------------------*/
7878 /* genNearPointerSet - emitcode for near pointer put */
7879 /*-----------------------------------------------------------------*/
7881 genNearPointerSet (operand * right,
7889 sym_link *retype, *letype;
7890 sym_link *ptype = operandType (result);
7892 D(emitcode (";", "genNearPointerSet"));
7894 retype = getSpec (operandType (right));
7895 letype = getSpec (ptype);
7896 aopOp (result, ic, FALSE);
7898 /* if the result is rematerializable &
7899 in data space & not a bit variable */
7900 if (AOP_TYPE (result) == AOP_IMMD &&
7901 DCL_TYPE (ptype) == POINTER &&
7902 !IS_BITVAR (retype) &&
7903 !IS_BITVAR (letype))
7905 genDataPointerSet (right, result, ic);
7909 /* if the value is already in a pointer register
7910 then don't need anything more */
7911 if (!AOP_INPREG (AOP (result)))
7914 //AOP_TYPE (result) == AOP_STK
7918 // Aha, it is a pointer, just in disguise.
7919 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7922 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7923 __FILE__, __LINE__);
7928 rname++; // skip the '@'.
7933 /* otherwise get a free pointer register */
7935 preg = getFreePtr (ic, &aop, FALSE);
7936 emitcode ("mov", "%s,%s",
7938 aopGet (AOP (result), 0, FALSE, TRUE));
7944 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7947 aopOp (right, ic, FALSE);
7949 /* if bitfield then unpack the bits */
7950 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7951 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7954 /* we have can just get the values */
7955 int size = AOP_SIZE (right);
7960 l = aopGet (AOP (right), offset, FALSE, TRUE);
7964 emitcode ("mov", "@%s,a", rname);
7967 emitcode ("mov", "@%s,%s", rname, l);
7969 emitcode ("inc", "%s", rname);
7974 /* now some housekeeping stuff */
7975 if (aop) /* we had to allocate for this iCode */
7977 if (pi) aopPut (AOP (result),rname,0);
7978 freeAsmop (NULL, aop, ic, TRUE);
7982 /* we did not allocate which means left
7983 already in a pointer register, then
7984 if size > 0 && this could be used again
7985 we have to point it back to where it
7987 if ((AOP_SIZE (right) > 1 &&
7988 !OP_SYMBOL (result)->remat &&
7989 (OP_SYMBOL (result)->liveTo > ic->seq ||
7993 int size = AOP_SIZE (right) - 1;
7995 emitcode ("dec", "%s", rname);
8000 if (pi) pi->generated = 1;
8001 freeAsmop (result, NULL, ic, TRUE);
8002 freeAsmop (right, NULL, ic, TRUE);
8005 /*-----------------------------------------------------------------*/
8006 /* genPagedPointerSet - emitcode for Paged pointer put */
8007 /*-----------------------------------------------------------------*/
8009 genPagedPointerSet (operand * right,
8017 sym_link *retype, *letype;
8019 D(emitcode (";", "genPagedPointerSet"));
8021 retype = getSpec (operandType (right));
8022 letype = getSpec (operandType (result));
8024 aopOp (result, ic, FALSE);
8026 /* if the value is already in a pointer register
8027 then don't need anything more */
8028 if (!AOP_INPREG (AOP (result)))
8030 /* otherwise get a free pointer register */
8032 preg = getFreePtr (ic, &aop, FALSE);
8033 emitcode ("mov", "%s,%s",
8035 aopGet (AOP (result), 0, FALSE, TRUE));
8039 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8041 aopOp (right, ic, FALSE);
8043 /* if bitfield then unpack the bits */
8044 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8045 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8048 /* we have can just get the values */
8049 int size = AOP_SIZE (right);
8054 l = aopGet (AOP (right), offset, FALSE, TRUE);
8057 emitcode ("movx", "@%s,a", rname);
8060 emitcode ("inc", "%s", rname);
8066 /* now some housekeeping stuff */
8067 if (aop) /* we had to allocate for this iCode */
8069 if (pi) aopPut (AOP (result),rname,0);
8070 freeAsmop (NULL, aop, ic, TRUE);
8074 /* we did not allocate which means left
8075 already in a pointer register, then
8076 if size > 0 && this could be used again
8077 we have to point it back to where it
8079 if (AOP_SIZE (right) > 1 &&
8080 !OP_SYMBOL (result)->remat &&
8081 (OP_SYMBOL (result)->liveTo > ic->seq ||
8084 int size = AOP_SIZE (right) - 1;
8086 emitcode ("dec", "%s", rname);
8091 if (pi) pi->generated = 1;
8092 freeAsmop (result, NULL, ic, TRUE);
8093 freeAsmop (right, NULL, ic, TRUE);
8098 /*-----------------------------------------------------------------*/
8099 /* genFarPointerSet - set value from far space */
8100 /*-----------------------------------------------------------------*/
8102 genFarPointerSet (operand * right,
8103 operand * result, iCode * ic, iCode * pi)
8106 sym_link *retype = getSpec (operandType (right));
8107 sym_link *letype = getSpec (operandType (result));
8109 D(emitcode (";", "genFarPointerSet"));
8111 aopOp (result, ic, FALSE);
8113 /* if the operand is already in dptr
8114 then we do nothing else we move the value to dptr */
8115 if (AOP_TYPE (result) != AOP_STR)
8117 /* if this is remateriazable */
8118 if (AOP_TYPE (result) == AOP_IMMD)
8119 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8121 { /* we need to get it byte by byte */
8122 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8123 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8126 /* so dptr know contains the address */
8127 aopOp (right, ic, FALSE);
8129 /* if bit then unpack */
8130 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8131 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8134 size = AOP_SIZE (right);
8139 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8141 emitcode ("movx", "@dptr,a");
8143 emitcode ("inc", "dptr");
8146 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8147 aopPut (AOP(result),"dpl",0);
8148 aopPut (AOP(result),"dph",1);
8151 freeAsmop (result, NULL, ic, TRUE);
8152 freeAsmop (right, NULL, ic, TRUE);
8155 /*-----------------------------------------------------------------*/
8156 /* genGenPointerSet - set value from generic pointer space */
8157 /*-----------------------------------------------------------------*/
8159 genGenPointerSet (operand * right,
8160 operand * result, iCode * ic, iCode * pi)
8163 sym_link *retype = getSpec (operandType (right));
8164 sym_link *letype = getSpec (operandType (result));
8166 D(emitcode (";", "genGenPointerSet"));
8168 aopOp (result, ic, FALSE);
8170 /* if the operand is already in dptr
8171 then we do nothing else we move the value to dptr */
8172 if (AOP_TYPE (result) != AOP_STR)
8174 /* if this is remateriazable */
8175 if (AOP_TYPE (result) == AOP_IMMD)
8177 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8178 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8179 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8181 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8184 { /* we need to get it byte by byte */
8185 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8186 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8187 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8190 /* so dptr know contains the address */
8191 aopOp (right, ic, FALSE);
8193 /* if bit then unpack */
8194 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8195 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8198 size = AOP_SIZE (right);
8203 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8205 emitcode ("lcall", "__gptrput");
8207 emitcode ("inc", "dptr");
8211 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8212 aopPut (AOP(result),"dpl",0);
8213 aopPut (AOP(result),"dph",1);
8214 aopPut (AOP(result),"b",2);
8217 freeAsmop (result, NULL, ic, TRUE);
8218 freeAsmop (right, NULL, ic, TRUE);
8221 /*-----------------------------------------------------------------*/
8222 /* genPointerSet - stores the value into a pointer location */
8223 /*-----------------------------------------------------------------*/
8225 genPointerSet (iCode * ic, iCode *pi)
8227 operand *right, *result;
8228 sym_link *type, *etype;
8231 D(emitcode (";", "genPointerSet"));
8233 right = IC_RIGHT (ic);
8234 result = IC_RESULT (ic);
8236 /* depending on the type of pointer we need to
8237 move it to the correct pointer register */
8238 type = operandType (result);
8239 etype = getSpec (type);
8240 /* if left is of type of pointer then it is simple */
8241 if (IS_PTR (type) && !IS_FUNC (type->next))
8243 p_type = DCL_TYPE (type);
8247 /* we have to go by the storage class */
8248 p_type = PTR_TYPE (SPEC_OCLS (etype));
8251 /* special case when cast remat */
8252 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8253 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8254 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8255 type = operandType (result);
8256 p_type = DCL_TYPE (type);
8258 /* now that we have the pointer type we assign
8259 the pointer values */
8265 genNearPointerSet (right, result, ic, pi);
8269 genPagedPointerSet (right, result, ic, pi);
8273 genFarPointerSet (right, result, ic, pi);
8277 genGenPointerSet (right, result, ic, pi);
8281 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8282 "genPointerSet: illegal pointer type");
8287 /*-----------------------------------------------------------------*/
8288 /* genIfx - generate code for Ifx statement */
8289 /*-----------------------------------------------------------------*/
8291 genIfx (iCode * ic, iCode * popIc)
8293 operand *cond = IC_COND (ic);
8296 D(emitcode (";", "genIfx"));
8298 aopOp (cond, ic, FALSE);
8300 /* get the value into acc */
8301 if (AOP_TYPE (cond) != AOP_CRY)
8305 /* the result is now in the accumulator */
8306 freeAsmop (cond, NULL, ic, TRUE);
8308 /* if there was something to be popped then do it */
8312 /* if the condition is a bit variable */
8313 if (isbit && IS_ITEMP (cond) &&
8315 genIfxJump (ic, SPIL_LOC (cond)->rname);
8316 else if (isbit && !IS_ITEMP (cond))
8317 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8319 genIfxJump (ic, "a");
8324 /*-----------------------------------------------------------------*/
8325 /* genAddrOf - generates code for address of */
8326 /*-----------------------------------------------------------------*/
8328 genAddrOf (iCode * ic)
8330 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8333 D(emitcode (";", "genAddrOf"));
8335 aopOp (IC_RESULT (ic), ic, FALSE);
8337 /* if the operand is on the stack then we
8338 need to get the stack offset of this
8342 /* if it has an offset then we need to compute
8346 emitcode ("mov", "a,_bp");
8347 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8348 ((char) (sym->stack - _G.nRegsSaved)) :
8349 ((char) sym->stack)) & 0xff);
8350 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8354 /* we can just move _bp */
8355 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8357 /* fill the result with zero */
8358 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8363 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8369 /* object not on stack then we need the name */
8370 size = AOP_SIZE (IC_RESULT (ic));
8375 char s[SDCC_NAME_MAX];
8377 sprintf (s, "#(%s >> %d)",
8381 sprintf (s, "#%s", sym->rname);
8382 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8386 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8390 /*-----------------------------------------------------------------*/
8391 /* genFarFarAssign - assignment when both are in far space */
8392 /*-----------------------------------------------------------------*/
8394 genFarFarAssign (operand * result, operand * right, iCode * ic)
8396 int size = AOP_SIZE (right);
8400 D(emitcode (";", "genFarFarAssign"));
8402 /* first push the right side on to the stack */
8405 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8407 emitcode ("push", "acc");
8410 freeAsmop (right, NULL, ic, FALSE);
8411 /* now assign DPTR to result */
8412 aopOp (result, ic, FALSE);
8413 size = AOP_SIZE (result);
8416 emitcode ("pop", "acc");
8417 aopPut (AOP (result), "a", --offset);
8419 freeAsmop (result, NULL, ic, FALSE);
8423 /*-----------------------------------------------------------------*/
8424 /* genAssign - generate code for assignment */
8425 /*-----------------------------------------------------------------*/
8427 genAssign (iCode * ic)
8429 operand *result, *right;
8431 unsigned long lit = 0L;
8433 D(emitcode(";","genAssign"));
8435 result = IC_RESULT (ic);
8436 right = IC_RIGHT (ic);
8438 /* if they are the same */
8439 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8442 aopOp (right, ic, FALSE);
8444 /* special case both in far space */
8445 if (AOP_TYPE (right) == AOP_DPTR &&
8446 IS_TRUE_SYMOP (result) &&
8447 isOperandInFarSpace (result))
8450 genFarFarAssign (result, right, ic);
8454 aopOp (result, ic, TRUE);
8456 /* if they are the same registers */
8457 if (sameRegs (AOP (right), AOP (result)))
8460 /* if the result is a bit */
8461 if (AOP_TYPE (result) == AOP_CRY)
8464 /* if the right size is a literal then
8465 we know what the value is */
8466 if (AOP_TYPE (right) == AOP_LIT)
8468 if (((int) operandLitValue (right)))
8469 aopPut (AOP (result), one, 0);
8471 aopPut (AOP (result), zero, 0);
8475 /* the right is also a bit variable */
8476 if (AOP_TYPE (right) == AOP_CRY)
8478 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8479 aopPut (AOP (result), "c", 0);
8485 aopPut (AOP (result), "a", 0);
8489 /* bit variables done */
8491 size = AOP_SIZE (result);
8493 if (AOP_TYPE (right) == AOP_LIT)
8494 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8496 (AOP_TYPE (result) != AOP_REG) &&
8497 (AOP_TYPE (right) == AOP_LIT) &&
8498 !IS_FLOAT (operandType (right)) &&
8501 emitcode ("clr", "a");
8504 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8505 aopPut (AOP (result), "a", size);
8507 aopPut (AOP (result),
8508 aopGet (AOP (right), size, FALSE, FALSE),
8516 aopPut (AOP (result),
8517 aopGet (AOP (right), offset, FALSE, FALSE),
8524 freeAsmop (right, NULL, ic, TRUE);
8525 freeAsmop (result, NULL, ic, TRUE);
8528 /*-----------------------------------------------------------------*/
8529 /* genJumpTab - genrates code for jump table */
8530 /*-----------------------------------------------------------------*/
8532 genJumpTab (iCode * ic)
8537 D(emitcode (";", "genJumpTab"));
8539 aopOp (IC_JTCOND (ic), ic, FALSE);
8540 /* get the condition into accumulator */
8541 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8543 /* multiply by three */
8544 emitcode ("add", "a,acc");
8545 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8546 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8548 jtab = newiTempLabel (NULL);
8549 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8550 emitcode ("jmp", "@a+dptr");
8551 emitcode ("", "%05d$:", jtab->key + 100);
8552 /* now generate the jump labels */
8553 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8554 jtab = setNextItem (IC_JTLABELS (ic)))
8555 emitcode ("ljmp", "%05d$", jtab->key + 100);
8559 /*-----------------------------------------------------------------*/
8560 /* genCast - gen code for casting */
8561 /*-----------------------------------------------------------------*/
8563 genCast (iCode * ic)
8565 operand *result = IC_RESULT (ic);
8566 sym_link *ctype = operandType (IC_LEFT (ic));
8567 sym_link *rtype = operandType (IC_RIGHT (ic));
8568 operand *right = IC_RIGHT (ic);
8571 D(emitcode(";", "genCast"));
8573 /* if they are equivalent then do nothing */
8574 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8577 aopOp (right, ic, FALSE);
8578 aopOp (result, ic, FALSE);
8580 /* if the result is a bit */
8581 if (IS_BITVAR(OP_SYMBOL(result)->type))
8583 /* if the right size is a literal then
8584 we know what the value is */
8585 if (AOP_TYPE (right) == AOP_LIT)
8587 if (((int) operandLitValue (right)))
8588 aopPut (AOP (result), one, 0);
8590 aopPut (AOP (result), zero, 0);
8595 /* the right is also a bit variable */
8596 if (AOP_TYPE (right) == AOP_CRY)
8598 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8599 aopPut (AOP (result), "c", 0);
8605 aopPut (AOP (result), "a", 0);
8609 /* if they are the same size : or less */
8610 if (AOP_SIZE (result) <= AOP_SIZE (right))
8613 /* if they are in the same place */
8614 if (sameRegs (AOP (right), AOP (result)))
8617 /* if they in different places then copy */
8618 size = AOP_SIZE (result);
8622 aopPut (AOP (result),
8623 aopGet (AOP (right), offset, FALSE, FALSE),
8631 /* if the result is of type pointer */
8636 sym_link *type = operandType (right);
8637 sym_link *etype = getSpec (type);
8639 /* pointer to generic pointer */
8640 if (IS_GENPTR (ctype))
8643 p_type = DCL_TYPE (type);
8646 if (SPEC_SCLS(etype)==S_REGISTER) {
8647 // let's assume it is a generic pointer
8650 /* we have to go by the storage class */
8651 p_type = PTR_TYPE (SPEC_OCLS (etype));
8655 /* the first two bytes are known */
8656 size = GPTRSIZE - 1;
8660 aopPut (AOP (result),
8661 aopGet (AOP (right), offset, FALSE, FALSE),
8665 /* the last byte depending on type */
8667 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8672 // pointerTypeToGPByte will have bitched.
8676 sprintf(gpValStr, "#0x%d", gpVal);
8677 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8682 /* just copy the pointers */
8683 size = AOP_SIZE (result);
8687 aopPut (AOP (result),
8688 aopGet (AOP (right), offset, FALSE, FALSE),
8695 /* so we now know that the size of destination is greater
8696 than the size of the source */
8697 /* we move to result for the size of source */
8698 size = AOP_SIZE (right);
8702 aopPut (AOP (result),
8703 aopGet (AOP (right), offset, FALSE, FALSE),
8708 /* now depending on the sign of the source && destination */
8709 size = AOP_SIZE (result) - AOP_SIZE (right);
8710 /* if unsigned or not an integral type */
8711 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8714 aopPut (AOP (result), zero, offset++);
8718 /* we need to extend the sign :{ */
8719 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8722 emitcode ("rlc", "a");
8723 emitcode ("subb", "a,acc");
8725 aopPut (AOP (result), "a", offset++);
8728 /* we are done hurray !!!! */
8731 freeAsmop (right, NULL, ic, TRUE);
8732 freeAsmop (result, NULL, ic, TRUE);
8736 /*-----------------------------------------------------------------*/
8737 /* genDjnz - generate decrement & jump if not zero instrucion */
8738 /*-----------------------------------------------------------------*/
8740 genDjnz (iCode * ic, iCode * ifx)
8746 D(emitcode (";", "genDjnz"));
8748 /* if the if condition has a false label
8749 then we cannot save */
8753 /* if the minus is not of the form
8755 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8756 !IS_OP_LITERAL (IC_RIGHT (ic)))
8759 if (operandLitValue (IC_RIGHT (ic)) != 1)
8762 /* if the size of this greater than one then no
8764 if (getSize (operandType (IC_RESULT (ic))) > 1)
8767 /* otherwise we can save BIG */
8768 lbl = newiTempLabel (NULL);
8769 lbl1 = newiTempLabel (NULL);
8771 aopOp (IC_RESULT (ic), ic, FALSE);
8773 if (AOP_NEEDSACC(IC_RESULT(ic)))
8775 /* If the result is accessed indirectly via
8776 * the accumulator, we must explicitly write
8777 * it back after the decrement.
8779 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8781 if (strcmp(rByte, "a"))
8783 /* Something is hopelessly wrong */
8784 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8785 __FILE__, __LINE__);
8786 /* We can just give up; the generated code will be inefficient,
8789 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8792 emitcode ("dec", "%s", rByte);
8793 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8794 emitcode ("jnz", "%05d$", lbl->key + 100);
8796 else if (IS_AOP_PREG (IC_RESULT (ic)))
8798 emitcode ("dec", "%s",
8799 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8800 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8801 emitcode ("jnz", "%05d$", lbl->key + 100);
8805 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8808 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8809 emitcode ("", "%05d$:", lbl->key + 100);
8810 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8811 emitcode ("", "%05d$:", lbl1->key + 100);
8813 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8818 /*-----------------------------------------------------------------*/
8819 /* genReceive - generate code for a receive iCode */
8820 /*-----------------------------------------------------------------*/
8822 genReceive (iCode * ic)
8824 int size = getSize (operandType (IC_RESULT (ic)));
8826 D(emitcode (";", "genReceive"));
8828 if (ic->argreg == 1) { /* first parameter */
8829 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8830 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8831 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8833 offset = fReturnSizeMCS51 - size;
8835 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8836 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8839 aopOp (IC_RESULT (ic), ic, FALSE);
8840 size = AOP_SIZE (IC_RESULT (ic));
8843 emitcode ("pop", "acc");
8844 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8849 aopOp (IC_RESULT (ic), ic, FALSE);
8851 assignResultValue (IC_RESULT (ic));
8853 } else { /* second receive onwards */
8855 aopOp (IC_RESULT (ic), ic, FALSE);
8856 rb1off = ic->argreg;
8858 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
8861 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8864 /*-----------------------------------------------------------------*/
8865 /* gen51Code - generate code for 8051 based controllers */
8866 /*-----------------------------------------------------------------*/
8868 gen51Code (iCode * lic)
8873 lineHead = lineCurr = NULL;
8875 /* print the allocation information */
8877 printAllocInfo (currFunc, codeOutFile);
8878 /* if debug information required */
8879 if (options.debug && currFunc)
8881 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8883 if (IS_STATIC (currFunc->etype))
8884 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8886 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8889 /* stack pointer name */
8890 if (options.useXstack)
8896 for (ic = lic; ic; ic = ic->next)
8899 if (ic->lineno && cln != ic->lineno)
8904 emitcode ("", "C$%s$%d$%d$%d ==.",
8905 FileBaseName (ic->filename), ic->lineno,
8906 ic->level, ic->block);
8909 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
8910 printCLine(ic->filename, ic->lineno));
8913 /* if the result is marked as
8914 spilt and rematerializable or code for
8915 this has already been generated then
8917 if (resultRemat (ic) || ic->generated)
8920 /* depending on the operation */
8940 /* IPOP happens only when trying to restore a
8941 spilt live range, if there is an ifx statement
8942 following this pop then the if statement might
8943 be using some of the registers being popped which
8944 would destory the contents of the register so
8945 we need to check for this condition and handle it */
8947 ic->next->op == IFX &&
8948 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8949 genIfx (ic->next, ic);
8967 genEndFunction (ic);
8987 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9004 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9008 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9015 /* note these two are xlated by algebraic equivalence
9016 during parsing SDCC.y */
9017 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9018 "got '>=' or '<=' shouldn't have come here");
9022 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9034 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9038 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9042 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9069 case GET_VALUE_AT_ADDRESS:
9070 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9074 if (POINTER_SET (ic))
9075 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9101 addSet (&_G.sendSet, ic);
9110 /* now we are ready to call the
9111 peep hole optimizer */
9112 if (!options.nopeep)
9113 peepHole (&lineHead);
9115 /* now do the actual printing */
9116 printLine (lineHead, codeOutFile);