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"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
79 static char *rb1regs[] = {
80 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
83 extern int mcs51_ptrRegReq;
84 extern int mcs51_nRegs;
85 extern FILE *codeOutFile;
86 static void saveRBank (int, iCode *, bool);
87 #define RESULTONSTACK(x) \
88 (IC_RESULT(x) && IC_RESULT(x)->aop && \
89 IC_RESULT(x)->aop->type == AOP_STK )
91 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
92 #define CLRC emitcode("clr","c")
93 #define SETC emitcode("setb","c")
95 static lineNode *lineHead = NULL;
96 static lineNode *lineCurr = NULL;
98 static unsigned char SLMask[] =
99 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
100 0xE0, 0xC0, 0x80, 0x00};
101 static unsigned char SRMask[] =
102 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
103 0x07, 0x03, 0x01, 0x00};
110 /*-----------------------------------------------------------------*/
111 /* emitcode - writes the code into a file : for now it is simple */
112 /*-----------------------------------------------------------------*/
114 emitcode (char *inst, const char *fmt,...)
117 char lb[INITIAL_INLINEASM];
125 sprintf (lb, "%s\t", inst);
127 sprintf (lb, "%s", inst);
128 vsprintf (lb + (strlen (lb)), fmt, ap);
131 vsprintf (lb, fmt, ap);
133 while (isspace (*lbp))
135 // printf ("%s\n", lb); // EEP - debugging
138 lineCurr = (lineCurr ?
139 connectLine (lineCurr, newLineNode (lb)) :
140 (lineHead = newLineNode (lb)));
141 lineCurr->isInline = _G.inLine;
142 lineCurr->isDebug = _G.debugLine;
146 /*-----------------------------------------------------------------*/
147 /* mova - moves specified value into accumulator */
148 /*-----------------------------------------------------------------*/
152 /* do some early peephole optimization */
153 if (!strcmp(x, "a") || !strcmp(x, "acc"))
156 emitcode("mov","a,%s", x);
159 /*-----------------------------------------------------------------*/
160 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
161 /*-----------------------------------------------------------------*/
163 getFreePtr (iCode * ic, asmop ** aopp, bool result)
165 bool r0iu = FALSE, r1iu = FALSE;
166 bool r0ou = FALSE, r1ou = FALSE;
168 /* the logic: if r0 & r1 used in the instruction
169 then we are in trouble otherwise */
171 /* first check if r0 & r1 are used by this
172 instruction, in which case we are in trouble */
173 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
174 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
179 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
180 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
182 /* if no usage of r0 then return it */
185 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
186 (*aopp)->type = AOP_R0;
188 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
191 /* if no usage of r1 then return it */
194 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
195 (*aopp)->type = AOP_R1;
197 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
200 /* now we know they both have usage */
201 /* if r0 not used in this instruction */
204 /* push it if not already pushed */
207 emitcode ("push", "%s",
208 mcs51_regWithIdx (R0_IDX)->dname);
212 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
213 (*aopp)->type = AOP_R0;
215 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
218 /* if r1 not used then */
222 /* push it if not already pushed */
225 emitcode ("push", "%s",
226 mcs51_regWithIdx (R1_IDX)->dname);
230 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
231 (*aopp)->type = AOP_R1;
232 return mcs51_regWithIdx (R1_IDX);
235 /* I said end of world, but not quite end of world yet */
237 /* we can push it on the stack */
238 (*aopp)->type = AOP_STK;
241 /* in the case that result AND left AND right needs a pointer reg
242 we can safely use the result's */
243 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
244 (*aopp)->type = AOP_R0;
245 return mcs51_regWithIdx (R0_IDX);
247 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
248 (*aopp)->type = AOP_R1;
249 return mcs51_regWithIdx (R1_IDX);
253 /* now this is REALLY the end of the world */
254 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
255 "getFreePtr should never reach here");
259 /*-----------------------------------------------------------------*/
260 /* newAsmop - creates a new asmOp */
261 /*-----------------------------------------------------------------*/
263 newAsmop (short type)
267 aop = Safe_calloc (1, sizeof (asmop));
272 /*-----------------------------------------------------------------*/
273 /* pointerCode - returns the code for a pointer type */
274 /*-----------------------------------------------------------------*/
276 pointerCode (sym_link * etype)
279 return PTR_TYPE (SPEC_OCLS (etype));
283 /*-----------------------------------------------------------------*/
284 /* aopForSym - for a true symbol */
285 /*-----------------------------------------------------------------*/
287 aopForSym (iCode * ic, symbol * sym, bool result)
292 wassertl (ic != NULL, "Got a null iCode");
293 wassertl (sym != NULL, "Got a null symbol");
295 space = SPEC_OCLS (sym->etype);
297 /* if already has one */
301 /* assign depending on the storage class */
302 /* if it is on the stack or indirectly addressable */
303 /* space we need to assign either r0 or r1 to it */
304 if (sym->onStack || sym->iaccess)
306 sym->aop = aop = newAsmop (0);
307 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
308 aop->size = getSize (sym->type);
310 /* now assign the address of the variable to
311 the pointer register */
312 if (aop->type != AOP_STK)
318 emitcode ("push", "acc");
320 emitcode ("mov", "a,_bp");
321 emitcode ("add", "a,#0x%02x",
323 ((char) (sym->stack - _G.nRegsSaved)) :
324 ((char) sym->stack)) & 0xff);
325 emitcode ("mov", "%s,a",
326 aop->aopu.aop_ptr->name);
329 emitcode ("pop", "acc");
332 emitcode ("mov", "%s,#%s",
333 aop->aopu.aop_ptr->name,
335 aop->paged = space->paged;
338 aop->aopu.aop_stk = sym->stack;
342 /* if in bit space */
343 if (IN_BITSPACE (space))
345 sym->aop = aop = newAsmop (AOP_CRY);
346 aop->aopu.aop_dir = sym->rname;
347 aop->size = getSize (sym->type);
350 /* if it is in direct space */
351 if (IN_DIRSPACE (space))
353 sym->aop = aop = newAsmop (AOP_DIR);
354 aop->aopu.aop_dir = sym->rname;
355 aop->size = getSize (sym->type);
359 /* special case for a function */
360 if (IS_FUNC (sym->type))
362 sym->aop = aop = newAsmop (AOP_IMMD);
363 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
364 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
365 aop->size = FPTRSIZE;
369 /* only remaining is far space */
370 /* in which case DPTR gets the address */
371 sym->aop = aop = newAsmop (AOP_DPTR);
372 emitcode ("mov", "dptr,#%s", sym->rname);
373 aop->size = getSize (sym->type);
375 /* if it is in code space */
376 if (IN_CODESPACE (space))
382 /*-----------------------------------------------------------------*/
383 /* aopForRemat - rematerialzes an object */
384 /*-----------------------------------------------------------------*/
386 aopForRemat (symbol * sym)
388 iCode *ic = sym->rematiCode;
389 asmop *aop = newAsmop (AOP_IMMD);
396 val += (int) operandLitValue (IC_RIGHT (ic));
397 else if (ic->op == '-')
398 val -= (int) operandLitValue (IC_RIGHT (ic));
399 else if (IS_CAST_ICODE(ic)) {
400 sym_link *from_type = operandType(IC_RIGHT(ic));
401 aop->aopu.aop_immd.from_cast_remat = 1;
402 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
403 ptr_type = DCL_TYPE(from_type);
404 if (ptr_type == IPOINTER) {
411 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
415 sprintf (buffer, "(%s %c 0x%04x)",
416 OP_SYMBOL (IC_LEFT (ic))->rname,
417 val >= 0 ? '+' : '-',
420 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
422 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
423 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
424 /* set immd2 field if required */
425 if (aop->aopu.aop_immd.from_cast_remat) {
426 sprintf(buffer,"#0x%02x",ptr_type);
427 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
428 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
434 /*-----------------------------------------------------------------*/
435 /* regsInCommon - two operands have some registers in common */
436 /*-----------------------------------------------------------------*/
438 regsInCommon (operand * op1, operand * op2)
443 /* if they have registers in common */
444 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
447 sym1 = OP_SYMBOL (op1);
448 sym2 = OP_SYMBOL (op2);
450 if (sym1->nRegs == 0 || sym2->nRegs == 0)
453 for (i = 0; i < sym1->nRegs; i++)
459 for (j = 0; j < sym2->nRegs; j++)
464 if (sym2->regs[j] == sym1->regs[i])
472 /*-----------------------------------------------------------------*/
473 /* operandsEqu - equivalent */
474 /*-----------------------------------------------------------------*/
476 operandsEqu (operand * op1, operand * op2)
480 /* if they not symbols */
481 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
484 sym1 = OP_SYMBOL (op1);
485 sym2 = OP_SYMBOL (op2);
487 /* if both are itemps & one is spilt
488 and the other is not then false */
489 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
490 sym1->isspilt != sym2->isspilt)
493 /* if they are the same */
497 if (strcmp (sym1->rname, sym2->rname) == 0)
501 /* if left is a tmp & right is not */
502 if (IS_ITEMP (op1) &&
505 (sym1->usl.spillLoc == sym2))
508 if (IS_ITEMP (op2) &&
512 (sym2->usl.spillLoc == sym1))
518 /*-----------------------------------------------------------------*/
519 /* sameRegs - two asmops have the same registers */
520 /*-----------------------------------------------------------------*/
522 sameRegs (asmop * aop1, asmop * aop2)
529 if (aop1->type != AOP_REG ||
530 aop2->type != AOP_REG)
533 if (aop1->size != aop2->size)
536 for (i = 0; i < aop1->size; i++)
537 if (aop1->aopu.aop_reg[i] !=
538 aop2->aopu.aop_reg[i])
544 /*-----------------------------------------------------------------*/
545 /* aopOp - allocates an asmop for an operand : */
546 /*-----------------------------------------------------------------*/
548 aopOp (operand * op, iCode * ic, bool result)
557 /* if this a literal */
558 if (IS_OP_LITERAL (op))
560 op->aop = aop = newAsmop (AOP_LIT);
561 aop->aopu.aop_lit = op->operand.valOperand;
562 aop->size = getSize (operandType (op));
566 /* if already has a asmop then continue */
570 /* if the underlying symbol has a aop */
571 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
573 op->aop = OP_SYMBOL (op)->aop;
577 /* if this is a true symbol */
578 if (IS_TRUE_SYMOP (op))
580 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
584 /* this is a temporary : this has
590 e) can be a return use only */
592 sym = OP_SYMBOL (op);
594 /* if the type is a conditional */
595 if (sym->regType == REG_CND)
597 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
602 /* if it is spilt then two situations
604 b) has a spill location */
605 if (sym->isspilt || sym->nRegs == 0)
608 /* rematerialize it NOW */
611 sym->aop = op->aop = aop =
613 aop->size = getSize (sym->type);
620 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
621 aop->size = getSize (sym->type);
622 for (i = 0; i < 2; i++)
623 aop->aopu.aop_str[i] = accUse[i];
631 aop = op->aop = sym->aop = newAsmop (AOP_STR);
632 aop->size = getSize (sym->type);
633 for (i = 0; i < fReturnSizeMCS51; i++)
634 aop->aopu.aop_str[i] = fReturn[i];
638 /* else spill location */
639 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
640 /* force a new aop if sizes differ */
641 sym->usl.spillLoc->aop = NULL;
643 sym->aop = op->aop = aop =
644 aopForSym (ic, sym->usl.spillLoc, result);
645 aop->size = getSize (sym->type);
649 /* must be in a register */
650 sym->aop = op->aop = aop = newAsmop (AOP_REG);
651 aop->size = sym->nRegs;
652 for (i = 0; i < sym->nRegs; i++)
653 aop->aopu.aop_reg[i] = sym->regs[i];
656 /*-----------------------------------------------------------------*/
657 /* freeAsmop - free up the asmop given to an operand */
658 /*----------------------------------------------------------------*/
660 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
677 /* depending on the asmop type only three cases need work AOP_RO
678 , AOP_R1 && AOP_STK */
686 emitcode ("pop", "ar0");
690 bitVectUnSetBit (ic->rUsed, R0_IDX);
698 emitcode ("pop", "ar1");
702 bitVectUnSetBit (ic->rUsed, R1_IDX);
708 int stk = aop->aopu.aop_stk + aop->size;
709 bitVectUnSetBit (ic->rUsed, R0_IDX);
710 bitVectUnSetBit (ic->rUsed, R1_IDX);
712 getFreePtr (ic, &aop, FALSE);
716 emitcode ("mov", "a,_bp");
717 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
718 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
722 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
727 emitcode ("pop", "acc");
728 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
731 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
734 freeAsmop (op, NULL, ic, TRUE);
737 emitcode ("pop", "ar0");
743 emitcode ("pop", "ar1");
750 /* all other cases just dealloc */
756 OP_SYMBOL (op)->aop = NULL;
757 /* if the symbol has a spill */
759 SPIL_LOC (op)->aop = NULL;
764 /*-----------------------------------------------------------------*/
765 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
766 /* clobber the accumulator */
767 /*-----------------------------------------------------------------*/
769 aopGetUsesAcc (asmop *aop, int offset)
771 if (offset > (aop->size - 1))
789 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
798 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
802 /* Error case --- will have been caught already */
809 /*-----------------------------------------------------------------*/
810 /* aopGet - for fetching value of the aop */
811 /*-----------------------------------------------------------------*/
813 aopGet (asmop * aop, int offset, bool bit16, bool dname)
818 /* offset is greater than
820 if (offset > (aop->size - 1) &&
821 aop->type != AOP_LIT)
824 /* depending on type */
830 /* if we need to increment it */
831 while (offset > aop->coff)
833 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
837 while (offset < aop->coff)
839 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
846 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
847 return (dname ? "acc" : "a");
849 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
850 rs = Safe_calloc (1, strlen (s) + 1);
855 if (aop->code && aop->coff==0 && offset>=1) {
856 emitcode ("mov", "a,#0x%02x", offset);
857 emitcode ("movc", "a,@a+dptr");
858 return (dname ? "acc" : "a");
861 while (offset > aop->coff)
863 emitcode ("inc", "dptr");
867 while (offset < aop->coff)
869 emitcode ("lcall", "__decdptr");
876 emitcode ("clr", "a");
877 emitcode ("movc", "a,@a+dptr");
881 emitcode ("movx", "a,@dptr");
883 return (dname ? "acc" : "a");
887 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
888 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
890 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
892 sprintf (s, "#(%s >> %d)",
893 aop->aopu.aop_immd.aop_immd1,
897 aop->aopu.aop_immd.aop_immd1);
898 rs = Safe_calloc (1, strlen (s) + 1);
904 sprintf (s, "(%s + %d)",
908 sprintf (s, "%s", aop->aopu.aop_dir);
909 rs = Safe_calloc (1, strlen (s) + 1);
915 return aop->aopu.aop_reg[offset]->dname;
917 return aop->aopu.aop_reg[offset]->name;
920 emitcode ("clr", "a");
921 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
922 emitcode ("rlc", "a");
923 return (dname ? "acc" : "a");
926 if (!offset && dname)
928 return aop->aopu.aop_str[offset];
931 return aopLiteral (aop->aopu.aop_lit, offset);
935 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
939 return aop->aopu.aop_str[offset];
943 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
944 "aopget got unsupported aop->type");
947 /*-----------------------------------------------------------------*/
948 /* aopPut - puts a string for a aop */
949 /*-----------------------------------------------------------------*/
951 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
955 if (aop->size && offset > (aop->size - 1))
957 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
958 "aopPut got offset > aop->size");
962 /* will assign value to value */
963 /* depending on where it is ofcourse */
968 sprintf (d, "(%s + %d)",
969 aop->aopu.aop_dir, offset);
971 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 writing 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) ||
1119 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1124 if (!offset && (strcmp (s, "acc") == 0) &&
1128 if (strcmp (aop->aopu.aop_str[offset], s) &&
1130 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1134 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1135 "aopPut got unsupported aop->type");
1143 /*-----------------------------------------------------------------*/
1144 /* pointToEnd :- points to the last byte of the operand */
1145 /*-----------------------------------------------------------------*/
1147 pointToEnd (asmop * aop)
1153 aop->coff = count = (aop->size - 1);
1159 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1163 emitcode ("inc", "dptr");
1170 /*-----------------------------------------------------------------*/
1171 /* reAdjustPreg - points a register back to where it should */
1172 /*-----------------------------------------------------------------*/
1174 reAdjustPreg (asmop * aop)
1176 if ((aop->coff==0) || aop->size <= 1)
1184 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1189 emitcode ("lcall", "__decdptr");
1196 #define AOP(op) op->aop
1197 #define AOP_TYPE(op) AOP(op)->type
1198 #define AOP_SIZE(op) AOP(op)->size
1199 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1200 AOP_TYPE(x) == AOP_R0))
1202 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1203 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1205 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1206 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1207 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1210 /*-----------------------------------------------------------------*/
1211 /* opIsGptr: returns non-zero if the passed operand is */
1212 /* a generic pointer type. */
1213 /*-----------------------------------------------------------------*/
1215 opIsGptr (operand * op)
1217 sym_link *type = operandType (op);
1219 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1226 /*-----------------------------------------------------------------*/
1227 /* getDataSize - get the operand data size */
1228 /*-----------------------------------------------------------------*/
1230 getDataSize (operand * op)
1233 size = AOP_SIZE (op);
1234 if (size == GPTRSIZE)
1236 sym_link *type = operandType (op);
1237 if (IS_GENPTR (type))
1239 /* generic pointer; arithmetic operations
1240 * should ignore the high byte (pointer type).
1248 /*-----------------------------------------------------------------*/
1249 /* outAcc - output Acc */
1250 /*-----------------------------------------------------------------*/
1252 outAcc (operand * result)
1255 size = getDataSize (result);
1258 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1261 /* unsigned or positive */
1264 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1269 /*-----------------------------------------------------------------*/
1270 /* outBitC - output a bit C */
1271 /*-----------------------------------------------------------------*/
1273 outBitC (operand * result)
1275 /* if the result is bit */
1276 if (AOP_TYPE (result) == AOP_CRY)
1277 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1280 emitcode ("clr", "a");
1281 emitcode ("rlc", "a");
1286 /*-----------------------------------------------------------------*/
1287 /* toBoolean - emit code for orl a,operator(sizeop) */
1288 /*-----------------------------------------------------------------*/
1290 toBoolean (operand * oper)
1292 int size = AOP_SIZE (oper) - 1;
1294 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1296 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1300 /*-----------------------------------------------------------------*/
1301 /* genNot - generate code for ! operation */
1302 /*-----------------------------------------------------------------*/
1308 D(emitcode ("; genNot",""));
1310 /* assign asmOps to operand & result */
1311 aopOp (IC_LEFT (ic), ic, FALSE);
1312 aopOp (IC_RESULT (ic), ic, TRUE);
1314 /* if in bit space then a special case */
1315 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1317 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1318 emitcode ("cpl", "c");
1319 outBitC (IC_RESULT (ic));
1323 toBoolean (IC_LEFT (ic));
1325 tlbl = newiTempLabel (NULL);
1326 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1327 emitcode ("", "%05d$:", tlbl->key + 100);
1328 outBitC (IC_RESULT (ic));
1331 /* release the aops */
1332 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1333 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1337 /*-----------------------------------------------------------------*/
1338 /* genCpl - generate code for complement */
1339 /*-----------------------------------------------------------------*/
1347 D(emitcode ("; genCpl",""));
1349 /* assign asmOps to operand & result */
1350 aopOp (IC_LEFT (ic), ic, FALSE);
1351 aopOp (IC_RESULT (ic), ic, TRUE);
1353 /* special case if in bit space */
1354 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1355 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1356 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1357 emitcode ("cpl", "c");
1358 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1361 tlbl=newiTempLabel(NULL);
1362 emitcode ("cjne", "%s,#0x01,%05d$",
1363 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1364 emitcode ("", "%05d$:", tlbl->key+100);
1365 outBitC (IC_RESULT(ic));
1369 size = AOP_SIZE (IC_RESULT (ic));
1372 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1374 emitcode ("cpl", "a");
1375 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1380 /* release the aops */
1381 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1382 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1385 /*-----------------------------------------------------------------*/
1386 /* genUminusFloat - unary minus for floating points */
1387 /*-----------------------------------------------------------------*/
1389 genUminusFloat (operand * op, operand * result)
1391 int size, offset = 0;
1394 D(emitcode ("; genUminusFloat",""));
1396 /* for this we just copy and then flip the bit */
1398 size = AOP_SIZE (op) - 1;
1402 aopPut (AOP (result),
1403 aopGet (AOP (op), offset, FALSE, FALSE),
1405 isOperandVolatile (result, FALSE));
1409 l = aopGet (AOP (op), offset, FALSE, FALSE);
1413 emitcode ("cpl", "acc.7");
1414 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1417 /*-----------------------------------------------------------------*/
1418 /* genUminus - unary minus code generation */
1419 /*-----------------------------------------------------------------*/
1421 genUminus (iCode * ic)
1424 sym_link *optype, *rtype;
1427 D(emitcode ("; genUminus",""));
1430 aopOp (IC_LEFT (ic), ic, FALSE);
1431 aopOp (IC_RESULT (ic), ic, TRUE);
1433 /* if both in bit space then special
1435 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1436 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1439 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1440 emitcode ("cpl", "c");
1441 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1445 optype = operandType (IC_LEFT (ic));
1446 rtype = operandType (IC_RESULT (ic));
1448 /* if float then do float stuff */
1449 if (IS_FLOAT (optype))
1451 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1455 /* otherwise subtract from zero */
1456 size = AOP_SIZE (IC_LEFT (ic));
1461 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1462 if (!strcmp (l, "a"))
1466 emitcode ("cpl", "a");
1467 emitcode ("addc", "a,#0");
1473 emitcode ("clr", "a");
1474 emitcode ("subb", "a,%s", l);
1476 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1479 /* if any remaining bytes in the result */
1480 /* we just need to propagate the sign */
1481 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1483 emitcode ("rlc", "a");
1484 emitcode ("subb", "a,acc");
1486 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1490 /* release the aops */
1491 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1492 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1495 /*-----------------------------------------------------------------*/
1496 /* saveRegisters - will look for a call and save the registers */
1497 /*-----------------------------------------------------------------*/
1499 saveRegisters (iCode * lic)
1506 for (ic = lic; ic; ic = ic->next)
1507 if (ic->op == CALL || ic->op == PCALL)
1512 fprintf (stderr, "found parameter push with no function call\n");
1516 /* if the registers have been saved already or don't need to be then
1520 if (IS_SYMOP(IC_LEFT(ic)) &&
1521 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1522 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1525 /* safe the registers in use at this time but skip the
1526 ones for the result */
1527 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1528 mcs51_rUmaskForOp (IC_RESULT(ic)));
1531 if (options.useXstack)
1533 if (bitVectBitValue (rsave, R0_IDX))
1534 emitcode ("mov", "b,r0");
1535 emitcode ("mov", "r0,%s", spname);
1536 for (i = 0; i < mcs51_nRegs; i++)
1538 if (bitVectBitValue (rsave, i))
1541 emitcode ("mov", "a,b");
1543 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1544 emitcode ("movx", "@r0,a");
1545 emitcode ("inc", "r0");
1548 emitcode ("mov", "%s,r0", spname);
1549 if (bitVectBitValue (rsave, R0_IDX))
1550 emitcode ("mov", "r0,b");
1553 for (i = 0; i < mcs51_nRegs; i++)
1555 if (bitVectBitValue (rsave, i))
1556 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1560 /*-----------------------------------------------------------------*/
1561 /* unsaveRegisters - pop the pushed registers */
1562 /*-----------------------------------------------------------------*/
1564 unsaveRegisters (iCode * ic)
1569 /* restore the registers in use at this time but skip the
1570 ones for the result */
1571 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1572 mcs51_rUmaskForOp (IC_RESULT(ic)));
1574 if (options.useXstack)
1576 emitcode ("mov", "r0,%s", spname);
1577 for (i = mcs51_nRegs; i >= 0; i--)
1579 if (bitVectBitValue (rsave, i))
1581 emitcode ("dec", "r0");
1582 emitcode ("movx", "a,@r0");
1584 emitcode ("mov", "b,a");
1586 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1590 emitcode ("mov", "%s,r0", spname);
1591 if (bitVectBitValue (rsave, R0_IDX))
1592 emitcode ("mov", "r0,b");
1595 for (i = mcs51_nRegs; i >= 0; i--)
1597 if (bitVectBitValue (rsave, i))
1598 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1604 /*-----------------------------------------------------------------*/
1606 /*-----------------------------------------------------------------*/
1608 pushSide (operand * oper, int size)
1613 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1614 if (AOP_TYPE (oper) != AOP_REG &&
1615 AOP_TYPE (oper) != AOP_DIR &&
1618 emitcode ("mov", "a,%s", l);
1619 emitcode ("push", "acc");
1622 emitcode ("push", "%s", l);
1626 /*-----------------------------------------------------------------*/
1627 /* assignResultValue - */
1628 /*-----------------------------------------------------------------*/
1630 assignResultValue (operand * oper)
1633 int size = AOP_SIZE (oper);
1636 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1642 /*-----------------------------------------------------------------*/
1643 /* genXpush - pushes onto the external stack */
1644 /*-----------------------------------------------------------------*/
1646 genXpush (iCode * ic)
1648 asmop *aop = newAsmop (0);
1650 int size, offset = 0;
1652 D(emitcode ("; genXpush",""));
1654 aopOp (IC_LEFT (ic), ic, FALSE);
1655 r = getFreePtr (ic, &aop, FALSE);
1658 emitcode ("mov", "%s,_spx", r->name);
1660 size = AOP_SIZE (IC_LEFT (ic));
1664 char *l = aopGet (AOP (IC_LEFT (ic)),
1665 offset++, FALSE, FALSE);
1667 emitcode ("movx", "@%s,a", r->name);
1668 emitcode ("inc", "%s", r->name);
1673 emitcode ("mov", "_spx,%s", r->name);
1675 freeAsmop (NULL, aop, ic, TRUE);
1676 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1679 /*-----------------------------------------------------------------*/
1680 /* genIpush - genrate code for pushing this gets a little complex */
1681 /*-----------------------------------------------------------------*/
1683 genIpush (iCode * ic)
1685 int size, offset = 0;
1688 D(emitcode ("; genIpush",""));
1690 /* if this is not a parm push : ie. it is spill push
1691 and spill push is always done on the local stack */
1695 /* and the item is spilt then do nothing */
1696 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1699 aopOp (IC_LEFT (ic), ic, FALSE);
1700 size = AOP_SIZE (IC_LEFT (ic));
1701 /* push it on the stack */
1704 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1710 emitcode ("push", "%s", l);
1715 /* this is a paramter push: in this case we call
1716 the routine to find the call and save those
1717 registers that need to be saved */
1720 /* if use external stack then call the external
1721 stack pushing routine */
1722 if (options.useXstack)
1728 /* then do the push */
1729 aopOp (IC_LEFT (ic), ic, FALSE);
1732 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1733 size = AOP_SIZE (IC_LEFT (ic));
1737 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1738 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1739 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1742 emitcode ("mov", "a,%s", l);
1743 emitcode ("push", "acc");
1746 emitcode ("push", "%s", l);
1749 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1752 /*-----------------------------------------------------------------*/
1753 /* genIpop - recover the registers: can happen only for spilling */
1754 /*-----------------------------------------------------------------*/
1756 genIpop (iCode * ic)
1760 D(emitcode ("; genIpop",""));
1762 /* if the temp was not pushed then */
1763 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1766 aopOp (IC_LEFT (ic), ic, FALSE);
1767 size = AOP_SIZE (IC_LEFT (ic));
1768 offset = (size - 1);
1770 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1773 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1776 /*-----------------------------------------------------------------*/
1777 /* unsaveRBank - restores the resgister bank from stack */
1778 /*-----------------------------------------------------------------*/
1780 unsaveRBank (int bank, iCode * ic, bool popPsw)
1786 if (options.useXstack)
1790 /* Assume r0 is available for use. */
1791 r = mcs51_regWithIdx (R0_IDX);;
1796 r = getFreePtr (ic, &aop, FALSE);
1798 emitcode ("mov", "%s,_spx", r->name);
1803 if (options.useXstack)
1805 emitcode ("movx", "a,@%s", r->name);
1806 emitcode ("mov", "psw,a");
1807 emitcode ("dec", "%s", r->name);
1811 emitcode ("pop", "psw");
1815 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1817 if (options.useXstack)
1819 emitcode ("movx", "a,@%s", r->name);
1820 emitcode ("mov", "(%s+%d),a",
1821 regs8051[i].base, 8 * bank + regs8051[i].offset);
1822 emitcode ("dec", "%s", r->name);
1826 emitcode ("pop", "(%s+%d)",
1827 regs8051[i].base, 8 * bank + regs8051[i].offset);
1830 if (options.useXstack)
1832 emitcode ("mov", "_spx,%s", r->name);
1837 freeAsmop (NULL, aop, ic, TRUE);
1841 /*-----------------------------------------------------------------*/
1842 /* saveRBank - saves an entire register bank on the stack */
1843 /*-----------------------------------------------------------------*/
1845 saveRBank (int bank, iCode * ic, bool pushPsw)
1851 if (options.useXstack)
1855 /* Assume r0 is available for use. */
1856 r = mcs51_regWithIdx (R0_IDX);;
1861 r = getFreePtr (ic, &aop, FALSE);
1863 emitcode ("mov", "%s,_spx", r->name);
1866 for (i = 0; i < mcs51_nRegs; i++)
1868 if (options.useXstack)
1870 emitcode ("inc", "%s", r->name);
1871 emitcode ("mov", "a,(%s+%d)",
1872 regs8051[i].base, 8 * bank + regs8051[i].offset);
1873 emitcode ("movx", "@%s,a", r->name);
1876 emitcode ("push", "(%s+%d)",
1877 regs8051[i].base, 8 * bank + regs8051[i].offset);
1882 if (options.useXstack)
1884 emitcode ("mov", "a,psw");
1885 emitcode ("movx", "@%s,a", r->name);
1886 emitcode ("inc", "%s", r->name);
1887 emitcode ("mov", "_spx,%s", r->name);
1892 emitcode ("push", "psw");
1895 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1900 freeAsmop (NULL, aop, ic, TRUE);
1909 /*-----------------------------------------------------------------*/
1910 /* genSend - gen code for SEND */
1911 /*-----------------------------------------------------------------*/
1912 static void genSend(set *sendSet)
1917 for (sic = setFirstItem (_G.sendSet); sic;
1918 sic = setNextItem (_G.sendSet)) {
1919 int size, offset = 0;
1920 aopOp (IC_LEFT (sic), sic, FALSE);
1921 size = AOP_SIZE (IC_LEFT (sic));
1923 if (sic->argreg == 1) {
1925 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1927 if (strcmp (l, fReturn[offset]))
1928 emitcode ("mov", "%s,%s", fReturn[offset], l);
1934 emitcode ("mov","b1_%d,%s",rb1_count++,
1935 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1938 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1942 /*-----------------------------------------------------------------*/
1943 /* genCall - generates a call statement */
1944 /*-----------------------------------------------------------------*/
1946 genCall (iCode * ic)
1949 // bool restoreBank = FALSE;
1950 bool swapBanks = FALSE;
1952 D(emitcode("; genCall",""));
1954 dtype = operandType (IC_LEFT (ic));
1955 /* if send set is not empty the assign */
1958 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
1959 genSend(reverseSet(_G.sendSet));
1961 genSend(_G.sendSet);
1967 /* if we are calling a not _naked function that is not using
1968 the same register bank then we need to save the
1969 destination registers on the stack */
1970 dtype = operandType (IC_LEFT (ic));
1971 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
1972 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1973 !IFFUNC_ISISR (dtype))
1978 /* if caller saves & we have not saved then */
1984 emitcode ("mov", "psw,#0x%02x",
1985 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1989 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1990 OP_SYMBOL (IC_LEFT (ic))->rname :
1991 OP_SYMBOL (IC_LEFT (ic))->name));
1995 emitcode ("mov", "psw,#0x%02x",
1996 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1999 /* if we need assign a result value */
2000 if ((IS_ITEMP (IC_RESULT (ic)) &&
2001 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2002 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2003 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2004 IS_TRUE_SYMOP (IC_RESULT (ic)))
2008 aopOp (IC_RESULT (ic), ic, FALSE);
2011 assignResultValue (IC_RESULT (ic));
2013 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2016 /* adjust the stack for parameters if
2021 if (ic->parmBytes > 3)
2023 emitcode ("mov", "a,%s", spname);
2024 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2025 emitcode ("mov", "%s,a", spname);
2028 for (i = 0; i < ic->parmBytes; i++)
2029 emitcode ("dec", "%s", spname);
2032 /* if we hade saved some registers then unsave them */
2033 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2034 unsaveRegisters (ic);
2036 // /* if register bank was saved then pop them */
2038 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2041 /*-----------------------------------------------------------------*/
2042 /* -10l - generates a call by pointer statement */
2043 /*-----------------------------------------------------------------*/
2045 genPcall (iCode * ic)
2048 symbol *rlbl = newiTempLabel (NULL);
2049 // bool restoreBank=FALSE;
2050 bool swapBanks = FALSE;
2052 D(emitcode("; genPCall",""));
2054 /* if caller saves & we have not saved then */
2058 /* if we are calling a not _naked function that is not using
2059 the same register bank then we need to save the
2060 destination registers on the stack */
2061 dtype = operandType (IC_LEFT (ic))->next;
2062 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2063 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2064 !IFFUNC_ISISR (dtype))
2066 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2067 // restoreBank=TRUE;
2069 // need caution message to user here
2072 /* push the return address on to the stack */
2073 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2074 emitcode ("push", "acc");
2075 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2076 emitcode ("push", "acc");
2078 /* now push the calling address */
2079 aopOp (IC_LEFT (ic), ic, FALSE);
2081 pushSide (IC_LEFT (ic), FPTRSIZE);
2083 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2085 /* if send set is not empty the assign */
2088 genSend(reverseSet(_G.sendSet));
2094 emitcode ("mov", "psw,#0x%02x",
2095 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2099 emitcode ("ret", "");
2100 emitcode ("", "%05d$:", (rlbl->key + 100));
2105 emitcode ("mov", "psw,#0x%02x",
2106 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2109 /* if we need assign a result value */
2110 if ((IS_ITEMP (IC_RESULT (ic)) &&
2111 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2112 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2113 IS_TRUE_SYMOP (IC_RESULT (ic)))
2117 aopOp (IC_RESULT (ic), ic, FALSE);
2120 assignResultValue (IC_RESULT (ic));
2122 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2125 /* adjust the stack for parameters if
2130 if (ic->parmBytes > 3)
2132 emitcode ("mov", "a,%s", spname);
2133 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2134 emitcode ("mov", "%s,a", spname);
2137 for (i = 0; i < ic->parmBytes; i++)
2138 emitcode ("dec", "%s", spname);
2142 // /* if register bank was saved then unsave them */
2144 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2146 /* if we hade saved some registers then
2148 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2149 unsaveRegisters (ic);
2152 /*-----------------------------------------------------------------*/
2153 /* resultRemat - result is rematerializable */
2154 /*-----------------------------------------------------------------*/
2156 resultRemat (iCode * ic)
2158 if (SKIP_IC (ic) || ic->op == IFX)
2161 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2163 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2164 if (sym->remat && !POINTER_SET (ic))
2171 #if defined(__BORLANDC__) || defined(_MSC_VER)
2172 #define STRCASECMP stricmp
2174 #define STRCASECMP strcasecmp
2177 /*-----------------------------------------------------------------*/
2178 /* inExcludeList - return 1 if the string is in exclude Reg list */
2179 /*-----------------------------------------------------------------*/
2181 regsCmp(void *p1, void *p2)
2183 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2187 inExcludeList (char *s)
2189 const char *p = setFirstItem(options.excludeRegsSet);
2191 if (p == NULL || STRCASECMP(p, "none") == 0)
2195 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2198 /*-----------------------------------------------------------------*/
2199 /* genFunction - generated code for function entry */
2200 /*-----------------------------------------------------------------*/
2202 genFunction (iCode * ic)
2206 bool switchedPSW = FALSE;
2207 int calleesaves_saved_register = -1;
2210 /* create the function header */
2211 emitcode (";", "-----------------------------------------");
2212 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2213 emitcode (";", "-----------------------------------------");
2215 emitcode ("", "%s:", sym->rname);
2216 ftype = operandType (IC_LEFT (ic));
2218 if (IFFUNC_ISNAKED(ftype))
2220 emitcode(";", "naked function: no prologue.");
2224 /* if critical function then turn interrupts off */
2225 if (IFFUNC_ISCRITICAL (ftype))
2226 emitcode ("clr", "ea");
2228 /* here we need to generate the equates for the
2229 register bank if required */
2230 if (FUNC_REGBANK (ftype) != rbank)
2234 rbank = FUNC_REGBANK (ftype);
2235 for (i = 0; i < mcs51_nRegs; i++)
2237 if (strcmp (regs8051[i].base, "0") == 0)
2238 emitcode ("", "%s = 0x%02x",
2240 8 * rbank + regs8051[i].offset);
2242 emitcode ("", "%s = %s + 0x%02x",
2245 8 * rbank + regs8051[i].offset);
2249 /* if this is an interrupt service routine then
2250 save acc, b, dpl, dph */
2251 if (IFFUNC_ISISR (sym->type))
2254 if (!inExcludeList ("acc"))
2255 emitcode ("push", "acc");
2256 if (!inExcludeList ("b"))
2257 emitcode ("push", "b");
2258 if (!inExcludeList ("dpl"))
2259 emitcode ("push", "dpl");
2260 if (!inExcludeList ("dph"))
2261 emitcode ("push", "dph");
2262 /* if this isr has no bank i.e. is going to
2263 run with bank 0 , then we need to save more
2265 if (!FUNC_REGBANK (sym->type))
2268 /* if this function does not call any other
2269 function then we can be economical and
2270 save only those registers that are used */
2271 if (!IFFUNC_HASFCALL(sym->type))
2275 /* if any registers used */
2278 /* save the registers used */
2279 for (i = 0; i < sym->regsUsed->size; i++)
2281 if (bitVectBitValue (sym->regsUsed, i) ||
2282 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2283 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2291 /* this function has a function call cannot
2292 determines register usage so we will have to push the
2294 saveRBank (0, ic, FALSE);
2295 if (options.parms_in_bank1) {
2297 for (i=0; i < 8 ; i++ ) {
2298 emitcode ("push","%s",rb1regs[i]);
2305 /* This ISR uses a non-zero bank.
2307 * We assume that the bank is available for our
2310 * However, if this ISR calls a function which uses some
2311 * other bank, we must save that bank entirely.
2313 unsigned long banksToSave = 0;
2315 if (IFFUNC_HASFCALL(sym->type))
2318 #define MAX_REGISTER_BANKS 4
2323 for (i = ic; i; i = i->next)
2325 if (i->op == ENDFUNCTION)
2327 /* we got to the end OK. */
2335 dtype = operandType (IC_LEFT(i));
2337 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2339 /* Mark this bank for saving. */
2340 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2342 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2346 banksToSave |= (1 << FUNC_REGBANK(dtype));
2349 /* And note that we don't need to do it in
2357 /* This is a mess; we have no idea what
2358 * register bank the called function might
2361 * The only thing I can think of to do is
2362 * throw a warning and hope.
2364 werror(W_FUNCPTR_IN_USING_ISR);
2368 if (banksToSave && options.useXstack)
2370 /* Since we aren't passing it an ic,
2371 * saveRBank will assume r0 is available to abuse.
2373 * So switch to our (trashable) bank now, so
2374 * the caller's R0 isn't trashed.
2376 emitcode ("push", "psw");
2377 emitcode ("mov", "psw,#0x%02x",
2378 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2382 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2384 if (banksToSave & (1 << ix))
2386 saveRBank(ix, NULL, FALSE);
2390 // TODO: this needs a closer look
2391 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2396 /* if callee-save to be used for this function
2397 then save the registers being used in this function */
2398 if (IFFUNC_CALLEESAVES(sym->type))
2402 /* if any registers used */
2405 /* save the registers used */
2406 for (i = 0; i < sym->regsUsed->size; i++)
2408 if (bitVectBitValue (sym->regsUsed, i) ||
2409 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2411 /* remember one saved register for later usage */
2412 if (calleesaves_saved_register < 0)
2413 calleesaves_saved_register = i;
2414 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2422 /* set the register bank to the desired value */
2423 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2426 emitcode ("push", "psw");
2427 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2430 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2433 if (options.useXstack)
2435 emitcode ("mov", "r0,%s", spname);
2436 emitcode ("mov", "a,_bp");
2437 emitcode ("movx", "@r0,a");
2438 emitcode ("inc", "%s", spname);
2442 /* set up the stack */
2443 emitcode ("push", "_bp"); /* save the callers stack */
2445 emitcode ("mov", "_bp,%s", spname);
2448 /* adjust the stack for the function */
2454 werror (W_STACK_OVERFLOW, sym->name);
2456 if (i > 3 && sym->recvSize < 4)
2459 emitcode ("mov", "a,sp");
2460 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2461 emitcode ("mov", "sp,a");
2466 if (IFFUNC_CALLEESAVES(sym->type))
2468 /* if it's a callee-saves function we need a saved register */
2469 if (calleesaves_saved_register >= 0)
2471 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2472 emitcode ("mov", "a,sp");
2473 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2474 emitcode ("mov", "sp,a");
2475 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2478 /* do it the hard way */
2480 emitcode ("inc", "sp");
2484 /* not callee-saves, we can clobber r0 */
2485 emitcode ("mov", "r0,a");
2486 emitcode ("mov", "a,sp");
2487 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2488 emitcode ("mov", "sp,a");
2489 emitcode ("mov", "a,r0");
2494 emitcode ("inc", "sp");
2500 emitcode ("mov", "a,_spx");
2501 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2502 emitcode ("mov", "_spx,a");
2507 /*-----------------------------------------------------------------*/
2508 /* genEndFunction - generates epilogue for functions */
2509 /*-----------------------------------------------------------------*/
2511 genEndFunction (iCode * ic)
2513 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2515 if (IFFUNC_ISNAKED(sym->type))
2517 emitcode(";", "naked function: no epilogue.");
2521 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2523 emitcode ("mov", "%s,_bp", spname);
2526 /* if use external stack but some variables were
2527 added to the local stack then decrement the
2529 if (options.useXstack && sym->stack)
2531 emitcode ("mov", "a,sp");
2532 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2533 emitcode ("mov", "sp,a");
2537 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2539 if (options.useXstack)
2541 emitcode ("mov", "r0,%s", spname);
2542 emitcode ("movx", "a,@r0");
2543 emitcode ("mov", "_bp,a");
2544 emitcode ("dec", "%s", spname);
2548 emitcode ("pop", "_bp");
2552 /* restore the register bank */
2553 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2555 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2556 || !options.useXstack)
2558 /* Special case of ISR using non-zero bank with useXstack
2561 emitcode ("pop", "psw");
2565 if (IFFUNC_ISISR (sym->type))
2568 /* now we need to restore the registers */
2569 /* if this isr has no bank i.e. is going to
2570 run with bank 0 , then we need to save more
2572 if (!FUNC_REGBANK (sym->type))
2574 /* if this function does not call any other
2575 function then we can be economical and
2576 save only those registers that are used */
2577 if (!IFFUNC_HASFCALL(sym->type))
2581 /* if any registers used */
2584 /* save the registers used */
2585 for (i = sym->regsUsed->size; i >= 0; i--)
2587 if (bitVectBitValue (sym->regsUsed, i) ||
2588 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2589 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2596 if (options.parms_in_bank1) {
2598 for (i = 7 ; i >= 0 ; i-- ) {
2599 emitcode ("pop","%s",rb1regs[i]);
2602 /* this function has a function call cannot
2603 determines register usage so we will have to pop the
2605 unsaveRBank (0, ic, FALSE);
2610 /* This ISR uses a non-zero bank.
2612 * Restore any register banks saved by genFunction
2615 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2618 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2620 if (savedBanks & (1 << ix))
2622 unsaveRBank(ix, NULL, FALSE);
2626 if (options.useXstack)
2628 /* Restore bank AFTER calling unsaveRBank,
2629 * since it can trash r0.
2631 emitcode ("pop", "psw");
2635 if (!inExcludeList ("dph"))
2636 emitcode ("pop", "dph");
2637 if (!inExcludeList ("dpl"))
2638 emitcode ("pop", "dpl");
2639 if (!inExcludeList ("b"))
2640 emitcode ("pop", "b");
2641 if (!inExcludeList ("acc"))
2642 emitcode ("pop", "acc");
2644 if (IFFUNC_ISCRITICAL (sym->type))
2645 emitcode ("setb", "ea");
2647 /* if debug then send end of function */
2648 if (options.debug && currFunc)
2651 emitcode ("", "C$%s$%d$%d$%d ==.",
2652 FileBaseName (ic->filename), currFunc->lastLine,
2653 ic->level, ic->block);
2654 if (IS_STATIC (currFunc->etype))
2655 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2657 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2661 emitcode ("reti", "");
2665 if (IFFUNC_ISCRITICAL (sym->type))
2666 emitcode ("setb", "ea");
2668 if (IFFUNC_CALLEESAVES(sym->type))
2672 /* if any registers used */
2675 /* save the registers used */
2676 for (i = sym->regsUsed->size; i >= 0; i--)
2678 if (bitVectBitValue (sym->regsUsed, i) ||
2679 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2680 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2686 /* if debug then send end of function */
2687 if (options.debug && currFunc)
2690 emitcode ("", "C$%s$%d$%d$%d ==.",
2691 FileBaseName (ic->filename), currFunc->lastLine,
2692 ic->level, ic->block);
2693 if (IS_STATIC (currFunc->etype))
2694 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2696 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2700 emitcode ("ret", "");
2705 /*-----------------------------------------------------------------*/
2706 /* genRet - generate code for return statement */
2707 /*-----------------------------------------------------------------*/
2711 int size, offset = 0, pushed = 0;
2713 D(emitcode ("; genRet",""));
2715 /* if we have no return value then
2716 just generate the "ret" */
2720 /* we have something to return then
2721 move the return value into place */
2722 aopOp (IC_LEFT (ic), ic, FALSE);
2723 size = AOP_SIZE (IC_LEFT (ic));
2728 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2731 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2733 emitcode ("push", "%s", l);
2738 l = aopGet (AOP (IC_LEFT (ic)), offset,
2740 if (strcmp (fReturn[offset], l))
2741 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2750 if (strcmp (fReturn[pushed], "a"))
2751 emitcode ("pop", fReturn[pushed]);
2753 emitcode ("pop", "acc");
2756 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2759 /* generate a jump to the return label
2760 if the next is not the return statement */
2761 if (!(ic->next && ic->next->op == LABEL &&
2762 IC_LABEL (ic->next) == returnLabel))
2764 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2768 /*-----------------------------------------------------------------*/
2769 /* genLabel - generates a label */
2770 /*-----------------------------------------------------------------*/
2772 genLabel (iCode * ic)
2774 /* special case never generate */
2775 if (IC_LABEL (ic) == entryLabel)
2778 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2781 /*-----------------------------------------------------------------*/
2782 /* genGoto - generates a ljmp */
2783 /*-----------------------------------------------------------------*/
2785 genGoto (iCode * ic)
2787 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2790 /*-----------------------------------------------------------------*/
2791 /* findLabelBackwards: walks back through the iCode chain looking */
2792 /* for the given label. Returns number of iCode instructions */
2793 /* between that label and given ic. */
2794 /* Returns zero if label not found. */
2795 /*-----------------------------------------------------------------*/
2797 findLabelBackwards (iCode * ic, int key)
2806 /* If we have any pushes or pops, we cannot predict the distance.
2807 I don't like this at all, this should be dealt with in the
2809 if (ic->op == IPUSH || ic->op == IPOP) {
2813 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2822 /*-----------------------------------------------------------------*/
2823 /* genPlusIncr :- does addition with increment if possible */
2824 /*-----------------------------------------------------------------*/
2826 genPlusIncr (iCode * ic)
2828 unsigned int icount;
2829 unsigned int size = getDataSize (IC_RESULT (ic));
2831 /* will try to generate an increment */
2832 /* if the right side is not a literal
2834 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2837 /* if the literal value of the right hand side
2838 is greater than 4 then it is not worth it */
2839 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2842 D(emitcode ("; genPlusIncr",""));
2844 /* if increment >=16 bits in register or direct space */
2845 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2846 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2854 /* If the next instruction is a goto and the goto target
2855 * is < 10 instructions previous to this, we can generate
2856 * jumps straight to that target.
2858 if (ic->next && ic->next->op == GOTO
2859 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2860 && labelRange <= 10)
2862 emitcode (";", "tail increment optimized");
2863 tlbl = IC_LABEL (ic->next);
2868 tlbl = newiTempLabel (NULL);
2871 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2872 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2873 IS_AOP_PREG (IC_RESULT (ic)))
2874 emitcode ("cjne", "%s,#0x00,%05d$",
2875 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2879 emitcode ("clr", "a");
2880 emitcode ("cjne", "a,%s,%05d$",
2881 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2885 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2888 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2889 IS_AOP_PREG (IC_RESULT (ic)))
2890 emitcode ("cjne", "%s,#0x00,%05d$",
2891 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2894 emitcode ("cjne", "a,%s,%05d$",
2895 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2898 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2902 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2903 IS_AOP_PREG (IC_RESULT (ic)))
2904 emitcode ("cjne", "%s,#0x00,%05d$",
2905 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2909 emitcode ("cjne", "a,%s,%05d$",
2910 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2913 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2918 emitcode ("", "%05d$:", tlbl->key + 100);
2923 /* if the sizes are greater than 1 then we cannot */
2924 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2925 AOP_SIZE (IC_LEFT (ic)) > 1)
2928 /* we can if the aops of the left & result match or
2929 if they are in registers and the registers are the
2931 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2936 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2937 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2938 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
2944 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2953 /*-----------------------------------------------------------------*/
2954 /* outBitAcc - output a bit in acc */
2955 /*-----------------------------------------------------------------*/
2957 outBitAcc (operand * result)
2959 symbol *tlbl = newiTempLabel (NULL);
2960 /* if the result is a bit */
2961 if (AOP_TYPE (result) == AOP_CRY)
2963 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
2967 emitcode ("jz", "%05d$", tlbl->key + 100);
2968 emitcode ("mov", "a,%s", one);
2969 emitcode ("", "%05d$:", tlbl->key + 100);
2974 /*-----------------------------------------------------------------*/
2975 /* genPlusBits - generates code for addition of two bits */
2976 /*-----------------------------------------------------------------*/
2978 genPlusBits (iCode * ic)
2980 D(emitcode ("; genPlusBits",""));
2982 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2984 symbol *lbl = newiTempLabel (NULL);
2985 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2986 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2987 emitcode ("cpl", "c");
2988 emitcode ("", "%05d$:", (lbl->key + 100));
2989 outBitC (IC_RESULT (ic));
2993 emitcode ("clr", "a");
2994 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2995 emitcode ("rlc", "a");
2996 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2997 emitcode ("addc", "a,#0x00");
2998 outAcc (IC_RESULT (ic));
3003 /* This is the original version of this code.
3005 * This is being kept around for reference,
3006 * because I am not entirely sure I got it right...
3009 adjustArithmeticResult (iCode * ic)
3011 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3012 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3013 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3014 aopPut (AOP (IC_RESULT (ic)),
3015 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3017 isOperandVolatile (IC_RESULT (ic), FALSE));
3019 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3020 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3021 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3022 aopPut (AOP (IC_RESULT (ic)),
3023 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3025 isOperandVolatile (IC_RESULT (ic), FALSE));
3027 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3028 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3029 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3030 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3031 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3034 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3035 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3039 /* This is the pure and virtuous version of this code.
3040 * I'm pretty certain it's right, but not enough to toss the old
3044 adjustArithmeticResult (iCode * ic)
3046 if (opIsGptr (IC_RESULT (ic)) &&
3047 opIsGptr (IC_LEFT (ic)) &&
3048 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3050 aopPut (AOP (IC_RESULT (ic)),
3051 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3053 isOperandVolatile (IC_RESULT (ic), FALSE));
3056 if (opIsGptr (IC_RESULT (ic)) &&
3057 opIsGptr (IC_RIGHT (ic)) &&
3058 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3060 aopPut (AOP (IC_RESULT (ic)),
3061 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3063 isOperandVolatile (IC_RESULT (ic), FALSE));
3066 if (opIsGptr (IC_RESULT (ic)) &&
3067 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3068 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
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, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3079 /*-----------------------------------------------------------------*/
3080 /* genPlus - generates code for addition */
3081 /*-----------------------------------------------------------------*/
3083 genPlus (iCode * ic)
3085 int size, offset = 0;
3087 asmop *leftOp, *rightOp;
3089 /* special cases :- */
3091 D(emitcode ("; genPlus",""));
3093 aopOp (IC_LEFT (ic), ic, FALSE);
3094 aopOp (IC_RIGHT (ic), ic, FALSE);
3095 aopOp (IC_RESULT (ic), ic, TRUE);
3097 /* if literal, literal on the right or
3098 if left requires ACC or right is already
3100 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3101 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3102 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3104 operand *t = IC_RIGHT (ic);
3105 IC_RIGHT (ic) = IC_LEFT (ic);
3109 /* if both left & right are in bit
3111 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3112 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3118 /* if left in bit space & right literal */
3119 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3120 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3122 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3123 /* if result in bit space */
3124 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3126 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3127 emitcode ("cpl", "c");
3128 outBitC (IC_RESULT (ic));
3132 size = getDataSize (IC_RESULT (ic));
3135 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3136 emitcode ("addc", "a,#00");
3137 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3143 /* if I can do an increment instead
3144 of add then GOOD for ME */
3145 if (genPlusIncr (ic) == TRUE)
3148 size = getDataSize (IC_RESULT (ic));
3150 leftOp = AOP(IC_LEFT(ic));
3151 rightOp = AOP(IC_RIGHT(ic));
3156 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3158 emitcode("mov", "b,a");
3159 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3160 emitcode("xch", "a,b");
3161 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3162 emitcode (add, "a,b");
3164 else if (aopGetUsesAcc (leftOp, offset))
3166 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3167 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3171 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3172 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3174 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3175 add = "addc"; /* further adds must propagate carry */
3178 adjustArithmeticResult (ic);
3181 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3182 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3183 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3186 /*-----------------------------------------------------------------*/
3187 /* genMinusDec :- does subtraction with deccrement if possible */
3188 /*-----------------------------------------------------------------*/
3190 genMinusDec (iCode * ic)
3192 unsigned int icount;
3193 unsigned int size = getDataSize (IC_RESULT (ic));
3195 /* will try to generate an increment */
3196 /* if the right side is not a literal
3198 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3201 /* if the literal value of the right hand side
3202 is greater than 4 then it is not worth it */
3203 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3206 D(emitcode ("; genMinusDec",""));
3208 /* if decrement >=16 bits in register or direct space */
3209 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3210 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3218 /* If the next instruction is a goto and the goto target
3219 * is <= 10 instructions previous to this, we can generate
3220 * jumps straight to that target.
3222 if (ic->next && ic->next->op == GOTO
3223 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3224 && labelRange <= 10)
3226 emitcode (";", "tail decrement optimized");
3227 tlbl = IC_LABEL (ic->next);
3232 tlbl = newiTempLabel (NULL);
3236 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3237 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3238 IS_AOP_PREG (IC_RESULT (ic)))
3239 emitcode ("cjne", "%s,#0xff,%05d$"
3240 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3244 emitcode ("mov", "a,#0xff");
3245 emitcode ("cjne", "a,%s,%05d$"
3246 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3249 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3252 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3253 IS_AOP_PREG (IC_RESULT (ic)))
3254 emitcode ("cjne", "%s,#0xff,%05d$"
3255 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3259 emitcode ("cjne", "a,%s,%05d$"
3260 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3263 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3267 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3268 IS_AOP_PREG (IC_RESULT (ic)))
3269 emitcode ("cjne", "%s,#0xff,%05d$"
3270 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3274 emitcode ("cjne", "a,%s,%05d$"
3275 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3278 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3282 emitcode ("", "%05d$:", tlbl->key + 100);
3287 /* if the sizes are greater than 1 then we cannot */
3288 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3289 AOP_SIZE (IC_LEFT (ic)) > 1)
3292 /* we can if the aops of the left & result match or
3293 if they are in registers and the registers are the
3295 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3299 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3307 /*-----------------------------------------------------------------*/
3308 /* addSign - complete with sign */
3309 /*-----------------------------------------------------------------*/
3311 addSign (operand * result, int offset, int sign)
3313 int size = (getDataSize (result) - offset);
3318 emitcode ("rlc", "a");
3319 emitcode ("subb", "a,acc");
3321 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3325 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3329 /*-----------------------------------------------------------------*/
3330 /* genMinusBits - generates code for subtraction of two bits */
3331 /*-----------------------------------------------------------------*/
3333 genMinusBits (iCode * ic)
3335 symbol *lbl = newiTempLabel (NULL);
3337 D(emitcode ("; genMinusBits",""));
3339 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3341 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3342 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3343 emitcode ("cpl", "c");
3344 emitcode ("", "%05d$:", (lbl->key + 100));
3345 outBitC (IC_RESULT (ic));
3349 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3350 emitcode ("subb", "a,acc");
3351 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3352 emitcode ("inc", "a");
3353 emitcode ("", "%05d$:", (lbl->key + 100));
3354 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3355 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3359 /*-----------------------------------------------------------------*/
3360 /* genMinus - generates code for subtraction */
3361 /*-----------------------------------------------------------------*/
3363 genMinus (iCode * ic)
3365 int size, offset = 0;
3367 D(emitcode ("; genMinus",""));
3369 aopOp (IC_LEFT (ic), ic, FALSE);
3370 aopOp (IC_RIGHT (ic), ic, FALSE);
3371 aopOp (IC_RESULT (ic), ic, TRUE);
3373 /* special cases :- */
3374 /* if both left & right are in bit space */
3375 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3376 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3382 /* if I can do an decrement instead
3383 of subtract then GOOD for ME */
3384 if (genMinusDec (ic) == TRUE)
3387 size = getDataSize (IC_RESULT (ic));
3389 /* if literal, add a,#-lit, else normal subb */
3390 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3392 unsigned long lit = 0L;
3394 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3399 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3400 /* first add without previous c */
3402 if (!size && lit== (unsigned long) -1) {
3403 emitcode ("dec", "a");
3405 emitcode ("add", "a,#0x%02x",
3406 (unsigned int) (lit & 0x0FFL));
3409 emitcode ("addc", "a,#0x%02x",
3410 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3412 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3417 asmop *leftOp, *rightOp;
3419 leftOp = AOP(IC_LEFT(ic));
3420 rightOp = AOP(IC_RIGHT(ic));
3424 if (aopGetUsesAcc(rightOp, offset)) {
3425 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3426 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3428 emitcode( "setb", "c");
3430 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3431 emitcode("cpl", "a");
3433 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3436 emitcode ("subb", "a,%s",
3437 aopGet(rightOp, offset, FALSE, TRUE));
3440 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3445 adjustArithmeticResult (ic);
3448 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3449 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3450 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3454 /*-----------------------------------------------------------------*/
3455 /* genMultbits :- multiplication of bits */
3456 /*-----------------------------------------------------------------*/
3458 genMultbits (operand * left,
3462 D(emitcode ("; genMultbits",""));
3464 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3465 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3470 /*-----------------------------------------------------------------*/
3471 /* genMultOneByte : 8*8=8/16 bit multiplication */
3472 /*-----------------------------------------------------------------*/
3474 genMultOneByte (operand * left,
3478 sym_link *opetype = operandType (result);
3480 int size=AOP_SIZE(result);
3482 D(emitcode ("; genMultOneByte",""));
3484 if (size<1 || size>2) {
3485 // this should never happen
3486 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3487 AOP_SIZE(result), __FILE__, lineno);
3491 /* (if two literals: the value is computed before) */
3492 /* if one literal, literal on the right */
3493 if (AOP_TYPE (left) == AOP_LIT)
3498 //emitcode (";", "swapped left and right");
3501 if (SPEC_USIGN(opetype)
3502 // ignore the sign of left and right, what else can we do?
3503 || (SPEC_USIGN(operandType(left)) &&
3504 SPEC_USIGN(operandType(right)))) {
3505 // just an unsigned 8*8=8/16 multiply
3506 //emitcode (";","unsigned");
3507 // TODO: check for accumulator clash between left & right aops?
3508 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3509 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3510 emitcode ("mul", "ab");
3511 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3513 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3518 // we have to do a signed multiply
3520 //emitcode (";", "signed");
3521 emitcode ("clr", "F0"); // reset sign flag
3522 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3524 lbl=newiTempLabel(NULL);
3525 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3526 // left side is negative, 8-bit two's complement, this fails for -128
3527 emitcode ("setb", "F0"); // set sign flag
3528 emitcode ("cpl", "a");
3529 emitcode ("inc", "a");
3531 emitcode ("", "%05d$:", lbl->key+100);
3534 if (AOP_TYPE(right)==AOP_LIT) {
3535 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3536 /* AND literal negative */
3538 emitcode ("cpl", "F0"); // complement sign flag
3539 emitcode ("mov", "b,#0x%02x", -val);
3541 emitcode ("mov", "b,#0x%02x", val);
3544 lbl=newiTempLabel(NULL);
3545 emitcode ("mov", "b,a");
3546 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3547 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3548 // right side is negative, 8-bit two's complement
3549 emitcode ("cpl", "F0"); // complement sign flag
3550 emitcode ("cpl", "a");
3551 emitcode ("inc", "a");
3552 emitcode ("", "%05d$:", lbl->key+100);
3554 emitcode ("mul", "ab");
3556 lbl=newiTempLabel(NULL);
3557 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3558 // only ONE op was negative, we have to do a 8/16-bit two's complement
3559 emitcode ("cpl", "a"); // lsb
3561 emitcode ("inc", "a");
3563 emitcode ("add", "a,#1");
3564 emitcode ("xch", "a,b");
3565 emitcode ("cpl", "a"); // msb
3566 emitcode ("addc", "a,#0");
3567 emitcode ("xch", "a,b");
3570 emitcode ("", "%05d$:", lbl->key+100);
3571 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3573 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3577 /*-----------------------------------------------------------------*/
3578 /* genMult - generates code for multiplication */
3579 /*-----------------------------------------------------------------*/
3581 genMult (iCode * ic)
3583 operand *left = IC_LEFT (ic);
3584 operand *right = IC_RIGHT (ic);
3585 operand *result = IC_RESULT (ic);
3587 D(emitcode ("; genMult",""));
3589 /* assign the amsops */
3590 aopOp (left, ic, FALSE);
3591 aopOp (right, ic, FALSE);
3592 aopOp (result, ic, TRUE);
3594 /* special cases first */
3596 if (AOP_TYPE (left) == AOP_CRY &&
3597 AOP_TYPE (right) == AOP_CRY)
3599 genMultbits (left, right, result);
3603 /* if both are of size == 1 */
3604 #if 0 // one of them can be a sloc shared with the result
3605 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3607 if (getSize(operandType(left)) == 1 &&
3608 getSize(operandType(right)) == 1)
3611 genMultOneByte (left, right, result);
3615 /* should have been converted to function call */
3616 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3617 getSize(OP_SYMBOL(right)->type));
3621 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3622 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3623 freeAsmop (result, NULL, ic, TRUE);
3626 /*-----------------------------------------------------------------*/
3627 /* genDivbits :- division of bits */
3628 /*-----------------------------------------------------------------*/
3630 genDivbits (operand * left,
3637 D(emitcode ("; genDivbits",""));
3639 /* the result must be bit */
3640 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3641 l = aopGet (AOP (left), 0, FALSE, FALSE);
3645 emitcode ("div", "ab");
3646 emitcode ("rrc", "a");
3647 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3650 /*-----------------------------------------------------------------*/
3651 /* genDivOneByte : 8 bit division */
3652 /*-----------------------------------------------------------------*/
3654 genDivOneByte (operand * left,
3658 sym_link *opetype = operandType (result);
3663 D(emitcode ("; genDivOneByte",""));
3665 size = AOP_SIZE (result) - 1;
3667 /* signed or unsigned */
3668 if (SPEC_USIGN (opetype))
3670 /* unsigned is easy */
3671 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3672 l = aopGet (AOP (left), 0, FALSE, FALSE);
3674 emitcode ("div", "ab");
3675 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3677 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3681 /* signed is a little bit more difficult */
3683 /* save the signs of the operands */
3684 l = aopGet (AOP (left), 0, FALSE, FALSE);
3686 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3687 emitcode ("push", "acc"); /* save it on the stack */
3689 /* now sign adjust for both left & right */
3690 l = aopGet (AOP (right), 0, FALSE, FALSE);
3692 lbl = newiTempLabel (NULL);
3693 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3694 emitcode ("cpl", "a");
3695 emitcode ("inc", "a");
3696 emitcode ("", "%05d$:", (lbl->key + 100));
3697 emitcode ("mov", "b,a");
3699 /* sign adjust left side */
3700 l = aopGet (AOP (left), 0, FALSE, FALSE);
3703 lbl = newiTempLabel (NULL);
3704 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3705 emitcode ("cpl", "a");
3706 emitcode ("inc", "a");
3707 emitcode ("", "%05d$:", (lbl->key + 100));
3709 /* now the division */
3710 emitcode ("div", "ab");
3711 /* we are interested in the lower order
3713 emitcode ("mov", "b,a");
3714 lbl = newiTempLabel (NULL);
3715 emitcode ("pop", "acc");
3716 /* if there was an over flow we don't
3717 adjust the sign of the result */
3718 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3719 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3721 emitcode ("clr", "a");
3722 emitcode ("subb", "a,b");
3723 emitcode ("mov", "b,a");
3724 emitcode ("", "%05d$:", (lbl->key + 100));
3726 /* now we are done */
3727 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3730 emitcode ("mov", "c,b.7");
3731 emitcode ("subb", "a,acc");
3734 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3738 /*-----------------------------------------------------------------*/
3739 /* genDiv - generates code for division */
3740 /*-----------------------------------------------------------------*/
3744 operand *left = IC_LEFT (ic);
3745 operand *right = IC_RIGHT (ic);
3746 operand *result = IC_RESULT (ic);
3748 D(emitcode ("; genDiv",""));
3750 /* assign the amsops */
3751 aopOp (left, ic, FALSE);
3752 aopOp (right, ic, FALSE);
3753 aopOp (result, ic, TRUE);
3755 /* special cases first */
3757 if (AOP_TYPE (left) == AOP_CRY &&
3758 AOP_TYPE (right) == AOP_CRY)
3760 genDivbits (left, right, result);
3764 /* if both are of size == 1 */
3765 if (AOP_SIZE (left) == 1 &&
3766 AOP_SIZE (right) == 1)
3768 genDivOneByte (left, right, result);
3772 /* should have been converted to function call */
3775 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3776 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3777 freeAsmop (result, NULL, ic, TRUE);
3780 /*-----------------------------------------------------------------*/
3781 /* genModbits :- modulus of bits */
3782 /*-----------------------------------------------------------------*/
3784 genModbits (operand * left,
3791 D(emitcode ("; genModbits",""));
3793 /* the result must be bit */
3794 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3795 l = aopGet (AOP (left), 0, FALSE, FALSE);
3799 emitcode ("div", "ab");
3800 emitcode ("mov", "a,b");
3801 emitcode ("rrc", "a");
3802 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3805 /*-----------------------------------------------------------------*/
3806 /* genModOneByte : 8 bit modulus */
3807 /*-----------------------------------------------------------------*/
3809 genModOneByte (operand * left,
3813 sym_link *opetype = operandType (result);
3817 D(emitcode ("; genModOneByte",""));
3819 /* signed or unsigned */
3820 if (SPEC_USIGN (opetype))
3822 /* unsigned is easy */
3823 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3824 l = aopGet (AOP (left), 0, FALSE, FALSE);
3826 emitcode ("div", "ab");
3827 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3831 /* signed is a little bit more difficult */
3833 /* save the signs of the operands */
3834 l = aopGet (AOP (left), 0, FALSE, FALSE);
3837 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3838 emitcode ("push", "acc"); /* save it on the stack */
3840 /* now sign adjust for both left & right */
3841 l = aopGet (AOP (right), 0, FALSE, FALSE);
3844 lbl = newiTempLabel (NULL);
3845 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3846 emitcode ("cpl", "a");
3847 emitcode ("inc", "a");
3848 emitcode ("", "%05d$:", (lbl->key + 100));
3849 emitcode ("mov", "b,a");
3851 /* sign adjust left side */
3852 l = aopGet (AOP (left), 0, FALSE, FALSE);
3855 lbl = newiTempLabel (NULL);
3856 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3857 emitcode ("cpl", "a");
3858 emitcode ("inc", "a");
3859 emitcode ("", "%05d$:", (lbl->key + 100));
3861 /* now the multiplication */
3862 emitcode ("div", "ab");
3863 /* we are interested in the lower order
3865 lbl = newiTempLabel (NULL);
3866 emitcode ("pop", "acc");
3867 /* if there was an over flow we don't
3868 adjust the sign of the result */
3869 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3870 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3872 emitcode ("clr", "a");
3873 emitcode ("subb", "a,b");
3874 emitcode ("mov", "b,a");
3875 emitcode ("", "%05d$:", (lbl->key + 100));
3877 /* now we are done */
3878 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3882 /*-----------------------------------------------------------------*/
3883 /* genMod - generates code for division */
3884 /*-----------------------------------------------------------------*/
3888 operand *left = IC_LEFT (ic);
3889 operand *right = IC_RIGHT (ic);
3890 operand *result = IC_RESULT (ic);
3892 D(emitcode ("; genMod",""));
3894 /* assign the amsops */
3895 aopOp (left, ic, FALSE);
3896 aopOp (right, ic, FALSE);
3897 aopOp (result, ic, TRUE);
3899 /* special cases first */
3901 if (AOP_TYPE (left) == AOP_CRY &&
3902 AOP_TYPE (right) == AOP_CRY)
3904 genModbits (left, right, result);
3908 /* if both are of size == 1 */
3909 if (AOP_SIZE (left) == 1 &&
3910 AOP_SIZE (right) == 1)
3912 genModOneByte (left, right, result);
3916 /* should have been converted to function call */
3920 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3921 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3922 freeAsmop (result, NULL, ic, TRUE);
3925 /*-----------------------------------------------------------------*/
3926 /* genIfxJump :- will create a jump depending on the ifx */
3927 /*-----------------------------------------------------------------*/
3929 genIfxJump (iCode * ic, char *jval)
3932 symbol *tlbl = newiTempLabel (NULL);
3935 D(emitcode ("; genIfxJump",""));
3937 /* if true label then we jump if condition
3941 jlbl = IC_TRUE (ic);
3942 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3943 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3947 /* false label is present */
3948 jlbl = IC_FALSE (ic);
3949 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3950 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3952 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3953 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3955 emitcode (inst, "%05d$", tlbl->key + 100);
3956 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3957 emitcode ("", "%05d$:", tlbl->key + 100);
3959 /* mark the icode as generated */
3963 /*-----------------------------------------------------------------*/
3964 /* genCmp :- greater or less than comparison */
3965 /*-----------------------------------------------------------------*/
3967 genCmp (operand * left, operand * right,
3968 operand * result, iCode * ifx, int sign, iCode *ic)
3970 int size, offset = 0;
3971 unsigned long lit = 0L;
3974 D(emitcode ("; genCmp",""));
3976 /* if left & right are bit variables */
3977 if (AOP_TYPE (left) == AOP_CRY &&
3978 AOP_TYPE (right) == AOP_CRY)
3980 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3981 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
3985 /* subtract right from left if at the
3986 end the carry flag is set then we know that
3987 left is greater than right */
3988 size = max (AOP_SIZE (left), AOP_SIZE (right));
3990 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3991 if ((size == 1) && !sign &&
3992 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3994 symbol *lbl = newiTempLabel (NULL);
3995 emitcode ("cjne", "%s,%s,%05d$",
3996 aopGet (AOP (left), offset, FALSE, FALSE),
3997 aopGet (AOP (right), offset, FALSE, FALSE),
3999 emitcode ("", "%05d$:", lbl->key + 100);
4003 if (AOP_TYPE (right) == AOP_LIT)
4005 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4006 /* optimize if(x < 0) or if(x >= 0) */
4015 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4016 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4018 genIfxJump (ifx, "acc.7");
4022 emitcode ("rlc", "a");
4030 rightInB = aopGetUsesAcc(AOP (right), offset);
4032 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4033 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4034 if (sign && size == 0)
4036 emitcode ("xrl", "a,#0x80");
4037 if (AOP_TYPE (right) == AOP_LIT)
4039 unsigned long lit = (unsigned long)
4040 floatFromVal (AOP (right)->aopu.aop_lit);
4041 emitcode ("subb", "a,#0x%02x",
4042 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4047 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4048 emitcode ("xrl", "b,#0x80");
4049 emitcode ("subb", "a,b");
4055 emitcode ("subb", "a,b");
4057 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4065 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4066 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4067 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4073 /* if the result is used in the next
4074 ifx conditional branch then generate
4075 code a little differently */
4077 genIfxJump (ifx, "c");
4080 /* leave the result in acc */
4084 /*-----------------------------------------------------------------*/
4085 /* genCmpGt :- greater than comparison */
4086 /*-----------------------------------------------------------------*/
4088 genCmpGt (iCode * ic, iCode * ifx)
4090 operand *left, *right, *result;
4091 sym_link *letype, *retype;
4094 D(emitcode ("; genCmpGt",""));
4096 left = IC_LEFT (ic);
4097 right = IC_RIGHT (ic);
4098 result = IC_RESULT (ic);
4100 letype = getSpec (operandType (left));
4101 retype = getSpec (operandType (right));
4102 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4103 /* assign the amsops */
4104 aopOp (left, ic, FALSE);
4105 aopOp (right, ic, FALSE);
4106 aopOp (result, ic, TRUE);
4108 genCmp (right, left, result, ifx, sign,ic);
4110 freeAsmop (result, NULL, ic, TRUE);
4113 /*-----------------------------------------------------------------*/
4114 /* genCmpLt - less than comparisons */
4115 /*-----------------------------------------------------------------*/
4117 genCmpLt (iCode * ic, iCode * ifx)
4119 operand *left, *right, *result;
4120 sym_link *letype, *retype;
4123 D(emitcode ("; genCmpLt",""));
4125 left = IC_LEFT (ic);
4126 right = IC_RIGHT (ic);
4127 result = IC_RESULT (ic);
4129 letype = getSpec (operandType (left));
4130 retype = getSpec (operandType (right));
4131 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4133 /* assign the amsops */
4134 aopOp (left, ic, FALSE);
4135 aopOp (right, ic, FALSE);
4136 aopOp (result, ic, TRUE);
4138 genCmp (left, right, result, ifx, sign,ic);
4140 freeAsmop (result, NULL, ic, TRUE);
4143 /*-----------------------------------------------------------------*/
4144 /* gencjneshort - compare and jump if not equal */
4145 /*-----------------------------------------------------------------*/
4147 gencjneshort (operand * left, operand * right, symbol * lbl)
4149 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4151 unsigned long lit = 0L;
4153 /* if the left side is a literal or
4154 if the right is in a pointer register and left
4156 if ((AOP_TYPE (left) == AOP_LIT) ||
4157 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4163 if (AOP_TYPE (right) == AOP_LIT)
4164 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4166 /* if the right side is a literal then anything goes */
4167 if (AOP_TYPE (right) == AOP_LIT &&
4168 AOP_TYPE (left) != AOP_DIR &&
4169 AOP_TYPE (left) != AOP_IMMD)
4173 emitcode ("cjne", "%s,%s,%05d$",
4174 aopGet (AOP (left), offset, FALSE, FALSE),
4175 aopGet (AOP (right), offset, FALSE, FALSE),
4181 /* if the right side is in a register or in direct space or
4182 if the left is a pointer register & right is not */
4183 else if (AOP_TYPE (right) == AOP_REG ||
4184 AOP_TYPE (right) == AOP_DIR ||
4185 AOP_TYPE (right) == AOP_LIT ||
4186 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4187 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4191 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4192 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4193 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4194 emitcode ("jnz", "%05d$", lbl->key + 100);
4196 emitcode ("cjne", "a,%s,%05d$",
4197 aopGet (AOP (right), offset, FALSE, TRUE),
4204 /* right is a pointer reg need both a & b */
4207 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4208 if (strcmp (l, "b"))
4209 emitcode ("mov", "b,%s", l);
4210 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4211 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4217 /*-----------------------------------------------------------------*/
4218 /* gencjne - compare and jump if not equal */
4219 /*-----------------------------------------------------------------*/
4221 gencjne (operand * left, operand * right, symbol * lbl)
4223 symbol *tlbl = newiTempLabel (NULL);
4225 gencjneshort (left, right, lbl);
4227 emitcode ("mov", "a,%s", one);
4228 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4229 emitcode ("", "%05d$:", lbl->key + 100);
4230 emitcode ("clr", "a");
4231 emitcode ("", "%05d$:", tlbl->key + 100);
4234 /*-----------------------------------------------------------------*/
4235 /* genCmpEq - generates code for equal to */
4236 /*-----------------------------------------------------------------*/
4238 genCmpEq (iCode * ic, iCode * ifx)
4240 operand *left, *right, *result;
4242 D(emitcode ("; genCmpEq",""));
4244 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4245 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4246 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4248 /* if literal, literal on the right or
4249 if the right is in a pointer register and left
4251 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4252 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4254 operand *t = IC_RIGHT (ic);
4255 IC_RIGHT (ic) = IC_LEFT (ic);
4259 if (ifx && !AOP_SIZE (result))
4262 /* if they are both bit variables */
4263 if (AOP_TYPE (left) == AOP_CRY &&
4264 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4266 if (AOP_TYPE (right) == AOP_LIT)
4268 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4271 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4272 emitcode ("cpl", "c");
4276 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4280 emitcode ("clr", "c");
4282 /* AOP_TYPE(right) == AOP_CRY */
4286 symbol *lbl = newiTempLabel (NULL);
4287 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4288 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4289 emitcode ("cpl", "c");
4290 emitcode ("", "%05d$:", (lbl->key + 100));
4292 /* if true label then we jump if condition
4294 tlbl = newiTempLabel (NULL);
4297 emitcode ("jnc", "%05d$", tlbl->key + 100);
4298 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4302 emitcode ("jc", "%05d$", tlbl->key + 100);
4303 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4305 emitcode ("", "%05d$:", tlbl->key + 100);
4309 tlbl = newiTempLabel (NULL);
4310 gencjneshort (left, right, tlbl);
4313 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4314 emitcode ("", "%05d$:", tlbl->key + 100);
4318 symbol *lbl = newiTempLabel (NULL);
4319 emitcode ("sjmp", "%05d$", lbl->key + 100);
4320 emitcode ("", "%05d$:", tlbl->key + 100);
4321 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4322 emitcode ("", "%05d$:", lbl->key + 100);
4325 /* mark the icode as generated */
4330 /* if they are both bit variables */
4331 if (AOP_TYPE (left) == AOP_CRY &&
4332 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4334 if (AOP_TYPE (right) == AOP_LIT)
4336 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4339 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4340 emitcode ("cpl", "c");
4344 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4348 emitcode ("clr", "c");
4350 /* AOP_TYPE(right) == AOP_CRY */
4354 symbol *lbl = newiTempLabel (NULL);
4355 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4356 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4357 emitcode ("cpl", "c");
4358 emitcode ("", "%05d$:", (lbl->key + 100));
4361 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4368 genIfxJump (ifx, "c");
4371 /* if the result is used in an arithmetic operation
4372 then put the result in place */
4377 gencjne (left, right, newiTempLabel (NULL));
4378 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4380 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4385 genIfxJump (ifx, "a");
4388 /* if the result is used in an arithmetic operation
4389 then put the result in place */
4390 if (AOP_TYPE (result) != AOP_CRY)
4392 /* leave the result in acc */
4396 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4397 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4398 freeAsmop (result, NULL, ic, TRUE);
4401 /*-----------------------------------------------------------------*/
4402 /* ifxForOp - returns the icode containing the ifx for operand */
4403 /*-----------------------------------------------------------------*/
4405 ifxForOp (operand * op, iCode * ic)
4407 /* if true symbol then needs to be assigned */
4408 if (IS_TRUE_SYMOP (op))
4411 /* if this has register type condition and
4412 the next instruction is ifx with the same operand
4413 and live to of the operand is upto the ifx only then */
4415 ic->next->op == IFX &&
4416 IC_COND (ic->next)->key == op->key &&
4417 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4423 /*-----------------------------------------------------------------*/
4424 /* hasInc - operand is incremented before any other use */
4425 /*-----------------------------------------------------------------*/
4427 hasInc (operand *op, iCode *ic,int osize)
4429 sym_link *type = operandType(op);
4430 sym_link *retype = getSpec (type);
4431 iCode *lic = ic->next;
4434 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4435 if (!IS_SYMOP(op)) return NULL;
4437 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4438 if (IS_AGGREGATE(type->next)) return NULL;
4439 if (osize != (isize = getSize(type->next))) return NULL;
4442 /* if operand of the form op = op + <sizeof *op> */
4443 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4444 isOperandEqual(IC_RESULT(lic),op) &&
4445 isOperandLiteral(IC_RIGHT(lic)) &&
4446 operandLitValue(IC_RIGHT(lic)) == isize) {
4449 /* if the operand used or deffed */
4450 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4453 /* if GOTO or IFX */
4454 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4460 /*-----------------------------------------------------------------*/
4461 /* genAndOp - for && operation */
4462 /*-----------------------------------------------------------------*/
4464 genAndOp (iCode * ic)
4466 operand *left, *right, *result;
4469 D(emitcode ("; genAndOp",""));
4471 /* note here that && operations that are in an
4472 if statement are taken away by backPatchLabels
4473 only those used in arthmetic operations remain */
4474 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4475 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4476 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4478 /* if both are bit variables */
4479 if (AOP_TYPE (left) == AOP_CRY &&
4480 AOP_TYPE (right) == AOP_CRY)
4482 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4483 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4488 tlbl = newiTempLabel (NULL);
4490 emitcode ("jz", "%05d$", tlbl->key + 100);
4492 emitcode ("", "%05d$:", tlbl->key + 100);
4496 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4497 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4498 freeAsmop (result, NULL, ic, TRUE);
4502 /*-----------------------------------------------------------------*/
4503 /* genOrOp - for || operation */
4504 /*-----------------------------------------------------------------*/
4506 genOrOp (iCode * ic)
4508 operand *left, *right, *result;
4511 D(emitcode ("; genOrOp",""));
4513 /* note here that || operations that are in an
4514 if statement are taken away by backPatchLabels
4515 only those used in arthmetic operations remain */
4516 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4517 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4518 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4520 /* if both are bit variables */
4521 if (AOP_TYPE (left) == AOP_CRY &&
4522 AOP_TYPE (right) == AOP_CRY)
4524 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4525 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4530 tlbl = newiTempLabel (NULL);
4532 emitcode ("jnz", "%05d$", tlbl->key + 100);
4534 emitcode ("", "%05d$:", tlbl->key + 100);
4538 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4539 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4540 freeAsmop (result, NULL, ic, TRUE);
4543 /*-----------------------------------------------------------------*/
4544 /* isLiteralBit - test if lit == 2^n */
4545 /*-----------------------------------------------------------------*/
4547 isLiteralBit (unsigned long lit)
4549 unsigned long pw[32] =
4550 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4551 0x100L, 0x200L, 0x400L, 0x800L,
4552 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4553 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4554 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4555 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4556 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4559 for (idx = 0; idx < 32; idx++)
4565 /*-----------------------------------------------------------------*/
4566 /* continueIfTrue - */
4567 /*-----------------------------------------------------------------*/
4569 continueIfTrue (iCode * ic)
4572 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4576 /*-----------------------------------------------------------------*/
4578 /*-----------------------------------------------------------------*/
4580 jumpIfTrue (iCode * ic)
4583 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4587 /*-----------------------------------------------------------------*/
4588 /* jmpTrueOrFalse - */
4589 /*-----------------------------------------------------------------*/
4591 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4593 // ugly but optimized by peephole
4596 symbol *nlbl = newiTempLabel (NULL);
4597 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4598 emitcode ("", "%05d$:", tlbl->key + 100);
4599 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4600 emitcode ("", "%05d$:", nlbl->key + 100);
4604 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4605 emitcode ("", "%05d$:", tlbl->key + 100);
4610 /*-----------------------------------------------------------------*/
4611 /* genAnd - code for and */
4612 /*-----------------------------------------------------------------*/
4614 genAnd (iCode * ic, iCode * ifx)
4616 operand *left, *right, *result;
4617 int size, offset = 0;
4618 unsigned long lit = 0L;
4622 D(emitcode ("; genAnd",""));
4624 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4625 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4626 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4629 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4631 AOP_TYPE (left), AOP_TYPE (right));
4632 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4634 AOP_SIZE (left), AOP_SIZE (right));
4637 /* if left is a literal & right is not then exchange them */
4638 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4639 AOP_NEEDSACC (left))
4641 operand *tmp = right;
4646 /* if result = right then exchange them */
4647 if (sameRegs (AOP (result), AOP (right)))
4649 operand *tmp = right;
4654 /* if right is bit then exchange them */
4655 if (AOP_TYPE (right) == AOP_CRY &&
4656 AOP_TYPE (left) != AOP_CRY)
4658 operand *tmp = right;
4662 if (AOP_TYPE (right) == AOP_LIT)
4663 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4665 size = AOP_SIZE (result);
4668 // result = bit & yy;
4669 if (AOP_TYPE (left) == AOP_CRY)
4671 // c = bit & literal;
4672 if (AOP_TYPE (right) == AOP_LIT)
4676 if (size && sameRegs (AOP (result), AOP (left)))
4679 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4684 if (size && (AOP_TYPE (result) == AOP_CRY))
4686 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4689 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4694 emitcode ("clr", "c");
4699 if (AOP_TYPE (right) == AOP_CRY)
4702 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4703 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4708 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4710 emitcode ("rrc", "a");
4711 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4719 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4720 genIfxJump (ifx, "c");
4724 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4725 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4726 if ((AOP_TYPE (right) == AOP_LIT) &&
4727 (AOP_TYPE (result) == AOP_CRY) &&
4728 (AOP_TYPE (left) != AOP_CRY))
4730 int posbit = isLiteralBit (lit);
4735 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4738 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4744 sprintf (buffer, "acc.%d", posbit & 0x07);
4745 genIfxJump (ifx, buffer);
4752 symbol *tlbl = newiTempLabel (NULL);
4753 int sizel = AOP_SIZE (left);
4755 emitcode ("setb", "c");
4758 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4760 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4762 if ((posbit = isLiteralBit (bytelit)) != 0)
4763 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4766 if (bytelit != 0x0FFL)
4767 emitcode ("anl", "a,%s",
4768 aopGet (AOP (right), offset, FALSE, TRUE));
4769 emitcode ("jnz", "%05d$", tlbl->key + 100);
4774 // bit = left & literal
4777 emitcode ("clr", "c");
4778 emitcode ("", "%05d$:", tlbl->key + 100);
4780 // if(left & literal)
4784 jmpTrueOrFalse (ifx, tlbl);
4792 /* if left is same as result */
4793 if (sameRegs (AOP (result), AOP (left)))
4795 for (; size--; offset++)
4797 if (AOP_TYPE (right) == AOP_LIT)
4799 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4801 else if (bytelit == 0)
4803 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4805 else if (IS_AOP_PREG (result))
4807 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4808 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4809 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4812 emitcode ("anl", "%s,%s",
4813 aopGet (AOP (left), offset, FALSE, TRUE),
4814 aopGet (AOP (right), offset, FALSE, FALSE));
4818 if (AOP_TYPE (left) == AOP_ACC)
4819 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4822 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4823 if (IS_AOP_PREG (result))
4825 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4826 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4830 emitcode ("anl", "%s,a",
4831 aopGet (AOP (left), offset, FALSE, TRUE));
4838 // left & result in different registers
4839 if (AOP_TYPE (result) == AOP_CRY)
4842 // if(size), result in bit
4843 // if(!size && ifx), conditional oper: if(left & right)
4844 symbol *tlbl = newiTempLabel (NULL);
4845 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4847 emitcode ("setb", "c");
4850 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4851 emitcode ("anl", "a,%s",
4852 aopGet (AOP (right), offset, FALSE, FALSE));
4854 if (AOP_TYPE(left)==AOP_ACC) {
4855 emitcode("mov", "b,a");
4856 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4857 emitcode("anl", "a,b");
4859 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4860 emitcode ("anl", "a,%s",
4861 aopGet (AOP (left), offset, FALSE, FALSE));
4864 emitcode ("jnz", "%05d$", tlbl->key + 100);
4870 emitcode ("", "%05d$:", tlbl->key + 100);
4874 jmpTrueOrFalse (ifx, tlbl);
4878 for (; (size--); offset++)
4881 // result = left & right
4882 if (AOP_TYPE (right) == AOP_LIT)
4884 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4886 aopPut (AOP (result),
4887 aopGet (AOP (left), offset, FALSE, FALSE),
4889 isOperandVolatile (result, FALSE));
4892 else if (bytelit == 0)
4894 /* dummy read of volatile operand */
4895 if (isOperandVolatile (left, FALSE))
4896 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4897 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4901 // faster than result <- left, anl result,right
4902 // and better if result is SFR
4903 if (AOP_TYPE (left) == AOP_ACC)
4904 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4907 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4908 emitcode ("anl", "a,%s",
4909 aopGet (AOP (left), offset, FALSE, FALSE));
4911 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4917 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4918 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4919 freeAsmop (result, NULL, ic, TRUE);
4922 /*-----------------------------------------------------------------*/
4923 /* genOr - code for or */
4924 /*-----------------------------------------------------------------*/
4926 genOr (iCode * ic, iCode * ifx)
4928 operand *left, *right, *result;
4929 int size, offset = 0;
4930 unsigned long lit = 0L;
4932 D(emitcode ("; genOr",""));
4934 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4935 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4936 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4939 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4941 AOP_TYPE (left), AOP_TYPE (right));
4942 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4944 AOP_SIZE (left), AOP_SIZE (right));
4947 /* if left is a literal & right is not then exchange them */
4948 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4949 AOP_NEEDSACC (left))
4951 operand *tmp = right;
4956 /* if result = right then exchange them */
4957 if (sameRegs (AOP (result), AOP (right)))
4959 operand *tmp = right;
4964 /* if right is bit then exchange them */
4965 if (AOP_TYPE (right) == AOP_CRY &&
4966 AOP_TYPE (left) != AOP_CRY)
4968 operand *tmp = right;
4972 if (AOP_TYPE (right) == AOP_LIT)
4973 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4975 size = AOP_SIZE (result);
4979 if (AOP_TYPE (left) == AOP_CRY)
4981 if (AOP_TYPE (right) == AOP_LIT)
4983 // c = bit | literal;
4986 // lit != 0 => result = 1
4987 if (AOP_TYPE (result) == AOP_CRY)
4990 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4992 continueIfTrue (ifx);
4995 emitcode ("setb", "c");
4999 // lit == 0 => result = left
5000 if (size && sameRegs (AOP (result), AOP (left)))
5002 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5007 if (AOP_TYPE (right) == AOP_CRY)
5010 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5011 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5016 symbol *tlbl = newiTempLabel (NULL);
5017 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5018 emitcode ("setb", "c");
5019 emitcode ("jb", "%s,%05d$",
5020 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5022 emitcode ("jnz", "%05d$", tlbl->key + 100);
5023 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5025 jmpTrueOrFalse (ifx, tlbl);
5031 emitcode ("", "%05d$:", tlbl->key + 100);
5040 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5041 genIfxJump (ifx, "c");
5045 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5046 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5047 if ((AOP_TYPE (right) == AOP_LIT) &&
5048 (AOP_TYPE (result) == AOP_CRY) &&
5049 (AOP_TYPE (left) != AOP_CRY))
5055 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5057 continueIfTrue (ifx);
5062 // lit = 0, result = boolean(left)
5064 emitcode ("setb", "c");
5068 symbol *tlbl = newiTempLabel (NULL);
5069 emitcode ("jnz", "%05d$", tlbl->key + 100);
5071 emitcode ("", "%05d$:", tlbl->key + 100);
5075 genIfxJump (ifx, "a");
5083 /* if left is same as result */
5084 if (sameRegs (AOP (result), AOP (left)))
5086 for (; size--; offset++)
5088 if (AOP_TYPE (right) == AOP_LIT)
5090 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5092 /* dummy read of volatile operand */
5093 if (isOperandVolatile (left, FALSE))
5094 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5098 else if (IS_AOP_PREG (left))
5100 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5101 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5102 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5105 emitcode ("orl", "%s,%s",
5106 aopGet (AOP (left), offset, FALSE, TRUE),
5107 aopGet (AOP (right), offset, FALSE, FALSE));
5111 if (AOP_TYPE (left) == AOP_ACC)
5112 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5115 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5116 if (IS_AOP_PREG (left))
5118 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5119 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5122 emitcode ("orl", "%s,a",
5123 aopGet (AOP (left), offset, FALSE, TRUE));
5130 // left & result in different registers
5131 if (AOP_TYPE (result) == AOP_CRY)
5134 // if(size), result in bit
5135 // if(!size && ifx), conditional oper: if(left | right)
5136 symbol *tlbl = newiTempLabel (NULL);
5137 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5139 emitcode ("setb", "c");
5142 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5143 emitcode ("orl", "a,%s",
5144 aopGet (AOP (right), offset, FALSE, FALSE));
5146 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5147 emitcode ("orl", "a,%s",
5148 aopGet (AOP (left), offset, FALSE, FALSE));
5150 emitcode ("jnz", "%05d$", tlbl->key + 100);
5156 emitcode ("", "%05d$:", tlbl->key + 100);
5160 jmpTrueOrFalse (ifx, tlbl);
5163 for (; (size--); offset++)
5166 // result = left & right
5167 if (AOP_TYPE (right) == AOP_LIT)
5169 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5171 aopPut (AOP (result),
5172 aopGet (AOP (left), offset, FALSE, FALSE),
5174 isOperandVolatile (result, FALSE));
5178 // faster than result <- left, anl result,right
5179 // and better if result is SFR
5180 if (AOP_TYPE (left) == AOP_ACC)
5181 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5184 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5185 emitcode ("orl", "a,%s",
5186 aopGet (AOP (left), offset, FALSE, FALSE));
5188 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5193 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5194 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5195 freeAsmop (result, NULL, ic, TRUE);
5198 /*-----------------------------------------------------------------*/
5199 /* genXor - code for xclusive or */
5200 /*-----------------------------------------------------------------*/
5202 genXor (iCode * ic, iCode * ifx)
5204 operand *left, *right, *result;
5205 int size, offset = 0;
5206 unsigned long lit = 0L;
5208 D(emitcode ("; genXor",""));
5210 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5211 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5212 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5215 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5217 AOP_TYPE (left), AOP_TYPE (right));
5218 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5220 AOP_SIZE (left), AOP_SIZE (right));
5223 /* if left is a literal & right is not ||
5224 if left needs acc & right does not */
5225 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5226 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5228 operand *tmp = right;
5233 /* if result = right then exchange them */
5234 if (sameRegs (AOP (result), AOP (right)))
5236 operand *tmp = right;
5241 /* if right is bit then exchange them */
5242 if (AOP_TYPE (right) == AOP_CRY &&
5243 AOP_TYPE (left) != AOP_CRY)
5245 operand *tmp = right;
5249 if (AOP_TYPE (right) == AOP_LIT)
5250 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5252 size = AOP_SIZE (result);
5256 if (AOP_TYPE (left) == AOP_CRY)
5258 if (AOP_TYPE (right) == AOP_LIT)
5260 // c = bit & literal;
5263 // lit>>1 != 0 => result = 1
5264 if (AOP_TYPE (result) == AOP_CRY)
5267 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5269 continueIfTrue (ifx);
5272 emitcode ("setb", "c");
5279 // lit == 0, result = left
5280 if (size && sameRegs (AOP (result), AOP (left)))
5282 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5286 // lit == 1, result = not(left)
5287 if (size && sameRegs (AOP (result), AOP (left)))
5289 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5294 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5295 emitcode ("cpl", "c");
5304 symbol *tlbl = newiTempLabel (NULL);
5305 if (AOP_TYPE (right) == AOP_CRY)
5308 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5312 int sizer = AOP_SIZE (right);
5314 // if val>>1 != 0, result = 1
5315 emitcode ("setb", "c");
5318 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5320 // test the msb of the lsb
5321 emitcode ("anl", "a,#0xfe");
5322 emitcode ("jnz", "%05d$", tlbl->key + 100);
5326 emitcode ("rrc", "a");
5328 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5329 emitcode ("cpl", "c");
5330 emitcode ("", "%05d$:", (tlbl->key + 100));
5337 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5338 genIfxJump (ifx, "c");
5342 if (sameRegs (AOP (result), AOP (left)))
5344 /* if left is same as result */
5345 for (; size--; offset++)
5347 if (AOP_TYPE (right) == AOP_LIT)
5349 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5351 else if (IS_AOP_PREG (left))
5353 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5354 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5355 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5358 emitcode ("xrl", "%s,%s",
5359 aopGet (AOP (left), offset, FALSE, TRUE),
5360 aopGet (AOP (right), offset, FALSE, FALSE));
5364 if (AOP_TYPE (left) == AOP_ACC)
5365 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5368 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5369 if (IS_AOP_PREG (left))
5371 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5372 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5375 emitcode ("xrl", "%s,a",
5376 aopGet (AOP (left), offset, FALSE, TRUE));
5383 // left & result in different registers
5384 if (AOP_TYPE (result) == AOP_CRY)
5387 // if(size), result in bit
5388 // if(!size && ifx), conditional oper: if(left ^ right)
5389 symbol *tlbl = newiTempLabel (NULL);
5390 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5392 emitcode ("setb", "c");
5395 if ((AOP_TYPE (right) == AOP_LIT) &&
5396 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5398 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5402 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5403 emitcode ("xrl", "a,%s",
5404 aopGet (AOP (right), offset, FALSE, FALSE));
5406 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5407 emitcode ("xrl", "a,%s",
5408 aopGet (AOP (left), offset, FALSE, FALSE));
5411 emitcode ("jnz", "%05d$", tlbl->key + 100);
5417 emitcode ("", "%05d$:", tlbl->key + 100);
5421 jmpTrueOrFalse (ifx, tlbl);
5424 for (; (size--); offset++)
5427 // result = left & right
5428 if (AOP_TYPE (right) == AOP_LIT)
5430 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5432 aopPut (AOP (result),
5433 aopGet (AOP (left), offset, FALSE, FALSE),
5435 isOperandVolatile (result, FALSE));
5439 // faster than result <- left, anl result,right
5440 // and better if result is SFR
5441 if (AOP_TYPE (left) == AOP_ACC)
5442 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5445 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5446 emitcode ("xrl", "a,%s",
5447 aopGet (AOP (left), offset, FALSE, TRUE));
5449 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5454 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5455 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5456 freeAsmop (result, NULL, ic, TRUE);
5459 /*-----------------------------------------------------------------*/
5460 /* genInline - write the inline code out */
5461 /*-----------------------------------------------------------------*/
5463 genInline (iCode * ic)
5465 char *buffer, *bp, *bp1;
5467 D(emitcode ("; genInline",""));
5469 _G.inLine += (!options.asmpeep);
5471 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5472 strcpy (buffer, IC_INLINE (ic));
5474 /* emit each line as a code */
5499 /* emitcode("",buffer); */
5500 _G.inLine -= (!options.asmpeep);
5503 /*-----------------------------------------------------------------*/
5504 /* genRRC - rotate right with carry */
5505 /*-----------------------------------------------------------------*/
5509 operand *left, *result;
5510 int size, offset = 0;
5513 D(emitcode ("; genRRC",""));
5515 /* rotate right with carry */
5516 left = IC_LEFT (ic);
5517 result = IC_RESULT (ic);
5518 aopOp (left, ic, FALSE);
5519 aopOp (result, ic, FALSE);
5521 /* move it to the result */
5522 size = AOP_SIZE (result);
5524 if (size == 1) { /* special case for 1 byte */
5525 l = aopGet (AOP (left), offset, FALSE, FALSE);
5527 emitcode ("rr", "a");
5533 l = aopGet (AOP (left), offset, FALSE, FALSE);
5535 emitcode ("rrc", "a");
5536 if (AOP_SIZE (result) > 1)
5537 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5539 /* now we need to put the carry into the
5540 highest order byte of the result */
5541 if (AOP_SIZE (result) > 1)
5543 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5546 emitcode ("mov", "acc.7,c");
5548 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5549 freeAsmop (left, NULL, ic, TRUE);
5550 freeAsmop (result, NULL, ic, TRUE);
5553 /*-----------------------------------------------------------------*/
5554 /* genRLC - generate code for rotate left with carry */
5555 /*-----------------------------------------------------------------*/
5559 operand *left, *result;
5560 int size, offset = 0;
5563 D(emitcode ("; genRLC",""));
5565 /* rotate right with carry */
5566 left = IC_LEFT (ic);
5567 result = IC_RESULT (ic);
5568 aopOp (left, ic, FALSE);
5569 aopOp (result, ic, FALSE);
5571 /* move it to the result */
5572 size = AOP_SIZE (result);
5576 l = aopGet (AOP (left), offset, FALSE, FALSE);
5578 if (size == 0) { /* special case for 1 byte */
5582 emitcode ("add", "a,acc");
5583 if (AOP_SIZE (result) > 1)
5584 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5587 l = aopGet (AOP (left), offset, FALSE, FALSE);
5589 emitcode ("rlc", "a");
5590 if (AOP_SIZE (result) > 1)
5591 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5594 /* now we need to put the carry into the
5595 highest order byte of the result */
5596 if (AOP_SIZE (result) > 1)
5598 l = aopGet (AOP (result), 0, FALSE, FALSE);
5601 emitcode ("mov", "acc.0,c");
5603 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5604 freeAsmop (left, NULL, ic, TRUE);
5605 freeAsmop (result, NULL, ic, TRUE);
5608 /*-----------------------------------------------------------------*/
5609 /* genGetHbit - generates code get highest order bit */
5610 /*-----------------------------------------------------------------*/
5612 genGetHbit (iCode * ic)
5614 operand *left, *result;
5616 D(emitcode ("; genGetHbit",""));
5618 left = IC_LEFT (ic);
5619 result = IC_RESULT (ic);
5620 aopOp (left, ic, FALSE);
5621 aopOp (result, ic, FALSE);
5623 /* get the highest order byte into a */
5624 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5625 if (AOP_TYPE (result) == AOP_CRY)
5627 emitcode ("rlc", "a");
5632 emitcode ("rl", "a");
5633 emitcode ("anl", "a,#0x01");
5638 freeAsmop (left, NULL, ic, TRUE);
5639 freeAsmop (result, NULL, ic, TRUE);
5642 /*-----------------------------------------------------------------*/
5643 /* AccRol - rotate left accumulator by known count */
5644 /*-----------------------------------------------------------------*/
5646 AccRol (int shCount)
5648 shCount &= 0x0007; // shCount : 0..7
5655 emitcode ("rl", "a");
5658 emitcode ("rl", "a");
5659 emitcode ("rl", "a");
5662 emitcode ("swap", "a");
5663 emitcode ("rr", "a");
5666 emitcode ("swap", "a");
5669 emitcode ("swap", "a");
5670 emitcode ("rl", "a");
5673 emitcode ("rr", "a");
5674 emitcode ("rr", "a");
5677 emitcode ("rr", "a");
5682 /*-----------------------------------------------------------------*/
5683 /* AccLsh - left shift accumulator by known count */
5684 /*-----------------------------------------------------------------*/
5686 AccLsh (int shCount)
5691 emitcode ("add", "a,acc");
5692 else if (shCount == 2)
5694 emitcode ("add", "a,acc");
5695 emitcode ("add", "a,acc");
5699 /* rotate left accumulator */
5701 /* and kill the lower order bits */
5702 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5707 /*-----------------------------------------------------------------*/
5708 /* AccRsh - right shift accumulator by known count */
5709 /*-----------------------------------------------------------------*/
5711 AccRsh (int shCount)
5718 emitcode ("rrc", "a");
5722 /* rotate right accumulator */
5723 AccRol (8 - shCount);
5724 /* and kill the higher order bits */
5725 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5730 /*-----------------------------------------------------------------*/
5731 /* AccSRsh - signed right shift accumulator by known count */
5732 /*-----------------------------------------------------------------*/
5734 AccSRsh (int shCount)
5741 emitcode ("mov", "c,acc.7");
5742 emitcode ("rrc", "a");
5744 else if (shCount == 2)
5746 emitcode ("mov", "c,acc.7");
5747 emitcode ("rrc", "a");
5748 emitcode ("mov", "c,acc.7");
5749 emitcode ("rrc", "a");
5753 tlbl = newiTempLabel (NULL);
5754 /* rotate right accumulator */
5755 AccRol (8 - shCount);
5756 /* and kill the higher order bits */
5757 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5758 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5759 emitcode ("orl", "a,#0x%02x",
5760 (unsigned char) ~SRMask[shCount]);
5761 emitcode ("", "%05d$:", tlbl->key + 100);
5766 /*-----------------------------------------------------------------*/
5767 /* shiftR1Left2Result - shift right one byte from left to result */
5768 /*-----------------------------------------------------------------*/
5770 shiftR1Left2Result (operand * left, int offl,
5771 operand * result, int offr,
5772 int shCount, int sign)
5774 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5775 /* shift right accumulator */
5780 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5783 /*-----------------------------------------------------------------*/
5784 /* shiftL1Left2Result - shift left one byte from left to result */
5785 /*-----------------------------------------------------------------*/
5787 shiftL1Left2Result (operand * left, int offl,
5788 operand * result, int offr, int shCount)
5791 l = aopGet (AOP (left), offl, FALSE, FALSE);
5793 /* shift left accumulator */
5795 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5798 /*-----------------------------------------------------------------*/
5799 /* movLeft2Result - move byte from left to result */
5800 /*-----------------------------------------------------------------*/
5802 movLeft2Result (operand * left, int offl,
5803 operand * result, int offr, int sign)
5806 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5808 l = aopGet (AOP (left), offl, FALSE, FALSE);
5810 if (*l == '@' && (IS_AOP_PREG (result)))
5812 emitcode ("mov", "a,%s", l);
5813 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5818 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
5821 /* MSB sign in acc.7 ! */
5822 if (getDataSize (left) == offl + 1)
5824 emitcode ("mov", "a,%s", l);
5825 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5832 /*-----------------------------------------------------------------*/
5833 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5834 /*-----------------------------------------------------------------*/
5838 emitcode ("rrc", "a");
5839 emitcode ("xch", "a,%s", x);
5840 emitcode ("rrc", "a");
5841 emitcode ("xch", "a,%s", x);
5844 /*-----------------------------------------------------------------*/
5845 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5846 /*-----------------------------------------------------------------*/
5850 emitcode ("xch", "a,%s", x);
5851 emitcode ("rlc", "a");
5852 emitcode ("xch", "a,%s", x);
5853 emitcode ("rlc", "a");
5856 /*-----------------------------------------------------------------*/
5857 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5858 /*-----------------------------------------------------------------*/
5862 emitcode ("xch", "a,%s", x);
5863 emitcode ("add", "a,acc");
5864 emitcode ("xch", "a,%s", x);
5865 emitcode ("rlc", "a");
5868 /*-----------------------------------------------------------------*/
5869 /* AccAXLsh - left shift a:x by known count (0..7) */
5870 /*-----------------------------------------------------------------*/
5872 AccAXLsh (char *x, int shCount)
5887 case 5: // AAAAABBB:CCCCCDDD
5889 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5891 emitcode ("anl", "a,#0x%02x",
5892 SLMask[shCount]); // BBB00000:CCCCCDDD
5894 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5896 AccRol (shCount); // DDDCCCCC:BBB00000
5898 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5900 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5902 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5904 emitcode ("anl", "a,#0x%02x",
5905 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5907 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5909 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5912 case 6: // AAAAAABB:CCCCCCDD
5913 emitcode ("anl", "a,#0x%02x",
5914 SRMask[shCount]); // 000000BB:CCCCCCDD
5915 emitcode ("mov", "c,acc.0"); // c = B
5916 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5918 AccAXRrl1 (x); // BCCCCCCD:D000000B
5919 AccAXRrl1 (x); // BBCCCCCC:DD000000
5921 emitcode("rrc","a");
5922 emitcode("xch","a,%s", x);
5923 emitcode("rrc","a");
5924 emitcode("mov","c,acc.0"); //<< get correct bit
5925 emitcode("xch","a,%s", x);
5927 emitcode("rrc","a");
5928 emitcode("xch","a,%s", x);
5929 emitcode("rrc","a");
5930 emitcode("xch","a,%s", x);
5933 case 7: // a:x <<= 7
5935 emitcode ("anl", "a,#0x%02x",
5936 SRMask[shCount]); // 0000000B:CCCCCCCD
5938 emitcode ("mov", "c,acc.0"); // c = B
5940 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5942 AccAXRrl1 (x); // BCCCCCCC:D0000000
5950 /*-----------------------------------------------------------------*/
5951 /* AccAXRsh - right shift a:x known count (0..7) */
5952 /*-----------------------------------------------------------------*/
5954 AccAXRsh (char *x, int shCount)
5962 AccAXRrl1 (x); // 0->a:x
5967 AccAXRrl1 (x); // 0->a:x
5970 AccAXRrl1 (x); // 0->a:x
5975 case 5: // AAAAABBB:CCCCCDDD = a:x
5977 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5979 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5981 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5983 emitcode ("anl", "a,#0x%02x",
5984 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5986 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5988 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5990 emitcode ("anl", "a,#0x%02x",
5991 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5993 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5995 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5997 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6000 case 6: // AABBBBBB:CCDDDDDD
6002 emitcode ("mov", "c,acc.7");
6003 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6005 emitcode ("mov", "c,acc.7");
6006 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6008 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6010 emitcode ("anl", "a,#0x%02x",
6011 SRMask[shCount]); // 000000AA:BBBBBBCC
6014 case 7: // ABBBBBBB:CDDDDDDD
6016 emitcode ("mov", "c,acc.7"); // c = A
6018 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6020 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6022 emitcode ("anl", "a,#0x%02x",
6023 SRMask[shCount]); // 0000000A:BBBBBBBC
6031 /*-----------------------------------------------------------------*/
6032 /* AccAXRshS - right shift signed a:x known count (0..7) */
6033 /*-----------------------------------------------------------------*/
6035 AccAXRshS (char *x, int shCount)
6043 emitcode ("mov", "c,acc.7");
6044 AccAXRrl1 (x); // s->a:x
6048 emitcode ("mov", "c,acc.7");
6049 AccAXRrl1 (x); // s->a:x
6051 emitcode ("mov", "c,acc.7");
6052 AccAXRrl1 (x); // s->a:x
6057 case 5: // AAAAABBB:CCCCCDDD = a:x
6059 tlbl = newiTempLabel (NULL);
6060 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6062 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6064 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6066 emitcode ("anl", "a,#0x%02x",
6067 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6069 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6071 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6073 emitcode ("anl", "a,#0x%02x",
6074 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6076 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6078 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6080 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6082 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6083 emitcode ("orl", "a,#0x%02x",
6084 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6086 emitcode ("", "%05d$:", tlbl->key + 100);
6087 break; // SSSSAAAA:BBBCCCCC
6089 case 6: // AABBBBBB:CCDDDDDD
6091 tlbl = newiTempLabel (NULL);
6092 emitcode ("mov", "c,acc.7");
6093 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6095 emitcode ("mov", "c,acc.7");
6096 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6098 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6100 emitcode ("anl", "a,#0x%02x",
6101 SRMask[shCount]); // 000000AA:BBBBBBCC
6103 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6104 emitcode ("orl", "a,#0x%02x",
6105 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6107 emitcode ("", "%05d$:", tlbl->key + 100);
6109 case 7: // ABBBBBBB:CDDDDDDD
6111 tlbl = newiTempLabel (NULL);
6112 emitcode ("mov", "c,acc.7"); // c = A
6114 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6116 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6118 emitcode ("anl", "a,#0x%02x",
6119 SRMask[shCount]); // 0000000A:BBBBBBBC
6121 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6122 emitcode ("orl", "a,#0x%02x",
6123 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6125 emitcode ("", "%05d$:", tlbl->key + 100);
6132 /*-----------------------------------------------------------------*/
6133 /* shiftL2Left2Result - shift left two bytes from left to result */
6134 /*-----------------------------------------------------------------*/
6136 shiftL2Left2Result (operand * left, int offl,
6137 operand * result, int offr, int shCount)
6139 if (sameRegs (AOP (result), AOP (left)) &&
6140 ((offl + MSB16) == offr))
6142 /* don't crash result[offr] */
6143 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6144 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6148 movLeft2Result (left, offl, result, offr, 0);
6149 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6151 /* ax << shCount (x = lsb(result)) */
6152 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6153 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6157 /*-----------------------------------------------------------------*/
6158 /* shiftR2Left2Result - shift right two bytes from left to result */
6159 /*-----------------------------------------------------------------*/
6161 shiftR2Left2Result (operand * left, int offl,
6162 operand * result, int offr,
6163 int shCount, int sign)
6165 if (sameRegs (AOP (result), AOP (left)) &&
6166 ((offl + MSB16) == offr))
6168 /* don't crash result[offr] */
6169 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6170 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6174 movLeft2Result (left, offl, result, offr, 0);
6175 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6177 /* a:x >> shCount (x = lsb(result)) */
6179 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6181 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6182 if (getDataSize (result) > 1)
6183 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6186 /*-----------------------------------------------------------------*/
6187 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6188 /*-----------------------------------------------------------------*/
6190 shiftLLeftOrResult (operand * left, int offl,
6191 operand * result, int offr, int shCount)
6193 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6194 /* shift left accumulator */
6196 /* or with result */
6197 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6198 /* back to result */
6199 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6202 /*-----------------------------------------------------------------*/
6203 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6204 /*-----------------------------------------------------------------*/
6206 shiftRLeftOrResult (operand * left, int offl,
6207 operand * result, int offr, int shCount)
6209 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6210 /* shift right accumulator */
6212 /* or with result */
6213 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6214 /* back to result */
6215 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6218 /*-----------------------------------------------------------------*/
6219 /* genlshOne - left shift a one byte quantity by known count */
6220 /*-----------------------------------------------------------------*/
6222 genlshOne (operand * result, operand * left, int shCount)
6224 D(emitcode ("; genlshOne",""));
6226 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6229 /*-----------------------------------------------------------------*/
6230 /* genlshTwo - left shift two bytes by known amount != 0 */
6231 /*-----------------------------------------------------------------*/
6233 genlshTwo (operand * result, operand * left, int shCount)
6237 D(emitcode ("; genlshTwo",""));
6239 size = getDataSize (result);
6241 /* if shCount >= 8 */
6249 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6251 movLeft2Result (left, LSB, result, MSB16, 0);
6253 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6256 /* 1 <= shCount <= 7 */
6260 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6262 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6266 /*-----------------------------------------------------------------*/
6267 /* shiftLLong - shift left one long from left to result */
6268 /* offl = LSB or MSB16 */
6269 /*-----------------------------------------------------------------*/
6271 shiftLLong (operand * left, operand * result, int offr)
6274 int size = AOP_SIZE (result);
6276 if (size >= LSB + offr)
6278 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6280 emitcode ("add", "a,acc");
6281 if (sameRegs (AOP (left), AOP (result)) &&
6282 size >= MSB16 + offr && offr != LSB)
6283 emitcode ("xch", "a,%s",
6284 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6286 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6289 if (size >= MSB16 + offr)
6291 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6293 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6296 emitcode ("rlc", "a");
6297 if (sameRegs (AOP (left), AOP (result)) &&
6298 size >= MSB24 + offr && offr != LSB)
6299 emitcode ("xch", "a,%s",
6300 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6302 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6305 if (size >= MSB24 + offr)
6307 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6309 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6312 emitcode ("rlc", "a");
6313 if (sameRegs (AOP (left), AOP (result)) &&
6314 size >= MSB32 + offr && offr != LSB)
6315 emitcode ("xch", "a,%s",
6316 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6318 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6321 if (size > MSB32 + offr)
6323 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6325 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6328 emitcode ("rlc", "a");
6329 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6332 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6335 /*-----------------------------------------------------------------*/
6336 /* genlshFour - shift four byte by a known amount != 0 */
6337 /*-----------------------------------------------------------------*/
6339 genlshFour (operand * result, operand * left, int shCount)
6343 D(emitcode ("; genlshFour",""));
6345 size = AOP_SIZE (result);
6347 /* if shifting more that 3 bytes */
6352 /* lowest order of left goes to the highest
6353 order of the destination */
6354 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6356 movLeft2Result (left, LSB, result, MSB32, 0);
6357 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6358 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6359 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6363 /* more than two bytes */
6364 else if (shCount >= 16)
6366 /* lower order two bytes goes to higher order two bytes */
6368 /* if some more remaining */
6370 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6373 movLeft2Result (left, MSB16, result, MSB32, 0);
6374 movLeft2Result (left, LSB, result, MSB24, 0);
6376 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6377 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6381 /* if more than 1 byte */
6382 else if (shCount >= 8)
6384 /* lower order three bytes goes to higher order three bytes */
6389 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6391 movLeft2Result (left, LSB, result, MSB16, 0);
6397 movLeft2Result (left, MSB24, result, MSB32, 0);
6398 movLeft2Result (left, MSB16, result, MSB24, 0);
6399 movLeft2Result (left, LSB, result, MSB16, 0);
6400 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6402 else if (shCount == 1)
6403 shiftLLong (left, result, MSB16);
6406 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6407 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6408 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6409 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6414 /* 1 <= shCount <= 7 */
6415 else if (shCount <= 2)
6417 shiftLLong (left, result, LSB);
6419 shiftLLong (result, result, LSB);
6421 /* 3 <= shCount <= 7, optimize */
6424 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6425 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6426 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6430 /*-----------------------------------------------------------------*/
6431 /* genLeftShiftLiteral - left shifting by known count */
6432 /*-----------------------------------------------------------------*/
6434 genLeftShiftLiteral (operand * left,
6439 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6442 D(emitcode ("; genLeftShiftLiteral",""));
6444 freeAsmop (right, NULL, ic, TRUE);
6446 aopOp (left, ic, FALSE);
6447 aopOp (result, ic, FALSE);
6449 size = getSize (operandType (result));
6452 emitcode ("; shift left ", "result %d, left %d", size,
6456 /* I suppose that the left size >= result size */
6461 movLeft2Result (left, size, result, size, 0);
6465 else if (shCount >= (size * 8))
6467 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6473 genlshOne (result, left, shCount);
6477 genlshTwo (result, left, shCount);
6481 genlshFour (result, left, shCount);
6484 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6485 "*** ack! mystery literal shift!\n");
6489 freeAsmop (left, NULL, ic, TRUE);
6490 freeAsmop (result, NULL, ic, TRUE);
6493 /*-----------------------------------------------------------------*/
6494 /* genLeftShift - generates code for left shifting */
6495 /*-----------------------------------------------------------------*/
6497 genLeftShift (iCode * ic)
6499 operand *left, *right, *result;
6502 symbol *tlbl, *tlbl1;
6504 D(emitcode ("; genLeftShift",""));
6506 right = IC_RIGHT (ic);
6507 left = IC_LEFT (ic);
6508 result = IC_RESULT (ic);
6510 aopOp (right, ic, FALSE);
6512 /* if the shift count is known then do it
6513 as efficiently as possible */
6514 if (AOP_TYPE (right) == AOP_LIT)
6516 genLeftShiftLiteral (left, right, result, ic);
6520 /* shift count is unknown then we have to form
6521 a loop get the loop count in B : Note: we take
6522 only the lower order byte since shifting
6523 more that 32 bits make no sense anyway, ( the
6524 largest size of an object can be only 32 bits ) */
6526 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6527 emitcode ("inc", "b");
6528 freeAsmop (right, NULL, ic, TRUE);
6529 aopOp (left, ic, FALSE);
6530 aopOp (result, ic, FALSE);
6532 /* now move the left to the result if they are not the
6534 if (!sameRegs (AOP (left), AOP (result)) &&
6535 AOP_SIZE (result) > 1)
6538 size = AOP_SIZE (result);
6542 l = aopGet (AOP (left), offset, FALSE, TRUE);
6543 if (*l == '@' && (IS_AOP_PREG (result)))
6546 emitcode ("mov", "a,%s", l);
6547 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6550 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6555 tlbl = newiTempLabel (NULL);
6556 size = AOP_SIZE (result);
6558 tlbl1 = newiTempLabel (NULL);
6560 /* if it is only one byte then */
6563 symbol *tlbl1 = newiTempLabel (NULL);
6565 l = aopGet (AOP (left), 0, FALSE, FALSE);
6567 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6568 emitcode ("", "%05d$:", tlbl->key + 100);
6569 emitcode ("add", "a,acc");
6570 emitcode ("", "%05d$:", tlbl1->key + 100);
6571 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6572 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6576 reAdjustPreg (AOP (result));
6578 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6579 emitcode ("", "%05d$:", tlbl->key + 100);
6580 l = aopGet (AOP (result), offset, FALSE, FALSE);
6582 emitcode ("add", "a,acc");
6583 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6586 l = aopGet (AOP (result), offset, FALSE, FALSE);
6588 emitcode ("rlc", "a");
6589 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6591 reAdjustPreg (AOP (result));
6593 emitcode ("", "%05d$:", tlbl1->key + 100);
6594 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6596 freeAsmop (left, NULL, ic, TRUE);
6597 freeAsmop (result, NULL, ic, TRUE);
6600 /*-----------------------------------------------------------------*/
6601 /* genrshOne - right shift a one byte quantity by known count */
6602 /*-----------------------------------------------------------------*/
6604 genrshOne (operand * result, operand * left,
6605 int shCount, int sign)
6607 D(emitcode ("; genrshOne",""));
6609 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6612 /*-----------------------------------------------------------------*/
6613 /* genrshTwo - right shift two bytes by known amount != 0 */
6614 /*-----------------------------------------------------------------*/
6616 genrshTwo (operand * result, operand * left,
6617 int shCount, int sign)
6619 D(emitcode ("; genrshTwo",""));
6621 /* if shCount >= 8 */
6626 shiftR1Left2Result (left, MSB16, result, LSB,
6629 movLeft2Result (left, MSB16, result, LSB, sign);
6630 addSign (result, MSB16, sign);
6633 /* 1 <= shCount <= 7 */
6635 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6638 /*-----------------------------------------------------------------*/
6639 /* shiftRLong - shift right one long from left to result */
6640 /* offl = LSB or MSB16 */
6641 /*-----------------------------------------------------------------*/
6643 shiftRLong (operand * left, int offl,
6644 operand * result, int sign)
6646 int isSameRegs=sameRegs(AOP(left),AOP(result));
6648 if (isSameRegs && offl>1) {
6649 // we are in big trouble, but this shouldn't happen
6650 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6653 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6658 emitcode ("rlc", "a");
6659 emitcode ("subb", "a,acc");
6661 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6663 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6664 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6667 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6672 emitcode ("clr", "c");
6674 emitcode ("mov", "c,acc.7");
6677 emitcode ("rrc", "a");
6679 if (isSameRegs && offl==MSB16) {
6680 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6682 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6683 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6686 emitcode ("rrc", "a");
6687 if (isSameRegs && offl==1) {
6688 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6690 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6691 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6693 emitcode ("rrc", "a");
6694 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6698 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6699 emitcode ("rrc", "a");
6700 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6704 /*-----------------------------------------------------------------*/
6705 /* genrshFour - shift four byte by a known amount != 0 */
6706 /*-----------------------------------------------------------------*/
6708 genrshFour (operand * result, operand * left,
6709 int shCount, int sign)
6711 D(emitcode ("; genrshFour",""));
6713 /* if shifting more that 3 bytes */
6718 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6720 movLeft2Result (left, MSB32, result, LSB, sign);
6721 addSign (result, MSB16, sign);
6723 else if (shCount >= 16)
6727 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6730 movLeft2Result (left, MSB24, result, LSB, 0);
6731 movLeft2Result (left, MSB32, result, MSB16, sign);
6733 addSign (result, MSB24, sign);
6735 else if (shCount >= 8)
6739 shiftRLong (left, MSB16, result, sign);
6740 else if (shCount == 0)
6742 movLeft2Result (left, MSB16, result, LSB, 0);
6743 movLeft2Result (left, MSB24, result, MSB16, 0);
6744 movLeft2Result (left, MSB32, result, MSB24, sign);
6745 addSign (result, MSB32, sign);
6749 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6750 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6751 /* the last shift is signed */
6752 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6753 addSign (result, MSB32, sign);
6757 { /* 1 <= shCount <= 7 */
6760 shiftRLong (left, LSB, result, sign);
6762 shiftRLong (result, LSB, result, sign);
6766 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6767 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6768 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6773 /*-----------------------------------------------------------------*/
6774 /* genRightShiftLiteral - right shifting by known count */
6775 /*-----------------------------------------------------------------*/
6777 genRightShiftLiteral (operand * left,
6783 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6786 D(emitcode ("; genRightShiftLiteral",""));
6788 freeAsmop (right, NULL, ic, TRUE);
6790 aopOp (left, ic, FALSE);
6791 aopOp (result, ic, FALSE);
6794 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6798 size = getDataSize (left);
6799 /* test the LEFT size !!! */
6801 /* I suppose that the left size >= result size */
6804 size = getDataSize (result);
6806 movLeft2Result (left, size, result, size, 0);
6809 else if (shCount >= (size * 8))
6812 /* get sign in acc.7 */
6813 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6815 addSign (result, LSB, sign);
6822 genrshOne (result, left, shCount, sign);
6826 genrshTwo (result, left, shCount, sign);
6830 genrshFour (result, left, shCount, sign);
6836 freeAsmop (left, NULL, ic, TRUE);
6837 freeAsmop (result, NULL, ic, TRUE);
6840 /*-----------------------------------------------------------------*/
6841 /* genSignedRightShift - right shift of signed number */
6842 /*-----------------------------------------------------------------*/
6844 genSignedRightShift (iCode * ic)
6846 operand *right, *left, *result;
6849 symbol *tlbl, *tlbl1;
6851 D(emitcode ("; genSignedRightShift",""));
6853 /* we do it the hard way put the shift count in b
6854 and loop thru preserving the sign */
6856 right = IC_RIGHT (ic);
6857 left = IC_LEFT (ic);
6858 result = IC_RESULT (ic);
6860 aopOp (right, ic, FALSE);
6863 if (AOP_TYPE (right) == AOP_LIT)
6865 genRightShiftLiteral (left, right, result, ic, 1);
6868 /* shift count is unknown then we have to form
6869 a loop get the loop count in B : Note: we take
6870 only the lower order byte since shifting
6871 more that 32 bits make no sense anyway, ( the
6872 largest size of an object can be only 32 bits ) */
6874 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6875 emitcode ("inc", "b");
6876 freeAsmop (right, NULL, ic, TRUE);
6877 aopOp (left, ic, FALSE);
6878 aopOp (result, ic, FALSE);
6880 /* now move the left to the result if they are not the
6882 if (!sameRegs (AOP (left), AOP (result)) &&
6883 AOP_SIZE (result) > 1)
6886 size = AOP_SIZE (result);
6890 l = aopGet (AOP (left), offset, FALSE, TRUE);
6891 if (*l == '@' && IS_AOP_PREG (result))
6894 emitcode ("mov", "a,%s", l);
6895 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6898 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6903 /* mov the highest order bit to OVR */
6904 tlbl = newiTempLabel (NULL);
6905 tlbl1 = newiTempLabel (NULL);
6907 size = AOP_SIZE (result);
6909 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6910 emitcode ("rlc", "a");
6911 emitcode ("mov", "ov,c");
6912 /* if it is only one byte then */
6915 l = aopGet (AOP (left), 0, FALSE, FALSE);
6917 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6918 emitcode ("", "%05d$:", tlbl->key + 100);
6919 emitcode ("mov", "c,ov");
6920 emitcode ("rrc", "a");
6921 emitcode ("", "%05d$:", tlbl1->key + 100);
6922 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6923 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6927 reAdjustPreg (AOP (result));
6928 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6929 emitcode ("", "%05d$:", tlbl->key + 100);
6930 emitcode ("mov", "c,ov");
6933 l = aopGet (AOP (result), offset, FALSE, FALSE);
6935 emitcode ("rrc", "a");
6936 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6938 reAdjustPreg (AOP (result));
6939 emitcode ("", "%05d$:", tlbl1->key + 100);
6940 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6943 freeAsmop (left, NULL, ic, TRUE);
6944 freeAsmop (result, NULL, ic, TRUE);
6947 /*-----------------------------------------------------------------*/
6948 /* genRightShift - generate code for right shifting */
6949 /*-----------------------------------------------------------------*/
6951 genRightShift (iCode * ic)
6953 operand *right, *left, *result;
6957 symbol *tlbl, *tlbl1;
6959 D(emitcode ("; genRightShift",""));
6961 /* if signed then we do it the hard way preserve the
6962 sign bit moving it inwards */
6963 retype = getSpec (operandType (IC_RESULT (ic)));
6965 if (!SPEC_USIGN (retype))
6967 genSignedRightShift (ic);
6971 /* signed & unsigned types are treated the same : i.e. the
6972 signed is NOT propagated inwards : quoting from the
6973 ANSI - standard : "for E1 >> E2, is equivalent to division
6974 by 2**E2 if unsigned or if it has a non-negative value,
6975 otherwise the result is implementation defined ", MY definition
6976 is that the sign does not get propagated */
6978 right = IC_RIGHT (ic);
6979 left = IC_LEFT (ic);
6980 result = IC_RESULT (ic);
6982 aopOp (right, ic, FALSE);
6984 /* if the shift count is known then do it
6985 as efficiently as possible */
6986 if (AOP_TYPE (right) == AOP_LIT)
6988 genRightShiftLiteral (left, right, result, ic, 0);
6992 /* shift count is unknown then we have to form
6993 a loop get the loop count in B : Note: we take
6994 only the lower order byte since shifting
6995 more that 32 bits make no sense anyway, ( the
6996 largest size of an object can be only 32 bits ) */
6998 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6999 emitcode ("inc", "b");
7000 freeAsmop (right, NULL, ic, TRUE);
7001 aopOp (left, ic, FALSE);
7002 aopOp (result, ic, FALSE);
7004 /* now move the left to the result if they are not the
7006 if (!sameRegs (AOP (left), AOP (result)) &&
7007 AOP_SIZE (result) > 1)
7010 size = AOP_SIZE (result);
7014 l = aopGet (AOP (left), offset, FALSE, TRUE);
7015 if (*l == '@' && IS_AOP_PREG (result))
7018 emitcode ("mov", "a,%s", l);
7019 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7022 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7027 tlbl = newiTempLabel (NULL);
7028 tlbl1 = newiTempLabel (NULL);
7029 size = AOP_SIZE (result);
7032 /* if it is only one byte then */
7035 l = aopGet (AOP (left), 0, FALSE, FALSE);
7037 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7038 emitcode ("", "%05d$:", tlbl->key + 100);
7040 emitcode ("rrc", "a");
7041 emitcode ("", "%05d$:", tlbl1->key + 100);
7042 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7043 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7047 reAdjustPreg (AOP (result));
7048 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7049 emitcode ("", "%05d$:", tlbl->key + 100);
7053 l = aopGet (AOP (result), offset, FALSE, FALSE);
7055 emitcode ("rrc", "a");
7056 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7058 reAdjustPreg (AOP (result));
7060 emitcode ("", "%05d$:", tlbl1->key + 100);
7061 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7064 freeAsmop (left, NULL, ic, TRUE);
7065 freeAsmop (result, NULL, ic, TRUE);
7068 /*-----------------------------------------------------------------*/
7069 /* emitPtrByteGet - emits code to get a byte into A through a */
7070 /* pointer register (R0, R1, or DPTR). The */
7071 /* original value of A can be preserved in B. */
7072 /*-----------------------------------------------------------------*/
7074 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7081 emitcode ("mov", "b,a");
7082 emitcode ("mov", "a,@%s", rname);
7087 emitcode ("mov", "b,a");
7088 emitcode ("movx", "a,@%s", rname);
7093 emitcode ("mov", "b,a");
7094 emitcode ("movx", "a,@dptr");
7099 emitcode ("mov", "b,a");
7100 emitcode ("clr", "a");
7101 emitcode ("movc", "a,@a+dptr");
7107 emitcode ("push", "b");
7108 emitcode ("push", "acc");
7110 emitcode ("lcall", "__gptrget");
7112 emitcode ("pop", "b");
7117 /*-----------------------------------------------------------------*/
7118 /* emitPtrByteSet - emits code to set a byte from src through a */
7119 /* pointer register (R0, R1, or DPTR). */
7120 /*-----------------------------------------------------------------*/
7122 emitPtrByteSet (char *rname, int p_type, char *src)
7131 emitcode ("mov", "@%s,a", rname);
7134 emitcode ("mov", "@%s,%s", rname, src);
7139 emitcode ("movx", "@%s,a", rname);
7144 emitcode ("movx", "@dptr,a");
7149 emitcode ("lcall", "__gptrput");
7154 /*-----------------------------------------------------------------*/
7155 /* genUnpackBits - generates code for unpacking bits */
7156 /*-----------------------------------------------------------------*/
7158 genUnpackBits (operand * result, char *rname, int ptype)
7160 int offset = 0; /* result byte offset */
7161 int rsize; /* result size */
7162 int rlen = 0; /* remaining bitfield length */
7163 sym_link *etype; /* bitfield type information */
7164 int blen; /* bitfield length */
7165 int bstr; /* bitfield starting bit within byte */
7167 D(emitcode ("; genUnpackBits",""));
7169 etype = getSpec (operandType (result));
7170 rsize = getSize (operandType (result));
7171 blen = SPEC_BLEN (etype);
7172 bstr = SPEC_BSTR (etype);
7174 /* If the bitfield length is less than a byte */
7177 emitPtrByteGet (rname, ptype, FALSE);
7179 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7180 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7184 /* Bit field did not fit in a byte. Copy all
7185 but the partial byte at the end. */
7186 for (rlen=blen;rlen>=8;rlen-=8)
7188 emitPtrByteGet (rname, ptype, FALSE);
7189 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7191 emitcode ("inc", "%s", rname);
7194 /* Handle the partial byte at the end */
7197 emitPtrByteGet (rname, ptype, FALSE);
7198 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7199 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7207 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7212 /*-----------------------------------------------------------------*/
7213 /* genDataPointerGet - generates code when ptr offset is known */
7214 /*-----------------------------------------------------------------*/
7216 genDataPointerGet (operand * left,
7222 int size, offset = 0;
7224 D(emitcode ("; genDataPointerGet",""));
7226 aopOp (result, ic, TRUE);
7228 /* get the string representation of the name */
7229 l = aopGet (AOP (left), 0, FALSE, TRUE);
7230 size = AOP_SIZE (result);
7234 sprintf (buffer, "(%s + %d)", l + 1, offset);
7236 sprintf (buffer, "%s", l + 1);
7237 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7240 freeAsmop (left, NULL, ic, TRUE);
7241 freeAsmop (result, NULL, ic, TRUE);
7244 /*-----------------------------------------------------------------*/
7245 /* genNearPointerGet - emitcode for near pointer fetch */
7246 /*-----------------------------------------------------------------*/
7248 genNearPointerGet (operand * left,
7256 sym_link *rtype, *retype;
7257 sym_link *ltype = operandType (left);
7260 D(emitcode ("; genNearPointerGet",""));
7262 rtype = operandType (result);
7263 retype = getSpec (rtype);
7265 aopOp (left, ic, FALSE);
7267 /* if left is rematerialisable and
7268 result is not bit variable type and
7269 the left is pointer to data space i.e
7270 lower 128 bytes of space */
7271 if (AOP_TYPE (left) == AOP_IMMD &&
7272 !IS_BITVAR (retype) &&
7273 DCL_TYPE (ltype) == POINTER)
7275 genDataPointerGet (left, result, ic);
7279 /* if the value is already in a pointer register
7280 then don't need anything more */
7281 if (!AOP_INPREG (AOP (left)))
7283 /* otherwise get a free pointer register */
7285 preg = getFreePtr (ic, &aop, FALSE);
7286 emitcode ("mov", "%s,%s",
7288 aopGet (AOP (left), 0, FALSE, TRUE));
7292 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7294 //aopOp (result, ic, FALSE);
7295 aopOp (result, ic, result?TRUE:FALSE);
7297 /* if bitfield then unpack the bits */
7298 if (IS_BITVAR (retype))
7299 genUnpackBits (result, rname, POINTER);
7302 /* we have can just get the values */
7303 int size = AOP_SIZE (result);
7308 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7311 emitcode ("mov", "a,@%s", rname);
7312 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7316 sprintf (buffer, "@%s", rname);
7317 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7321 emitcode ("inc", "%s", rname);
7325 /* now some housekeeping stuff */
7326 if (aop) /* we had to allocate for this iCode */
7328 if (pi) { /* post increment present */
7329 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7331 freeAsmop (NULL, aop, ic, TRUE);
7335 /* we did not allocate which means left
7336 already in a pointer register, then
7337 if size > 0 && this could be used again
7338 we have to point it back to where it
7340 if ((AOP_SIZE (result) > 1 &&
7341 !OP_SYMBOL (left)->remat &&
7342 (OP_SYMBOL (left)->liveTo > ic->seq ||
7346 int size = AOP_SIZE (result) - 1;
7348 emitcode ("dec", "%s", rname);
7353 freeAsmop (left, NULL, ic, TRUE);
7354 freeAsmop (result, NULL, ic, TRUE);
7355 if (pi) pi->generated = 1;
7358 /*-----------------------------------------------------------------*/
7359 /* genPagedPointerGet - emitcode for paged pointer fetch */
7360 /*-----------------------------------------------------------------*/
7362 genPagedPointerGet (operand * left,
7370 sym_link *rtype, *retype;
7372 D(emitcode ("; genPagedPointerGet",""));
7374 rtype = operandType (result);
7375 retype = getSpec (rtype);
7377 aopOp (left, ic, FALSE);
7379 /* if the value is already in a pointer register
7380 then don't need anything more */
7381 if (!AOP_INPREG (AOP (left)))
7383 /* otherwise get a free pointer register */
7385 preg = getFreePtr (ic, &aop, FALSE);
7386 emitcode ("mov", "%s,%s",
7388 aopGet (AOP (left), 0, FALSE, TRUE));
7392 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7394 aopOp (result, ic, FALSE);
7396 /* if bitfield then unpack the bits */
7397 if (IS_BITVAR (retype))
7398 genUnpackBits (result, rname, PPOINTER);
7401 /* we have can just get the values */
7402 int size = AOP_SIZE (result);
7408 emitcode ("movx", "a,@%s", rname);
7409 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7414 emitcode ("inc", "%s", rname);
7418 /* now some housekeeping stuff */
7419 if (aop) /* we had to allocate for this iCode */
7421 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7422 freeAsmop (NULL, aop, ic, TRUE);
7426 /* we did not allocate which means left
7427 already in a pointer register, then
7428 if size > 0 && this could be used again
7429 we have to point it back to where it
7431 if ((AOP_SIZE (result) > 1 &&
7432 !OP_SYMBOL (left)->remat &&
7433 (OP_SYMBOL (left)->liveTo > ic->seq ||
7437 int size = AOP_SIZE (result) - 1;
7439 emitcode ("dec", "%s", rname);
7444 freeAsmop (left, NULL, ic, TRUE);
7445 freeAsmop (result, NULL, ic, TRUE);
7446 if (pi) pi->generated = 1;
7450 /*-----------------------------------------------------------------*/
7451 /* genFarPointerGet - gget value from far space */
7452 /*-----------------------------------------------------------------*/
7454 genFarPointerGet (operand * left,
7455 operand * result, iCode * ic, iCode * pi)
7458 sym_link *retype = getSpec (operandType (result));
7460 D(emitcode ("; genFarPointerGet",""));
7462 aopOp (left, ic, FALSE);
7464 /* if the operand is already in dptr
7465 then we do nothing else we move the value to dptr */
7466 if (AOP_TYPE (left) != AOP_STR)
7468 /* if this is remateriazable */
7469 if (AOP_TYPE (left) == AOP_IMMD)
7470 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7472 { /* we need to get it byte by byte */
7473 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7474 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7477 /* so dptr know contains the address */
7478 aopOp (result, ic, FALSE);
7480 /* if bit then unpack */
7481 if (IS_BITVAR (retype))
7482 genUnpackBits (result, "dptr", FPOINTER);
7485 size = AOP_SIZE (result);
7490 emitcode ("movx", "a,@dptr");
7491 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7493 emitcode ("inc", "dptr");
7497 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7498 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7499 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7502 freeAsmop (left, NULL, ic, TRUE);
7503 freeAsmop (result, NULL, ic, TRUE);
7506 /*-----------------------------------------------------------------*/
7507 /* genCodePointerGet - gget value from code space */
7508 /*-----------------------------------------------------------------*/
7510 genCodePointerGet (operand * left,
7511 operand * result, iCode * ic, iCode *pi)
7514 sym_link *retype = getSpec (operandType (result));
7516 D(emitcode ("; genCodePointerGet",""));
7518 aopOp (left, ic, FALSE);
7520 /* if the operand is already in dptr
7521 then we do nothing else we move the value to dptr */
7522 if (AOP_TYPE (left) != AOP_STR)
7524 /* if this is remateriazable */
7525 if (AOP_TYPE (left) == AOP_IMMD)
7526 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7528 { /* we need to get it byte by byte */
7529 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7530 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7533 /* so dptr know contains the address */
7534 aopOp (result, ic, FALSE);
7536 /* if bit then unpack */
7537 if (IS_BITVAR (retype))
7538 genUnpackBits (result, "dptr", CPOINTER);
7541 size = AOP_SIZE (result);
7548 emitcode ("clr", "a");
7549 emitcode ("movc", "a,@a+dptr");
7550 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7551 emitcode ("inc", "dptr");
7555 emitcode ("mov", "a,#0x%02x", offset);
7556 emitcode ("movc", "a,@a+dptr");
7557 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7562 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7563 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7564 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7567 freeAsmop (left, NULL, ic, TRUE);
7568 freeAsmop (result, NULL, ic, TRUE);
7571 /*-----------------------------------------------------------------*/
7572 /* genGenPointerGet - gget value from generic pointer space */
7573 /*-----------------------------------------------------------------*/
7575 genGenPointerGet (operand * left,
7576 operand * result, iCode * ic, iCode *pi)
7579 sym_link *retype = getSpec (operandType (result));
7581 D(emitcode ("; genGenPointerGet",""));
7583 aopOp (left, ic, FALSE);
7585 /* if the operand is already in dptr
7586 then we do nothing else we move the value to dptr */
7587 if (AOP_TYPE (left) != AOP_STR)
7589 /* if this is remateriazable */
7590 if (AOP_TYPE (left) == AOP_IMMD)
7592 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7593 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7594 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7596 emitcode ("mov", "b,#%d", pointerCode (retype));
7599 { /* we need to get it byte by byte */
7600 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7601 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7602 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7605 /* so dptr know contains the address */
7606 aopOp (result, ic, FALSE);
7608 /* if bit then unpack */
7609 if (IS_BITVAR (retype))
7610 genUnpackBits (result, "dptr", GPOINTER);
7613 size = AOP_SIZE (result);
7618 emitcode ("lcall", "__gptrget");
7619 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7621 emitcode ("inc", "dptr");
7625 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7626 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7627 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7630 freeAsmop (left, NULL, ic, TRUE);
7631 freeAsmop (result, NULL, ic, TRUE);
7634 /*-----------------------------------------------------------------*/
7635 /* genPointerGet - generate code for pointer get */
7636 /*-----------------------------------------------------------------*/
7638 genPointerGet (iCode * ic, iCode *pi)
7640 operand *left, *result;
7641 sym_link *type, *etype;
7644 D(emitcode ("; genPointerGet",""));
7646 left = IC_LEFT (ic);
7647 result = IC_RESULT (ic);
7649 /* depending on the type of pointer we need to
7650 move it to the correct pointer register */
7651 type = operandType (left);
7652 etype = getSpec (type);
7653 /* if left is of type of pointer then it is simple */
7654 if (IS_PTR (type) && !IS_FUNC (type->next))
7655 p_type = DCL_TYPE (type);
7658 /* we have to go by the storage class */
7659 p_type = PTR_TYPE (SPEC_OCLS (etype));
7662 /* special case when cast remat */
7663 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7664 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7665 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7666 type = operandType (left);
7667 p_type = DCL_TYPE (type);
7669 /* now that we have the pointer type we assign
7670 the pointer values */
7676 genNearPointerGet (left, result, ic, pi);
7680 genPagedPointerGet (left, result, ic, pi);
7684 genFarPointerGet (left, result, ic, pi);
7688 genCodePointerGet (left, result, ic, pi);
7692 genGenPointerGet (left, result, ic, pi);
7700 /*-----------------------------------------------------------------*/
7701 /* genPackBits - generates code for packed bit storage */
7702 /*-----------------------------------------------------------------*/
7704 genPackBits (sym_link * etype,
7706 char *rname, int p_type)
7708 int offset = 0; /* source byte offset */
7709 int rlen = 0; /* remaining bitfield length */
7710 int blen; /* bitfield length */
7711 int bstr; /* bitfield starting bit within byte */
7712 int litval; /* source literal value (if AOP_LIT) */
7713 unsigned char mask; /* bitmask within current byte */
7715 D(emitcode ("; genPackBits",""));
7717 blen = SPEC_BLEN (etype);
7718 bstr = SPEC_BSTR (etype);
7720 /* If the bitfield length is less than a byte */
7723 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7724 (unsigned char) (0xFF >> (8 - bstr)));
7726 if (AOP_TYPE (right) == AOP_LIT)
7728 /* Case with a bitfield length <8 and literal source
7730 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7732 litval &= (~mask) & 0xff;
7733 emitPtrByteGet (rname, p_type, FALSE);
7734 if ((mask|litval)!=0xff)
7735 emitcode ("anl","a,#0x%02x", mask);
7737 emitcode ("orl","a,#0x%02x", litval);
7741 if ((blen==1) && (p_type!=GPOINTER))
7743 /* Case with a bitfield length == 1 and no generic pointer
7745 if (AOP_TYPE (right) == AOP_CRY)
7746 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7749 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7750 emitcode ("rrc","a");
7752 emitPtrByteGet (rname, p_type, FALSE);
7753 emitcode ("mov","acc.%d,c",bstr);
7757 /* Case with a bitfield length < 8 and arbitrary source
7759 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7760 /* shift and mask source value */
7762 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7764 /* transfer A to B and get next byte */
7765 emitPtrByteGet (rname, p_type, TRUE);
7767 emitcode ("anl", "a,#0x%02x", mask);
7768 emitcode ("orl", "a,b");
7769 if (p_type == GPOINTER)
7770 emitcode ("pop", "b");
7774 emitPtrByteSet (rname, p_type, "a");
7778 /* Bit length is greater than 7 bits. In this case, copy */
7779 /* all except the partial byte at the end */
7780 for (rlen=blen;rlen>=8;rlen-=8)
7782 emitPtrByteSet (rname, p_type,
7783 aopGet (AOP (right), offset++, FALSE, TRUE) );
7785 emitcode ("inc", "%s", rname);
7788 /* If there was a partial byte at the end */
7791 mask = (((unsigned char) -1 << rlen) & 0xff);
7793 if (AOP_TYPE (right) == AOP_LIT)
7795 /* Case with partial byte and literal source
7797 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7798 litval >>= (blen-rlen);
7799 litval &= (~mask) & 0xff;
7800 emitPtrByteGet (rname, p_type, FALSE);
7801 if ((mask|litval)!=0xff)
7802 emitcode ("anl","a,#0x%02x", mask);
7804 emitcode ("orl","a,#0x%02x", litval);
7808 /* Case with partial byte and arbitrary source
7810 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
7811 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7813 /* transfer A to B and get next byte */
7814 emitPtrByteGet (rname, p_type, TRUE);
7816 emitcode ("anl", "a,#0x%02x", mask);
7817 emitcode ("orl", "a,b");
7818 if (p_type == GPOINTER)
7819 emitcode ("pop", "b");
7821 emitPtrByteSet (rname, p_type, "a");
7827 /*-----------------------------------------------------------------*/
7828 /* genDataPointerSet - remat pointer to data space */
7829 /*-----------------------------------------------------------------*/
7831 genDataPointerSet (operand * right,
7835 int size, offset = 0;
7836 char *l, buffer[256];
7838 D(emitcode ("; genDataPointerSet",""));
7840 aopOp (right, ic, FALSE);
7842 l = aopGet (AOP (result), 0, FALSE, TRUE);
7843 size = AOP_SIZE (right);
7847 sprintf (buffer, "(%s + %d)", l + 1, offset);
7849 sprintf (buffer, "%s", l + 1);
7850 emitcode ("mov", "%s,%s", buffer,
7851 aopGet (AOP (right), offset++, FALSE, FALSE));
7854 freeAsmop (right, NULL, ic, TRUE);
7855 freeAsmop (result, NULL, ic, TRUE);
7858 /*-----------------------------------------------------------------*/
7859 /* genNearPointerSet - emitcode for near pointer put */
7860 /*-----------------------------------------------------------------*/
7862 genNearPointerSet (operand * right,
7870 sym_link *retype, *letype;
7871 sym_link *ptype = operandType (result);
7873 D(emitcode ("; genNearPointerSet",""));
7875 retype = getSpec (operandType (right));
7876 letype = getSpec (ptype);
7877 aopOp (result, ic, FALSE);
7879 /* if the result is rematerializable &
7880 in data space & not a bit variable */
7881 if (AOP_TYPE (result) == AOP_IMMD &&
7882 DCL_TYPE (ptype) == POINTER &&
7883 !IS_BITVAR (retype) &&
7884 !IS_BITVAR (letype))
7886 genDataPointerSet (right, result, ic);
7890 /* if the value is already in a pointer register
7891 then don't need anything more */
7892 if (!AOP_INPREG (AOP (result)))
7895 //AOP_TYPE (result) == AOP_STK
7899 // Aha, it is a pointer, just in disguise.
7900 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7903 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7904 __FILE__, __LINE__);
7909 rname++; // skip the '@'.
7914 /* otherwise get a free pointer register */
7916 preg = getFreePtr (ic, &aop, FALSE);
7917 emitcode ("mov", "%s,%s",
7919 aopGet (AOP (result), 0, FALSE, TRUE));
7925 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7928 aopOp (right, ic, FALSE);
7930 /* if bitfield then unpack the bits */
7931 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7932 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7935 /* we have can just get the values */
7936 int size = AOP_SIZE (right);
7941 l = aopGet (AOP (right), offset, FALSE, TRUE);
7945 emitcode ("mov", "@%s,a", rname);
7948 emitcode ("mov", "@%s,%s", rname, l);
7950 emitcode ("inc", "%s", rname);
7955 /* now some housekeeping stuff */
7956 if (aop) /* we had to allocate for this iCode */
7959 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
7960 freeAsmop (NULL, aop, ic, TRUE);
7964 /* we did not allocate which means left
7965 already in a pointer register, then
7966 if size > 0 && this could be used again
7967 we have to point it back to where it
7969 if ((AOP_SIZE (right) > 1 &&
7970 !OP_SYMBOL (result)->remat &&
7971 (OP_SYMBOL (result)->liveTo > ic->seq ||
7975 int size = AOP_SIZE (right) - 1;
7977 emitcode ("dec", "%s", rname);
7982 if (pi) pi->generated = 1;
7983 freeAsmop (result, NULL, ic, TRUE);
7984 freeAsmop (right, NULL, ic, TRUE);
7987 /*-----------------------------------------------------------------*/
7988 /* genPagedPointerSet - emitcode for Paged pointer put */
7989 /*-----------------------------------------------------------------*/
7991 genPagedPointerSet (operand * right,
7999 sym_link *retype, *letype;
8001 D(emitcode ("; genPagedPointerSet",""));
8003 retype = getSpec (operandType (right));
8004 letype = getSpec (operandType (result));
8006 aopOp (result, ic, FALSE);
8008 /* if the value is already in a pointer register
8009 then don't need anything more */
8010 if (!AOP_INPREG (AOP (result)))
8012 /* otherwise get a free pointer register */
8014 preg = getFreePtr (ic, &aop, FALSE);
8015 emitcode ("mov", "%s,%s",
8017 aopGet (AOP (result), 0, FALSE, TRUE));
8021 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8023 aopOp (right, ic, FALSE);
8025 /* if bitfield then unpack the bits */
8026 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8027 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8030 /* we have can just get the values */
8031 int size = AOP_SIZE (right);
8036 l = aopGet (AOP (right), offset, FALSE, TRUE);
8039 emitcode ("movx", "@%s,a", rname);
8042 emitcode ("inc", "%s", rname);
8048 /* now some housekeeping stuff */
8049 if (aop) /* we had to allocate for this iCode */
8052 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8053 freeAsmop (NULL, aop, ic, TRUE);
8057 /* we did not allocate which means left
8058 already in a pointer register, then
8059 if size > 0 && this could be used again
8060 we have to point it back to where it
8062 if (AOP_SIZE (right) > 1 &&
8063 !OP_SYMBOL (result)->remat &&
8064 (OP_SYMBOL (result)->liveTo > ic->seq ||
8067 int size = AOP_SIZE (right) - 1;
8069 emitcode ("dec", "%s", rname);
8074 if (pi) pi->generated = 1;
8075 freeAsmop (result, NULL, ic, TRUE);
8076 freeAsmop (right, NULL, ic, TRUE);
8081 /*-----------------------------------------------------------------*/
8082 /* genFarPointerSet - set value from far space */
8083 /*-----------------------------------------------------------------*/
8085 genFarPointerSet (operand * right,
8086 operand * result, iCode * ic, iCode * pi)
8089 sym_link *retype = getSpec (operandType (right));
8090 sym_link *letype = getSpec (operandType (result));
8092 D(emitcode ("; genFarPointerSet",""));
8094 aopOp (result, ic, FALSE);
8096 /* if the operand is already in dptr
8097 then we do nothing else we move the value to dptr */
8098 if (AOP_TYPE (result) != AOP_STR)
8100 /* if this is remateriazable */
8101 if (AOP_TYPE (result) == AOP_IMMD)
8102 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8104 { /* we need to get it byte by byte */
8105 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8106 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8109 /* so dptr know contains the address */
8110 aopOp (right, ic, FALSE);
8112 /* if bit then unpack */
8113 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8114 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8117 size = AOP_SIZE (right);
8122 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8124 emitcode ("movx", "@dptr,a");
8126 emitcode ("inc", "dptr");
8129 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8130 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8131 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8134 freeAsmop (result, NULL, ic, TRUE);
8135 freeAsmop (right, NULL, ic, TRUE);
8138 /*-----------------------------------------------------------------*/
8139 /* genGenPointerSet - set value from generic pointer space */
8140 /*-----------------------------------------------------------------*/
8142 genGenPointerSet (operand * right,
8143 operand * result, iCode * ic, iCode * pi)
8146 sym_link *retype = getSpec (operandType (right));
8147 sym_link *letype = getSpec (operandType (result));
8149 D(emitcode ("; genGenPointerSet",""));
8151 aopOp (result, ic, FALSE);
8153 /* if the operand is already in dptr
8154 then we do nothing else we move the value to dptr */
8155 if (AOP_TYPE (result) != AOP_STR)
8157 /* if this is remateriazable */
8158 if (AOP_TYPE (result) == AOP_IMMD)
8160 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8161 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8162 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8164 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8167 { /* we need to get it byte by byte */
8168 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8169 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8170 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8173 /* so dptr know contains the address */
8174 aopOp (right, ic, FALSE);
8176 /* if bit then unpack */
8177 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8178 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8181 size = AOP_SIZE (right);
8186 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8188 emitcode ("lcall", "__gptrput");
8190 emitcode ("inc", "dptr");
8194 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8195 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8196 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8199 freeAsmop (result, NULL, ic, TRUE);
8200 freeAsmop (right, NULL, ic, TRUE);
8203 /*-----------------------------------------------------------------*/
8204 /* genPointerSet - stores the value into a pointer location */
8205 /*-----------------------------------------------------------------*/
8207 genPointerSet (iCode * ic, iCode *pi)
8209 operand *right, *result;
8210 sym_link *type, *etype;
8213 D(emitcode ("; genPointerSet",""));
8215 right = IC_RIGHT (ic);
8216 result = IC_RESULT (ic);
8218 /* depending on the type of pointer we need to
8219 move it to the correct pointer register */
8220 type = operandType (result);
8221 etype = getSpec (type);
8222 /* if left is of type of pointer then it is simple */
8223 if (IS_PTR (type) && !IS_FUNC (type->next))
8225 p_type = DCL_TYPE (type);
8229 /* we have to go by the storage class */
8230 p_type = PTR_TYPE (SPEC_OCLS (etype));
8233 /* special case when cast remat */
8234 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8235 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8236 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8237 type = operandType (result);
8238 p_type = DCL_TYPE (type);
8240 /* now that we have the pointer type we assign
8241 the pointer values */
8247 genNearPointerSet (right, result, ic, pi);
8251 genPagedPointerSet (right, result, ic, pi);
8255 genFarPointerSet (right, result, ic, pi);
8259 genGenPointerSet (right, result, ic, pi);
8263 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8264 "genPointerSet: illegal pointer type");
8269 /*-----------------------------------------------------------------*/
8270 /* genIfx - generate code for Ifx statement */
8271 /*-----------------------------------------------------------------*/
8273 genIfx (iCode * ic, iCode * popIc)
8275 operand *cond = IC_COND (ic);
8278 D(emitcode ("; genIfx",""));
8280 aopOp (cond, ic, FALSE);
8282 /* get the value into acc */
8283 if (AOP_TYPE (cond) != AOP_CRY)
8287 /* the result is now in the accumulator */
8288 freeAsmop (cond, NULL, ic, TRUE);
8290 /* if there was something to be popped then do it */
8294 /* if the condition is a bit variable */
8295 if (isbit && IS_ITEMP (cond) &&
8297 genIfxJump (ic, SPIL_LOC (cond)->rname);
8298 else if (isbit && !IS_ITEMP (cond))
8299 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8301 genIfxJump (ic, "a");
8306 /*-----------------------------------------------------------------*/
8307 /* genAddrOf - generates code for address of */
8308 /*-----------------------------------------------------------------*/
8310 genAddrOf (iCode * ic)
8312 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8315 D(emitcode ("; genAddrOf",""));
8317 aopOp (IC_RESULT (ic), ic, FALSE);
8319 /* if the operand is on the stack then we
8320 need to get the stack offset of this
8324 /* if it has an offset then we need to compute
8328 emitcode ("mov", "a,_bp");
8329 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8330 ((char) (sym->stack - _G.nRegsSaved)) :
8331 ((char) sym->stack)) & 0xff);
8332 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8336 /* we can just move _bp */
8337 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8339 /* fill the result with zero */
8340 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8345 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8351 /* object not on stack then we need the name */
8352 size = AOP_SIZE (IC_RESULT (ic));
8357 char s[SDCC_NAME_MAX];
8359 sprintf (s, "#(%s >> %d)",
8363 sprintf (s, "#%s", sym->rname);
8364 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8368 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8372 /*-----------------------------------------------------------------*/
8373 /* genFarFarAssign - assignment when both are in far space */
8374 /*-----------------------------------------------------------------*/
8376 genFarFarAssign (operand * result, operand * right, iCode * ic)
8378 int size = AOP_SIZE (right);
8382 D(emitcode ("; genFarFarAssign",""));
8384 /* first push the right side on to the stack */
8387 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8389 emitcode ("push", "acc");
8392 freeAsmop (right, NULL, ic, FALSE);
8393 /* now assign DPTR to result */
8394 aopOp (result, ic, FALSE);
8395 size = AOP_SIZE (result);
8398 emitcode ("pop", "acc");
8399 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8401 freeAsmop (result, NULL, ic, FALSE);
8405 /*-----------------------------------------------------------------*/
8406 /* genAssign - generate code for assignment */
8407 /*-----------------------------------------------------------------*/
8409 genAssign (iCode * ic)
8411 operand *result, *right;
8413 unsigned long lit = 0L;
8415 D(emitcode("; genAssign",""));
8417 result = IC_RESULT (ic);
8418 right = IC_RIGHT (ic);
8420 /* if they are the same */
8421 if (operandsEqu (result, right) &&
8422 !isOperandVolatile (result, FALSE) &&
8423 !isOperandVolatile (right, FALSE))
8426 aopOp (right, ic, FALSE);
8428 /* special case both in far space */
8429 if (AOP_TYPE (right) == AOP_DPTR &&
8430 IS_TRUE_SYMOP (result) &&
8431 isOperandInFarSpace (result))
8434 genFarFarAssign (result, right, ic);
8438 aopOp (result, ic, TRUE);
8440 /* if they are the same registers */
8441 if (sameRegs (AOP (right), AOP (result)) &&
8442 !isOperandVolatile (result, FALSE) &&
8443 !isOperandVolatile (right, FALSE))
8446 /* if the result is a bit */
8447 if (AOP_TYPE (result) == AOP_CRY)
8450 /* if the right size is a literal then
8451 we know what the value is */
8452 if (AOP_TYPE (right) == AOP_LIT)
8454 if (((int) operandLitValue (right)))
8455 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8457 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8461 /* the right is also a bit variable */
8462 if (AOP_TYPE (right) == AOP_CRY)
8464 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8465 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8471 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8475 /* bit variables done */
8477 size = AOP_SIZE (result);
8479 if (AOP_TYPE (right) == AOP_LIT)
8480 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8482 (AOP_TYPE (result) != AOP_REG) &&
8483 (AOP_TYPE (right) == AOP_LIT) &&
8484 !IS_FLOAT (operandType (right)) &&
8487 emitcode ("clr", "a");
8490 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8491 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8493 aopPut (AOP (result),
8494 aopGet (AOP (right), size, FALSE, FALSE),
8496 isOperandVolatile (result, FALSE));
8503 aopPut (AOP (result),
8504 aopGet (AOP (right), offset, FALSE, FALSE),
8506 isOperandVolatile (result, FALSE));
8512 freeAsmop (right, NULL, ic, TRUE);
8513 freeAsmop (result, NULL, ic, TRUE);
8516 /*-----------------------------------------------------------------*/
8517 /* genJumpTab - genrates code for jump table */
8518 /*-----------------------------------------------------------------*/
8520 genJumpTab (iCode * ic)
8525 D(emitcode ("; genJumpTab",""));
8527 aopOp (IC_JTCOND (ic), ic, FALSE);
8528 /* get the condition into accumulator */
8529 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8531 /* multiply by three */
8532 emitcode ("add", "a,acc");
8533 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8534 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8536 jtab = newiTempLabel (NULL);
8537 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8538 emitcode ("jmp", "@a+dptr");
8539 emitcode ("", "%05d$:", jtab->key + 100);
8540 /* now generate the jump labels */
8541 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8542 jtab = setNextItem (IC_JTLABELS (ic)))
8543 emitcode ("ljmp", "%05d$", jtab->key + 100);
8547 /*-----------------------------------------------------------------*/
8548 /* genCast - gen code for casting */
8549 /*-----------------------------------------------------------------*/
8551 genCast (iCode * ic)
8553 operand *result = IC_RESULT (ic);
8554 sym_link *ctype = operandType (IC_LEFT (ic));
8555 sym_link *rtype = operandType (IC_RIGHT (ic));
8556 operand *right = IC_RIGHT (ic);
8559 D(emitcode("; genCast",""));
8561 /* if they are equivalent then do nothing */
8562 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8565 aopOp (right, ic, FALSE);
8566 aopOp (result, ic, FALSE);
8568 /* if the result is a bit (and not a bitfield) */
8569 // if (AOP_TYPE (result) == AOP_CRY)
8570 if (IS_BITVAR (OP_SYMBOL (result)->type)
8571 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8573 /* if the right size is a literal then
8574 we know what the value is */
8575 if (AOP_TYPE (right) == AOP_LIT)
8577 if (((int) operandLitValue (right)))
8578 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8580 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8585 /* the right is also a bit variable */
8586 if (AOP_TYPE (right) == AOP_CRY)
8588 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8589 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8595 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8600 /* if they are the same size : or less */
8601 if (AOP_SIZE (result) <= AOP_SIZE (right))
8604 /* if they are in the same place */
8605 if (sameRegs (AOP (right), AOP (result)))
8608 /* if they in different places then copy */
8609 size = AOP_SIZE (result);
8613 aopPut (AOP (result),
8614 aopGet (AOP (right), offset, FALSE, FALSE),
8616 isOperandVolatile (result, FALSE));
8623 /* if the result is of type pointer */
8628 sym_link *type = operandType (right);
8629 sym_link *etype = getSpec (type);
8631 /* pointer to generic pointer */
8632 if (IS_GENPTR (ctype))
8635 p_type = DCL_TYPE (type);
8638 if (SPEC_SCLS(etype)==S_REGISTER) {
8639 // let's assume it is a generic pointer
8642 /* we have to go by the storage class */
8643 p_type = PTR_TYPE (SPEC_OCLS (etype));
8647 /* the first two bytes are known */
8648 size = GPTRSIZE - 1;
8652 aopPut (AOP (result),
8653 aopGet (AOP (right), offset, FALSE, FALSE),
8655 isOperandVolatile (result, FALSE));
8658 /* the last byte depending on type */
8660 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8665 // pointerTypeToGPByte will have bitched.
8669 sprintf(gpValStr, "#0x%d", gpVal);
8670 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8675 /* just copy the pointers */
8676 size = AOP_SIZE (result);
8680 aopPut (AOP (result),
8681 aopGet (AOP (right), offset, FALSE, FALSE),
8683 isOperandVolatile (result, FALSE));
8689 /* so we now know that the size of destination is greater
8690 than the size of the source */
8691 /* we move to result for the size of source */
8692 size = AOP_SIZE (right);
8696 aopPut (AOP (result),
8697 aopGet (AOP (right), offset, FALSE, FALSE),
8699 isOperandVolatile (result, FALSE));
8703 /* now depending on the sign of the source && destination */
8704 size = AOP_SIZE (result) - AOP_SIZE (right);
8705 /* if unsigned or not an integral type */
8706 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8709 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8713 /* we need to extend the sign :{ */
8714 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8717 emitcode ("rlc", "a");
8718 emitcode ("subb", "a,acc");
8720 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8723 /* we are done hurray !!!! */
8726 freeAsmop (right, NULL, ic, TRUE);
8727 freeAsmop (result, NULL, ic, TRUE);
8731 /*-----------------------------------------------------------------*/
8732 /* genDjnz - generate decrement & jump if not zero instrucion */
8733 /*-----------------------------------------------------------------*/
8735 genDjnz (iCode * ic, iCode * ifx)
8741 D(emitcode ("; genDjnz",""));
8743 /* if the if condition has a false label
8744 then we cannot save */
8748 /* if the minus is not of the form
8750 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8751 !IS_OP_LITERAL (IC_RIGHT (ic)))
8754 if (operandLitValue (IC_RIGHT (ic)) != 1)
8757 /* if the size of this greater than one then no
8759 if (getSize (operandType (IC_RESULT (ic))) > 1)
8762 /* otherwise we can save BIG */
8763 lbl = newiTempLabel (NULL);
8764 lbl1 = newiTempLabel (NULL);
8766 aopOp (IC_RESULT (ic), ic, FALSE);
8768 if (AOP_NEEDSACC(IC_RESULT(ic)))
8770 /* If the result is accessed indirectly via
8771 * the accumulator, we must explicitly write
8772 * it back after the decrement.
8774 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8776 if (strcmp(rByte, "a"))
8778 /* Something is hopelessly wrong */
8779 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8780 __FILE__, __LINE__);
8781 /* We can just give up; the generated code will be inefficient,
8784 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8787 emitcode ("dec", "%s", rByte);
8788 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8789 emitcode ("jnz", "%05d$", lbl->key + 100);
8791 else if (IS_AOP_PREG (IC_RESULT (ic)))
8793 emitcode ("dec", "%s",
8794 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8795 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8796 emitcode ("jnz", "%05d$", lbl->key + 100);
8800 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8803 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8804 emitcode ("", "%05d$:", lbl->key + 100);
8805 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8806 emitcode ("", "%05d$:", lbl1->key + 100);
8808 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8813 /*-----------------------------------------------------------------*/
8814 /* genReceive - generate code for a receive iCode */
8815 /*-----------------------------------------------------------------*/
8817 genReceive (iCode * ic)
8819 int size = getSize (operandType (IC_RESULT (ic)));
8821 D(emitcode ("; genReceive",""));
8823 if (ic->argreg == 1) { /* first parameter */
8824 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8825 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8826 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8828 offset = fReturnSizeMCS51 - size;
8830 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8831 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8834 aopOp (IC_RESULT (ic), ic, FALSE);
8835 size = AOP_SIZE (IC_RESULT (ic));
8838 emitcode ("pop", "acc");
8839 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8844 aopOp (IC_RESULT (ic), ic, FALSE);
8846 assignResultValue (IC_RESULT (ic));
8848 } else { /* second receive onwards */
8850 aopOp (IC_RESULT (ic), ic, FALSE);
8851 rb1off = ic->argreg;
8853 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8856 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8859 /*-----------------------------------------------------------------*/
8860 /* genDummyRead - generate code for dummy read of volatiles */
8861 /*-----------------------------------------------------------------*/
8863 genDummyRead (iCode * ic)
8868 D(emitcode("; genDummyRead",""));
8870 right = IC_RIGHT (ic);
8872 aopOp (right, ic, FALSE);
8874 /* if the result is a bit */
8875 if (AOP_TYPE (right) == AOP_CRY)
8877 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8881 /* bit variables done */
8883 size = AOP_SIZE (right);
8887 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
8892 freeAsmop (right, NULL, ic, TRUE);
8895 /*-----------------------------------------------------------------*/
8896 /* gen51Code - generate code for 8051 based controllers */
8897 /*-----------------------------------------------------------------*/
8899 gen51Code (iCode * lic)
8904 lineHead = lineCurr = NULL;
8906 /* print the allocation information */
8907 if (allocInfo && currFunc)
8908 printAllocInfo (currFunc, codeOutFile);
8909 /* if debug information required */
8910 if (options.debug && currFunc)
8912 debugFile->writeFunction(currFunc);
8914 if (IS_STATIC (currFunc->etype))
8915 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8917 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8920 /* stack pointer name */
8921 if (options.useXstack)
8927 for (ic = lic; ic; ic = ic->next)
8930 if (ic->lineno && cln != ic->lineno)
8935 emitcode ("", "C$%s$%d$%d$%d ==.",
8936 FileBaseName (ic->filename), ic->lineno,
8937 ic->level, ic->block);
8940 if (!options.noCcodeInAsm) {
8941 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8942 printCLine(ic->filename, ic->lineno));
8946 if (options.iCodeInAsm) {
8950 for (i=0; i<8; i++) {
8951 sprintf (®sInUse[i],
8952 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8955 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8957 /* if the result is marked as
8958 spilt and rematerializable or code for
8959 this has already been generated then
8961 if (resultRemat (ic) || ic->generated)
8964 /* depending on the operation */
8984 /* IPOP happens only when trying to restore a
8985 spilt live range, if there is an ifx statement
8986 following this pop then the if statement might
8987 be using some of the registers being popped which
8988 would destory the contents of the register so
8989 we need to check for this condition and handle it */
8991 ic->next->op == IFX &&
8992 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8993 genIfx (ic->next, ic);
9011 genEndFunction (ic);
9031 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9048 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9052 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9059 /* note these two are xlated by algebraic equivalence
9060 during parsing SDCC.y */
9061 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9062 "got '>=' or '<=' shouldn't have come here");
9066 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9078 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9082 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9086 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9113 case GET_VALUE_AT_ADDRESS:
9114 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9118 if (POINTER_SET (ic))
9119 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9145 addSet (&_G.sendSet, ic);
9148 case DUMMY_READ_VOLATILE:
9158 /* now we are ready to call the
9159 peep hole optimizer */
9160 if (!options.nopeep)
9161 peepHole (&lineHead);
9163 /* now do the actual printing */
9164 printLine (lineHead, codeOutFile);