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))
137 lineCurr = (lineCurr ?
138 connectLine (lineCurr, newLineNode (lb)) :
139 (lineHead = newLineNode (lb)));
140 lineCurr->isInline = _G.inLine;
141 lineCurr->isDebug = _G.debugLine;
145 /*-----------------------------------------------------------------*/
146 /* mova - moves specified value into accumulator */
147 /*-----------------------------------------------------------------*/
151 /* do some early peephole optimization */
152 if (!strcmp(x, "a") || !strcmp(x, "acc"))
155 emitcode("mov","a,%s", x);
158 /*-----------------------------------------------------------------*/
159 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
160 /*-----------------------------------------------------------------*/
162 getFreePtr (iCode * ic, asmop ** aopp, bool result)
164 bool r0iu = FALSE, r1iu = FALSE;
165 bool r0ou = FALSE, r1ou = FALSE;
167 /* the logic: if r0 & r1 used in the instruction
168 then we are in trouble otherwise */
170 /* first check if r0 & r1 are used by this
171 instruction, in which case we are in trouble */
172 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
173 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
178 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
179 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
181 /* if no usage of r0 then return it */
184 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
185 (*aopp)->type = AOP_R0;
187 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
190 /* if no usage of r1 then return it */
193 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
194 (*aopp)->type = AOP_R1;
196 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
199 /* now we know they both have usage */
200 /* if r0 not used in this instruction */
203 /* push it if not already pushed */
206 emitcode ("push", "%s",
207 mcs51_regWithIdx (R0_IDX)->dname);
211 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
212 (*aopp)->type = AOP_R0;
214 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
217 /* if r1 not used then */
221 /* push it if not already pushed */
224 emitcode ("push", "%s",
225 mcs51_regWithIdx (R1_IDX)->dname);
229 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
230 (*aopp)->type = AOP_R1;
231 return mcs51_regWithIdx (R1_IDX);
234 /* I said end of world, but not quite end of world yet */
236 /* we can push it on the stack */
237 (*aopp)->type = AOP_STK;
240 /* in the case that result AND left AND right needs a pointer reg
241 we can safely use the result's */
242 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
243 (*aopp)->type = AOP_R0;
244 return mcs51_regWithIdx (R0_IDX);
246 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
247 (*aopp)->type = AOP_R1;
248 return mcs51_regWithIdx (R1_IDX);
252 /* now this is REALLY the end of the world */
253 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
254 "getFreePtr should never reach here");
258 /*-----------------------------------------------------------------*/
259 /* newAsmop - creates a new asmOp */
260 /*-----------------------------------------------------------------*/
262 newAsmop (short type)
266 aop = Safe_calloc (1, sizeof (asmop));
271 /*-----------------------------------------------------------------*/
272 /* pointerCode - returns the code for a pointer type */
273 /*-----------------------------------------------------------------*/
275 pointerCode (sym_link * etype)
278 return PTR_TYPE (SPEC_OCLS (etype));
282 /*-----------------------------------------------------------------*/
283 /* aopForSym - for a true symbol */
284 /*-----------------------------------------------------------------*/
286 aopForSym (iCode * ic, symbol * sym, bool result)
291 wassertl (ic != NULL, "Got a null iCode");
292 wassertl (sym != NULL, "Got a null symbol");
294 space = SPEC_OCLS (sym->etype);
296 /* if already has one */
300 /* assign depending on the storage class */
301 /* if it is on the stack or indirectly addressable */
302 /* space we need to assign either r0 or r1 to it */
303 if (sym->onStack || sym->iaccess)
305 sym->aop = aop = newAsmop (0);
306 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
307 aop->size = getSize (sym->type);
309 /* now assign the address of the variable to
310 the pointer register */
311 if (aop->type != AOP_STK)
317 emitcode ("push", "acc");
319 emitcode ("mov", "a,_bp");
320 emitcode ("add", "a,#0x%02x",
322 ((char) (sym->stack - _G.nRegsSaved)) :
323 ((char) sym->stack)) & 0xff);
324 emitcode ("mov", "%s,a",
325 aop->aopu.aop_ptr->name);
328 emitcode ("pop", "acc");
331 emitcode ("mov", "%s,#%s",
332 aop->aopu.aop_ptr->name,
334 aop->paged = space->paged;
337 aop->aopu.aop_stk = sym->stack;
341 /* if in bit space */
342 if (IN_BITSPACE (space))
344 sym->aop = aop = newAsmop (AOP_CRY);
345 aop->aopu.aop_dir = sym->rname;
346 aop->size = getSize (sym->type);
349 /* if it is in direct space */
350 if (IN_DIRSPACE (space))
352 sym->aop = aop = newAsmop (AOP_DIR);
353 aop->aopu.aop_dir = sym->rname;
354 aop->size = getSize (sym->type);
358 /* special case for a function */
359 if (IS_FUNC (sym->type))
361 sym->aop = aop = newAsmop (AOP_IMMD);
362 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
363 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
364 aop->size = FPTRSIZE;
368 /* only remaining is far space */
369 /* in which case DPTR gets the address */
370 sym->aop = aop = newAsmop (AOP_DPTR);
371 emitcode ("mov", "dptr,#%s", sym->rname);
372 aop->size = getSize (sym->type);
374 /* if it is in code space */
375 if (IN_CODESPACE (space))
381 /*-----------------------------------------------------------------*/
382 /* aopForRemat - rematerialzes an object */
383 /*-----------------------------------------------------------------*/
385 aopForRemat (symbol * sym)
387 iCode *ic = sym->rematiCode;
388 asmop *aop = newAsmop (AOP_IMMD);
395 val += (int) operandLitValue (IC_RIGHT (ic));
396 else if (ic->op == '-')
397 val -= (int) operandLitValue (IC_RIGHT (ic));
398 else if (IS_CAST_ICODE(ic)) {
399 sym_link *from_type = operandType(IC_RIGHT(ic));
400 aop->aopu.aop_immd.from_cast_remat = 1;
401 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
402 ptr_type = DCL_TYPE(from_type);
403 if (ptr_type == IPOINTER) {
410 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
414 sprintf (buffer, "(%s %c 0x%04x)",
415 OP_SYMBOL (IC_LEFT (ic))->rname,
416 val >= 0 ? '+' : '-',
419 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
421 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
422 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
423 /* set immd2 field if required */
424 if (aop->aopu.aop_immd.from_cast_remat) {
425 sprintf(buffer,"#0x%02x",ptr_type);
426 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
427 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
433 /*-----------------------------------------------------------------*/
434 /* regsInCommon - two operands have some registers in common */
435 /*-----------------------------------------------------------------*/
437 regsInCommon (operand * op1, operand * op2)
442 /* if they have registers in common */
443 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
446 sym1 = OP_SYMBOL (op1);
447 sym2 = OP_SYMBOL (op2);
449 if (sym1->nRegs == 0 || sym2->nRegs == 0)
452 for (i = 0; i < sym1->nRegs; i++)
458 for (j = 0; j < sym2->nRegs; j++)
463 if (sym2->regs[j] == sym1->regs[i])
471 /*-----------------------------------------------------------------*/
472 /* operandsEqu - equivalent */
473 /*-----------------------------------------------------------------*/
475 operandsEqu (operand * op1, operand * op2)
479 /* if they not symbols */
480 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
483 sym1 = OP_SYMBOL (op1);
484 sym2 = OP_SYMBOL (op2);
486 /* if both are itemps & one is spilt
487 and the other is not then false */
488 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
489 sym1->isspilt != sym2->isspilt)
492 /* if they are the same */
496 if (strcmp (sym1->rname, sym2->rname) == 0)
500 /* if left is a tmp & right is not */
501 if (IS_ITEMP (op1) &&
504 (sym1->usl.spillLoc == sym2))
507 if (IS_ITEMP (op2) &&
511 (sym2->usl.spillLoc == sym1))
517 /*-----------------------------------------------------------------*/
518 /* sameRegs - two asmops have the same registers */
519 /*-----------------------------------------------------------------*/
521 sameRegs (asmop * aop1, asmop * aop2)
528 if (aop1->type != AOP_REG ||
529 aop2->type != AOP_REG)
532 if (aop1->size != aop2->size)
535 for (i = 0; i < aop1->size; i++)
536 if (aop1->aopu.aop_reg[i] !=
537 aop2->aopu.aop_reg[i])
543 /*-----------------------------------------------------------------*/
544 /* aopOp - allocates an asmop for an operand : */
545 /*-----------------------------------------------------------------*/
547 aopOp (operand * op, iCode * ic, bool result)
556 /* if this a literal */
557 if (IS_OP_LITERAL (op))
559 op->aop = aop = newAsmop (AOP_LIT);
560 aop->aopu.aop_lit = op->operand.valOperand;
561 aop->size = getSize (operandType (op));
565 /* if already has a asmop then continue */
569 /* if the underlying symbol has a aop */
570 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
572 op->aop = OP_SYMBOL (op)->aop;
576 /* if this is a true symbol */
577 if (IS_TRUE_SYMOP (op))
579 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
583 /* this is a temporary : this has
589 e) can be a return use only */
591 sym = OP_SYMBOL (op);
593 /* if the type is a conditional */
594 if (sym->regType == REG_CND)
596 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
601 /* if it is spilt then two situations
603 b) has a spill location */
604 if (sym->isspilt || sym->nRegs == 0)
607 /* rematerialize it NOW */
610 sym->aop = op->aop = aop =
612 aop->size = getSize (sym->type);
619 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
620 aop->size = getSize (sym->type);
621 for (i = 0; i < 2; i++)
622 aop->aopu.aop_str[i] = accUse[i];
630 aop = op->aop = sym->aop = newAsmop (AOP_STR);
631 aop->size = getSize (sym->type);
632 for (i = 0; i < fReturnSizeMCS51; i++)
633 aop->aopu.aop_str[i] = fReturn[i];
637 /* else spill location */
638 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
639 /* force a new aop if sizes differ */
640 sym->usl.spillLoc->aop = NULL;
642 sym->aop = op->aop = aop =
643 aopForSym (ic, sym->usl.spillLoc, result);
644 aop->size = getSize (sym->type);
648 /* must be in a register */
649 sym->aop = op->aop = aop = newAsmop (AOP_REG);
650 aop->size = sym->nRegs;
651 for (i = 0; i < sym->nRegs; i++)
652 aop->aopu.aop_reg[i] = sym->regs[i];
655 /*-----------------------------------------------------------------*/
656 /* freeAsmop - free up the asmop given to an operand */
657 /*----------------------------------------------------------------*/
659 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
676 /* depending on the asmop type only three cases need work AOP_RO
677 , AOP_R1 && AOP_STK */
685 emitcode ("pop", "ar0");
689 bitVectUnSetBit (ic->rUsed, R0_IDX);
697 emitcode ("pop", "ar1");
701 bitVectUnSetBit (ic->rUsed, R1_IDX);
707 int stk = aop->aopu.aop_stk + aop->size;
708 bitVectUnSetBit (ic->rUsed, R0_IDX);
709 bitVectUnSetBit (ic->rUsed, R1_IDX);
711 getFreePtr (ic, &aop, FALSE);
715 emitcode ("mov", "a,_bp");
716 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
717 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
721 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
726 emitcode ("pop", "acc");
727 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
730 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
733 freeAsmop (op, NULL, ic, TRUE);
736 emitcode ("pop", "ar0");
742 emitcode ("pop", "ar1");
749 /* all other cases just dealloc */
755 OP_SYMBOL (op)->aop = NULL;
756 /* if the symbol has a spill */
758 SPIL_LOC (op)->aop = NULL;
763 /*-----------------------------------------------------------------*/
764 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
765 /* clobber the accumulator */
766 /*-----------------------------------------------------------------*/
768 aopGetUsesAcc (asmop *aop, int offset)
770 if (offset > (aop->size - 1))
788 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
797 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
801 /* Error case --- will have been caught already */
808 /*-----------------------------------------------------------------*/
809 /* aopGet - for fetching value of the aop */
810 /*-----------------------------------------------------------------*/
812 aopGet (asmop * aop, int offset, bool bit16, bool dname)
817 /* offset is greater than
819 if (offset > (aop->size - 1) &&
820 aop->type != AOP_LIT)
823 /* depending on type */
829 /* if we need to increment it */
830 while (offset > aop->coff)
832 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
836 while (offset < aop->coff)
838 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
845 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
846 return (dname ? "acc" : "a");
848 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
849 rs = Safe_calloc (1, strlen (s) + 1);
854 if (aop->code && aop->coff==0 && offset>=1) {
855 emitcode ("mov", "a,#0x%02x", offset);
856 emitcode ("movc", "a,@a+dptr");
857 return (dname ? "acc" : "a");
860 while (offset > aop->coff)
862 emitcode ("inc", "dptr");
866 while (offset < aop->coff)
868 emitcode ("lcall", "__decdptr");
875 emitcode ("clr", "a");
876 emitcode ("movc", "a,@a+dptr");
880 emitcode ("movx", "a,@dptr");
882 return (dname ? "acc" : "a");
886 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
887 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
889 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
891 sprintf (s, "#(%s >> %d)",
892 aop->aopu.aop_immd.aop_immd1,
896 aop->aopu.aop_immd.aop_immd1);
897 rs = Safe_calloc (1, strlen (s) + 1);
903 sprintf (s, "(%s + %d)",
907 sprintf (s, "%s", aop->aopu.aop_dir);
908 rs = Safe_calloc (1, strlen (s) + 1);
914 return aop->aopu.aop_reg[offset]->dname;
916 return aop->aopu.aop_reg[offset]->name;
919 emitcode ("clr", "a");
920 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
921 emitcode ("rlc", "a");
922 return (dname ? "acc" : "a");
925 if (!offset && dname)
927 return aop->aopu.aop_str[offset];
930 return aopLiteral (aop->aopu.aop_lit, offset);
934 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
938 return aop->aopu.aop_str[offset];
942 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
943 "aopget got unsupported aop->type");
946 /*-----------------------------------------------------------------*/
947 /* aopPut - puts a string for a aop */
948 /*-----------------------------------------------------------------*/
950 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
954 if (aop->size && offset > (aop->size - 1))
956 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
957 "aopPut got offset > aop->size");
961 /* will assign value to value */
962 /* depending on where it is ofcourse */
967 sprintf (d, "(%s + %d)",
968 aop->aopu.aop_dir, offset);
970 sprintf (d, "%s", aop->aopu.aop_dir);
974 emitcode ("mov", "%s,%s", d, s);
979 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
980 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
983 strcmp (s, "r0") == 0 ||
984 strcmp (s, "r1") == 0 ||
985 strcmp (s, "r2") == 0 ||
986 strcmp (s, "r3") == 0 ||
987 strcmp (s, "r4") == 0 ||
988 strcmp (s, "r5") == 0 ||
989 strcmp (s, "r6") == 0 ||
990 strcmp (s, "r7") == 0)
991 emitcode ("mov", "%s,%s",
992 aop->aopu.aop_reg[offset]->dname, s);
994 emitcode ("mov", "%s,%s",
995 aop->aopu.aop_reg[offset]->name, s);
1002 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1003 "aopPut writing to code space");
1007 while (offset > aop->coff)
1010 emitcode ("inc", "dptr");
1013 while (offset < aop->coff)
1016 emitcode ("lcall", "__decdptr");
1021 /* if not in accumulater */
1024 emitcode ("movx", "@dptr,a");
1029 while (offset > aop->coff)
1032 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1034 while (offset < aop->coff)
1037 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1044 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1050 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1052 else if (strcmp (s, "r0") == 0 ||
1053 strcmp (s, "r1") == 0 ||
1054 strcmp (s, "r2") == 0 ||
1055 strcmp (s, "r3") == 0 ||
1056 strcmp (s, "r4") == 0 ||
1057 strcmp (s, "r5") == 0 ||
1058 strcmp (s, "r6") == 0 ||
1059 strcmp (s, "r7") == 0)
1062 sprintf (buffer, "a%s", s);
1063 emitcode ("mov", "@%s,%s",
1064 aop->aopu.aop_ptr->name, buffer);
1067 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1072 if (strcmp (s, "a") == 0)
1073 emitcode ("push", "acc");
1077 emitcode ("push", "acc");
1079 emitcode ("push", s);
1085 /* if bit variable */
1086 if (!aop->aopu.aop_dir)
1088 emitcode ("clr", "a");
1089 emitcode ("rlc", "a");
1094 emitcode ("clr", "%s", aop->aopu.aop_dir);
1096 emitcode ("setb", "%s", aop->aopu.aop_dir);
1097 else if (!strcmp (s, "c"))
1098 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1101 if (strcmp (s, "a"))
1106 /* set C, if a >= 1 */
1107 emitcode ("add", "a,#0xff");
1108 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1116 if (strcmp (aop->aopu.aop_str[offset], s) ||
1118 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1123 if (!offset && (strcmp (s, "acc") == 0) &&
1127 if (strcmp (aop->aopu.aop_str[offset], s) &&
1129 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1133 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1134 "aopPut got unsupported aop->type");
1142 /*-----------------------------------------------------------------*/
1143 /* pointToEnd :- points to the last byte of the operand */
1144 /*-----------------------------------------------------------------*/
1146 pointToEnd (asmop * aop)
1152 aop->coff = count = (aop->size - 1);
1158 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1162 emitcode ("inc", "dptr");
1169 /*-----------------------------------------------------------------*/
1170 /* reAdjustPreg - points a register back to where it should */
1171 /*-----------------------------------------------------------------*/
1173 reAdjustPreg (asmop * aop)
1175 if ((aop->coff==0) || aop->size <= 1)
1183 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1188 emitcode ("lcall", "__decdptr");
1195 #define AOP(op) op->aop
1196 #define AOP_TYPE(op) AOP(op)->type
1197 #define AOP_SIZE(op) AOP(op)->size
1198 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1199 AOP_TYPE(x) == AOP_R0))
1201 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1202 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1204 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1205 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1206 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1208 /*-----------------------------------------------------------------*/
1209 /* genNotFloat - generates not for float operations */
1210 /*-----------------------------------------------------------------*/
1212 genNotFloat (operand * op, operand * res)
1218 D(emitcode ("; genNotFloat",""));
1220 /* we will put 127 in the first byte of
1222 aopPut (AOP (res), "#127", 0, isOperandVolatile (op, FALSE));
1223 size = AOP_SIZE (op) - 1;
1226 l = aopGet (op->aop, offset++, FALSE, FALSE);
1231 emitcode ("orl", "a,%s",
1233 offset++, FALSE, FALSE));
1236 tlbl = newiTempLabel (NULL);
1237 aopPut (res->aop, one, 1, isOperandVolatile (op, FALSE));
1238 emitcode ("jz", "%05d$", (tlbl->key + 100));
1239 aopPut (res->aop, zero, 1, isOperandVolatile (op, FALSE));
1240 emitcode ("", "%05d$:", (tlbl->key + 100));
1242 size = res->aop->size - 2;
1244 /* put zeros in the rest */
1246 aopPut (res->aop, zero, offset++, isOperandVolatile (op, FALSE));
1249 /*-----------------------------------------------------------------*/
1250 /* opIsGptr: returns non-zero if the passed operand is */
1251 /* a generic pointer type. */
1252 /*-----------------------------------------------------------------*/
1254 opIsGptr (operand * op)
1256 sym_link *type = operandType (op);
1258 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1265 /*-----------------------------------------------------------------*/
1266 /* getDataSize - get the operand data size */
1267 /*-----------------------------------------------------------------*/
1269 getDataSize (operand * op)
1272 size = AOP_SIZE (op);
1273 if (size == GPTRSIZE)
1275 sym_link *type = operandType (op);
1276 if (IS_GENPTR (type))
1278 /* generic pointer; arithmetic operations
1279 * should ignore the high byte (pointer type).
1287 /*-----------------------------------------------------------------*/
1288 /* outAcc - output Acc */
1289 /*-----------------------------------------------------------------*/
1291 outAcc (operand * result)
1294 size = getDataSize (result);
1297 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1300 /* unsigned or positive */
1303 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1308 /*-----------------------------------------------------------------*/
1309 /* outBitC - output a bit C */
1310 /*-----------------------------------------------------------------*/
1312 outBitC (operand * result)
1314 /* if the result is bit */
1315 if (AOP_TYPE (result) == AOP_CRY)
1316 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1319 emitcode ("clr", "a");
1320 emitcode ("rlc", "a");
1325 /*-----------------------------------------------------------------*/
1326 /* toBoolean - emit code for orl a,operator(sizeop) */
1327 /*-----------------------------------------------------------------*/
1329 toBoolean (operand * oper)
1331 int size = AOP_SIZE (oper) - 1;
1333 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1335 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1339 /*-----------------------------------------------------------------*/
1340 /* genNot - generate code for ! operation */
1341 /*-----------------------------------------------------------------*/
1346 sym_link *optype = operandType (IC_LEFT (ic));
1348 D(emitcode ("; genNot",""));
1350 /* assign asmOps to operand & result */
1351 aopOp (IC_LEFT (ic), ic, FALSE);
1352 aopOp (IC_RESULT (ic), ic, TRUE);
1354 /* if in bit space then a special case */
1355 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1357 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1358 emitcode ("cpl", "c");
1359 outBitC (IC_RESULT (ic));
1363 /* if type float then do float */
1364 if (IS_FLOAT (optype))
1366 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1370 toBoolean (IC_LEFT (ic));
1372 tlbl = newiTempLabel (NULL);
1373 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1374 emitcode ("", "%05d$:", tlbl->key + 100);
1375 outBitC (IC_RESULT (ic));
1378 /* release the aops */
1379 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1380 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1384 /*-----------------------------------------------------------------*/
1385 /* genCpl - generate code for complement */
1386 /*-----------------------------------------------------------------*/
1394 D(emitcode ("; genCpl",""));
1396 /* assign asmOps to operand & result */
1397 aopOp (IC_LEFT (ic), ic, FALSE);
1398 aopOp (IC_RESULT (ic), ic, TRUE);
1400 /* special case if in bit space */
1401 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1402 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1403 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1404 emitcode ("cpl", "c");
1405 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1408 tlbl=newiTempLabel(NULL);
1409 emitcode ("cjne", "%s,#0x01,%05d$",
1410 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1411 emitcode ("", "%05d$:", tlbl->key+100);
1412 outBitC (IC_RESULT(ic));
1416 size = AOP_SIZE (IC_RESULT (ic));
1419 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1421 emitcode ("cpl", "a");
1422 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1427 /* release the aops */
1428 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1429 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1432 /*-----------------------------------------------------------------*/
1433 /* genUminusFloat - unary minus for floating points */
1434 /*-----------------------------------------------------------------*/
1436 genUminusFloat (operand * op, operand * result)
1438 int size, offset = 0;
1441 D(emitcode ("; genUminusFloat",""));
1443 /* for this we just copy and then flip the bit */
1445 size = AOP_SIZE (op) - 1;
1449 aopPut (AOP (result),
1450 aopGet (AOP (op), offset, FALSE, FALSE),
1452 isOperandVolatile (result, FALSE));
1456 l = aopGet (AOP (op), offset, FALSE, FALSE);
1460 emitcode ("cpl", "acc.7");
1461 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1464 /*-----------------------------------------------------------------*/
1465 /* genUminus - unary minus code generation */
1466 /*-----------------------------------------------------------------*/
1468 genUminus (iCode * ic)
1471 sym_link *optype, *rtype;
1474 D(emitcode ("; genUminus",""));
1477 aopOp (IC_LEFT (ic), ic, FALSE);
1478 aopOp (IC_RESULT (ic), ic, TRUE);
1480 /* if both in bit space then special
1482 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1483 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1486 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1487 emitcode ("cpl", "c");
1488 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1492 optype = operandType (IC_LEFT (ic));
1493 rtype = operandType (IC_RESULT (ic));
1495 /* if float then do float stuff */
1496 if (IS_FLOAT (optype))
1498 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1502 /* otherwise subtract from zero */
1503 size = AOP_SIZE (IC_LEFT (ic));
1508 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1509 if (!strcmp (l, "a"))
1513 emitcode ("cpl", "a");
1514 emitcode ("addc", "a,#0");
1520 emitcode ("clr", "a");
1521 emitcode ("subb", "a,%s", l);
1523 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1526 /* if any remaining bytes in the result */
1527 /* we just need to propagate the sign */
1528 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1530 emitcode ("rlc", "a");
1531 emitcode ("subb", "a,acc");
1533 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1537 /* release the aops */
1538 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1539 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1542 /*-----------------------------------------------------------------*/
1543 /* saveRegisters - will look for a call and save the registers */
1544 /*-----------------------------------------------------------------*/
1546 saveRegisters (iCode * lic)
1553 for (ic = lic; ic; ic = ic->next)
1554 if (ic->op == CALL || ic->op == PCALL)
1559 fprintf (stderr, "found parameter push with no function call\n");
1563 /* if the registers have been saved already or don't need to be then
1567 if (IS_SYMOP(IC_LEFT(ic)) &&
1568 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1569 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1572 /* safe the registers in use at this time but skip the
1573 ones for the result */
1574 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1575 mcs51_rUmaskForOp (IC_RESULT(ic)));
1578 if (options.useXstack)
1580 if (bitVectBitValue (rsave, R0_IDX))
1581 emitcode ("mov", "b,r0");
1582 emitcode ("mov", "r0,%s", spname);
1583 for (i = 0; i < mcs51_nRegs; i++)
1585 if (bitVectBitValue (rsave, i))
1588 emitcode ("mov", "a,b");
1590 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1591 emitcode ("movx", "@r0,a");
1592 emitcode ("inc", "r0");
1595 emitcode ("mov", "%s,r0", spname);
1596 if (bitVectBitValue (rsave, R0_IDX))
1597 emitcode ("mov", "r0,b");
1600 for (i = 0; i < mcs51_nRegs; i++)
1602 if (bitVectBitValue (rsave, i))
1603 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1607 /*-----------------------------------------------------------------*/
1608 /* unsaveRegisters - pop the pushed registers */
1609 /*-----------------------------------------------------------------*/
1611 unsaveRegisters (iCode * ic)
1616 /* restore the registers in use at this time but skip the
1617 ones for the result */
1618 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1619 mcs51_rUmaskForOp (IC_RESULT(ic)));
1621 if (options.useXstack)
1623 emitcode ("mov", "r0,%s", spname);
1624 for (i = mcs51_nRegs; i >= 0; i--)
1626 if (bitVectBitValue (rsave, i))
1628 emitcode ("dec", "r0");
1629 emitcode ("movx", "a,@r0");
1631 emitcode ("mov", "b,a");
1633 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1637 emitcode ("mov", "%s,r0", spname);
1638 if (bitVectBitValue (rsave, R0_IDX))
1639 emitcode ("mov", "r0,b");
1642 for (i = mcs51_nRegs; i >= 0; i--)
1644 if (bitVectBitValue (rsave, i))
1645 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1651 /*-----------------------------------------------------------------*/
1653 /*-----------------------------------------------------------------*/
1655 pushSide (operand * oper, int size)
1660 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1661 if (AOP_TYPE (oper) != AOP_REG &&
1662 AOP_TYPE (oper) != AOP_DIR &&
1665 emitcode ("mov", "a,%s", l);
1666 emitcode ("push", "acc");
1669 emitcode ("push", "%s", l);
1673 /*-----------------------------------------------------------------*/
1674 /* assignResultValue - */
1675 /*-----------------------------------------------------------------*/
1677 assignResultValue (operand * oper)
1680 int size = AOP_SIZE (oper);
1683 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1689 /*-----------------------------------------------------------------*/
1690 /* genXpush - pushes onto the external stack */
1691 /*-----------------------------------------------------------------*/
1693 genXpush (iCode * ic)
1695 asmop *aop = newAsmop (0);
1697 int size, offset = 0;
1699 D(emitcode ("; genXpush",""));
1701 aopOp (IC_LEFT (ic), ic, FALSE);
1702 r = getFreePtr (ic, &aop, FALSE);
1705 emitcode ("mov", "%s,_spx", r->name);
1707 size = AOP_SIZE (IC_LEFT (ic));
1711 char *l = aopGet (AOP (IC_LEFT (ic)),
1712 offset++, FALSE, FALSE);
1714 emitcode ("movx", "@%s,a", r->name);
1715 emitcode ("inc", "%s", r->name);
1720 emitcode ("mov", "_spx,%s", r->name);
1722 freeAsmop (NULL, aop, ic, TRUE);
1723 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1726 /*-----------------------------------------------------------------*/
1727 /* genIpush - genrate code for pushing this gets a little complex */
1728 /*-----------------------------------------------------------------*/
1730 genIpush (iCode * ic)
1732 int size, offset = 0;
1735 D(emitcode ("; genIpush",""));
1737 /* if this is not a parm push : ie. it is spill push
1738 and spill push is always done on the local stack */
1742 /* and the item is spilt then do nothing */
1743 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1746 aopOp (IC_LEFT (ic), ic, FALSE);
1747 size = AOP_SIZE (IC_LEFT (ic));
1748 /* push it on the stack */
1751 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1757 emitcode ("push", "%s", l);
1762 /* this is a paramter push: in this case we call
1763 the routine to find the call and save those
1764 registers that need to be saved */
1767 /* if use external stack then call the external
1768 stack pushing routine */
1769 if (options.useXstack)
1775 /* then do the push */
1776 aopOp (IC_LEFT (ic), ic, FALSE);
1779 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1780 size = AOP_SIZE (IC_LEFT (ic));
1784 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1785 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1786 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1789 emitcode ("mov", "a,%s", l);
1790 emitcode ("push", "acc");
1793 emitcode ("push", "%s", l);
1796 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1799 /*-----------------------------------------------------------------*/
1800 /* genIpop - recover the registers: can happen only for spilling */
1801 /*-----------------------------------------------------------------*/
1803 genIpop (iCode * ic)
1807 D(emitcode ("; genIpop",""));
1809 /* if the temp was not pushed then */
1810 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1813 aopOp (IC_LEFT (ic), ic, FALSE);
1814 size = AOP_SIZE (IC_LEFT (ic));
1815 offset = (size - 1);
1817 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1820 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1823 /*-----------------------------------------------------------------*/
1824 /* unsaveRBank - restores the resgister bank from stack */
1825 /*-----------------------------------------------------------------*/
1827 unsaveRBank (int bank, iCode * ic, bool popPsw)
1833 if (options.useXstack)
1837 /* Assume r0 is available for use. */
1838 r = mcs51_regWithIdx (R0_IDX);;
1843 r = getFreePtr (ic, &aop, FALSE);
1845 emitcode ("mov", "%s,_spx", r->name);
1850 if (options.useXstack)
1852 emitcode ("movx", "a,@%s", r->name);
1853 emitcode ("mov", "psw,a");
1854 emitcode ("dec", "%s", r->name);
1858 emitcode ("pop", "psw");
1862 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1864 if (options.useXstack)
1866 emitcode ("movx", "a,@%s", r->name);
1867 emitcode ("mov", "(%s+%d),a",
1868 regs8051[i].base, 8 * bank + regs8051[i].offset);
1869 emitcode ("dec", "%s", r->name);
1873 emitcode ("pop", "(%s+%d)",
1874 regs8051[i].base, 8 * bank + regs8051[i].offset);
1877 if (options.useXstack)
1879 emitcode ("mov", "_spx,%s", r->name);
1884 freeAsmop (NULL, aop, ic, TRUE);
1888 /*-----------------------------------------------------------------*/
1889 /* saveRBank - saves an entire register bank on the stack */
1890 /*-----------------------------------------------------------------*/
1892 saveRBank (int bank, iCode * ic, bool pushPsw)
1898 if (options.useXstack)
1902 /* Assume r0 is available for use. */
1903 r = mcs51_regWithIdx (R0_IDX);;
1908 r = getFreePtr (ic, &aop, FALSE);
1910 emitcode ("mov", "%s,_spx", r->name);
1913 for (i = 0; i < mcs51_nRegs; i++)
1915 if (options.useXstack)
1917 emitcode ("inc", "%s", r->name);
1918 emitcode ("mov", "a,(%s+%d)",
1919 regs8051[i].base, 8 * bank + regs8051[i].offset);
1920 emitcode ("movx", "@%s,a", r->name);
1923 emitcode ("push", "(%s+%d)",
1924 regs8051[i].base, 8 * bank + regs8051[i].offset);
1929 if (options.useXstack)
1931 emitcode ("mov", "a,psw");
1932 emitcode ("movx", "@%s,a", r->name);
1933 emitcode ("inc", "%s", r->name);
1934 emitcode ("mov", "_spx,%s", r->name);
1939 emitcode ("push", "psw");
1942 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1947 freeAsmop (NULL, aop, ic, TRUE);
1956 /*-----------------------------------------------------------------*/
1957 /* genSend - gen code for SEND */
1958 /*-----------------------------------------------------------------*/
1959 static void genSend(set *sendSet)
1964 for (sic = setFirstItem (_G.sendSet); sic;
1965 sic = setNextItem (_G.sendSet)) {
1966 int size, offset = 0;
1967 aopOp (IC_LEFT (sic), sic, FALSE);
1968 size = AOP_SIZE (IC_LEFT (sic));
1970 if (sic->argreg == 1) {
1972 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1974 if (strcmp (l, fReturn[offset]))
1975 emitcode ("mov", "%s,%s", fReturn[offset], l);
1981 emitcode ("mov","b1_%d,%s",rb1_count++,
1982 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
1985 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1989 /*-----------------------------------------------------------------*/
1990 /* genCall - generates a call statement */
1991 /*-----------------------------------------------------------------*/
1993 genCall (iCode * ic)
1996 // bool restoreBank = FALSE;
1997 bool swapBanks = FALSE;
1999 D(emitcode("; genCall",""));
2001 dtype = operandType (IC_LEFT (ic));
2002 /* if send set is not empty the assign */
2005 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2006 genSend(reverseSet(_G.sendSet));
2008 genSend(_G.sendSet);
2014 /* if we are calling a not _naked function that is not using
2015 the same register bank then we need to save the
2016 destination registers on the stack */
2017 dtype = operandType (IC_LEFT (ic));
2018 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2019 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2020 !IFFUNC_ISISR (dtype))
2025 /* if caller saves & we have not saved then */
2031 emitcode ("mov", "psw,#0x%02x",
2032 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2036 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2037 OP_SYMBOL (IC_LEFT (ic))->rname :
2038 OP_SYMBOL (IC_LEFT (ic))->name));
2042 emitcode ("mov", "psw,#0x%02x",
2043 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2046 /* if we need assign a result value */
2047 if ((IS_ITEMP (IC_RESULT (ic)) &&
2048 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2049 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2050 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2051 IS_TRUE_SYMOP (IC_RESULT (ic)))
2055 aopOp (IC_RESULT (ic), ic, FALSE);
2058 assignResultValue (IC_RESULT (ic));
2060 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2063 /* adjust the stack for parameters if
2068 if (ic->parmBytes > 3)
2070 emitcode ("mov", "a,%s", spname);
2071 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2072 emitcode ("mov", "%s,a", spname);
2075 for (i = 0; i < ic->parmBytes; i++)
2076 emitcode ("dec", "%s", spname);
2079 /* if we hade saved some registers then unsave them */
2080 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2081 unsaveRegisters (ic);
2083 // /* if register bank was saved then pop them */
2085 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2088 /*-----------------------------------------------------------------*/
2089 /* -10l - generates a call by pointer statement */
2090 /*-----------------------------------------------------------------*/
2092 genPcall (iCode * ic)
2095 symbol *rlbl = newiTempLabel (NULL);
2096 // bool restoreBank=FALSE;
2097 bool swapBanks = FALSE;
2099 D(emitcode("; genPCall",""));
2101 /* if caller saves & we have not saved then */
2105 /* if we are calling a not _naked function that is not using
2106 the same register bank then we need to save the
2107 destination registers on the stack */
2108 dtype = operandType (IC_LEFT (ic))->next;
2109 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2110 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2111 !IFFUNC_ISISR (dtype))
2113 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2114 // restoreBank=TRUE;
2116 // need caution message to user here
2119 /* push the return address on to the stack */
2120 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2121 emitcode ("push", "acc");
2122 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2123 emitcode ("push", "acc");
2125 /* now push the calling address */
2126 aopOp (IC_LEFT (ic), ic, FALSE);
2128 pushSide (IC_LEFT (ic), FPTRSIZE);
2130 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2132 /* if send set is not empty the assign */
2135 genSend(reverseSet(_G.sendSet));
2141 emitcode ("mov", "psw,#0x%02x",
2142 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2146 emitcode ("ret", "");
2147 emitcode ("", "%05d$:", (rlbl->key + 100));
2152 emitcode ("mov", "psw,#0x%02x",
2153 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2156 /* if we need assign a result value */
2157 if ((IS_ITEMP (IC_RESULT (ic)) &&
2158 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2159 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2160 IS_TRUE_SYMOP (IC_RESULT (ic)))
2164 aopOp (IC_RESULT (ic), ic, FALSE);
2167 assignResultValue (IC_RESULT (ic));
2169 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2172 /* adjust the stack for parameters if
2177 if (ic->parmBytes > 3)
2179 emitcode ("mov", "a,%s", spname);
2180 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2181 emitcode ("mov", "%s,a", spname);
2184 for (i = 0; i < ic->parmBytes; i++)
2185 emitcode ("dec", "%s", spname);
2189 // /* if register bank was saved then unsave them */
2191 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2193 /* if we hade saved some registers then
2195 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2196 unsaveRegisters (ic);
2199 /*-----------------------------------------------------------------*/
2200 /* resultRemat - result is rematerializable */
2201 /*-----------------------------------------------------------------*/
2203 resultRemat (iCode * ic)
2205 if (SKIP_IC (ic) || ic->op == IFX)
2208 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2210 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2211 if (sym->remat && !POINTER_SET (ic))
2218 #if defined(__BORLANDC__) || defined(_MSC_VER)
2219 #define STRCASECMP stricmp
2221 #define STRCASECMP strcasecmp
2224 /*-----------------------------------------------------------------*/
2225 /* inExcludeList - return 1 if the string is in exclude Reg list */
2226 /*-----------------------------------------------------------------*/
2228 regsCmp(void *p1, void *p2)
2230 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2234 inExcludeList (char *s)
2236 const char *p = setFirstItem(options.excludeRegsSet);
2238 if (p == NULL || STRCASECMP(p, "none") == 0)
2242 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2245 /*-----------------------------------------------------------------*/
2246 /* genFunction - generated code for function entry */
2247 /*-----------------------------------------------------------------*/
2249 genFunction (iCode * ic)
2253 bool switchedPSW = FALSE;
2254 int calleesaves_saved_register = -1;
2257 /* create the function header */
2258 emitcode (";", "-----------------------------------------");
2259 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2260 emitcode (";", "-----------------------------------------");
2262 emitcode ("", "%s:", sym->rname);
2263 ftype = operandType (IC_LEFT (ic));
2265 if (IFFUNC_ISNAKED(ftype))
2267 emitcode(";", "naked function: no prologue.");
2271 /* if critical function then turn interrupts off */
2272 if (IFFUNC_ISCRITICAL (ftype))
2273 emitcode ("clr", "ea");
2275 /* here we need to generate the equates for the
2276 register bank if required */
2277 if (FUNC_REGBANK (ftype) != rbank)
2281 rbank = FUNC_REGBANK (ftype);
2282 for (i = 0; i < mcs51_nRegs; i++)
2284 if (strcmp (regs8051[i].base, "0") == 0)
2285 emitcode ("", "%s = 0x%02x",
2287 8 * rbank + regs8051[i].offset);
2289 emitcode ("", "%s = %s + 0x%02x",
2292 8 * rbank + regs8051[i].offset);
2296 /* if this is an interrupt service routine then
2297 save acc, b, dpl, dph */
2298 if (IFFUNC_ISISR (sym->type))
2301 if (!inExcludeList ("acc"))
2302 emitcode ("push", "acc");
2303 if (!inExcludeList ("b"))
2304 emitcode ("push", "b");
2305 if (!inExcludeList ("dpl"))
2306 emitcode ("push", "dpl");
2307 if (!inExcludeList ("dph"))
2308 emitcode ("push", "dph");
2309 /* if this isr has no bank i.e. is going to
2310 run with bank 0 , then we need to save more
2312 if (!FUNC_REGBANK (sym->type))
2315 /* if this function does not call any other
2316 function then we can be economical and
2317 save only those registers that are used */
2318 if (!IFFUNC_HASFCALL(sym->type))
2322 /* if any registers used */
2325 /* save the registers used */
2326 for (i = 0; i < sym->regsUsed->size; i++)
2328 if (bitVectBitValue (sym->regsUsed, i) ||
2329 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2330 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2338 /* this function has a function call cannot
2339 determines register usage so we will have to push the
2341 saveRBank (0, ic, FALSE);
2342 if (options.parms_in_bank1) {
2344 for (i=0; i < 8 ; i++ ) {
2345 emitcode ("push","%s",rb1regs[i]);
2352 /* This ISR uses a non-zero bank.
2354 * We assume that the bank is available for our
2357 * However, if this ISR calls a function which uses some
2358 * other bank, we must save that bank entirely.
2360 unsigned long banksToSave = 0;
2362 if (IFFUNC_HASFCALL(sym->type))
2365 #define MAX_REGISTER_BANKS 4
2370 for (i = ic; i; i = i->next)
2372 if (i->op == ENDFUNCTION)
2374 /* we got to the end OK. */
2382 dtype = operandType (IC_LEFT(i));
2384 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2386 /* Mark this bank for saving. */
2387 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2389 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2393 banksToSave |= (1 << FUNC_REGBANK(dtype));
2396 /* And note that we don't need to do it in
2404 /* This is a mess; we have no idea what
2405 * register bank the called function might
2408 * The only thing I can think of to do is
2409 * throw a warning and hope.
2411 werror(W_FUNCPTR_IN_USING_ISR);
2415 if (banksToSave && options.useXstack)
2417 /* Since we aren't passing it an ic,
2418 * saveRBank will assume r0 is available to abuse.
2420 * So switch to our (trashable) bank now, so
2421 * the caller's R0 isn't trashed.
2423 emitcode ("push", "psw");
2424 emitcode ("mov", "psw,#0x%02x",
2425 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2429 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2431 if (banksToSave & (1 << ix))
2433 saveRBank(ix, NULL, FALSE);
2437 // TODO: this needs a closer look
2438 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2443 /* if callee-save to be used for this function
2444 then save the registers being used in this function */
2445 if (IFFUNC_CALLEESAVES(sym->type))
2449 /* if any registers used */
2452 /* save the registers used */
2453 for (i = 0; i < sym->regsUsed->size; i++)
2455 if (bitVectBitValue (sym->regsUsed, i) ||
2456 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2458 /* remember one saved register for later usage */
2459 if (calleesaves_saved_register < 0)
2460 calleesaves_saved_register = i;
2461 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2469 /* set the register bank to the desired value */
2470 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2473 emitcode ("push", "psw");
2474 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2477 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2480 if (options.useXstack)
2482 emitcode ("mov", "r0,%s", spname);
2483 emitcode ("mov", "a,_bp");
2484 emitcode ("movx", "@r0,a");
2485 emitcode ("inc", "%s", spname);
2489 /* set up the stack */
2490 emitcode ("push", "_bp"); /* save the callers stack */
2492 emitcode ("mov", "_bp,%s", spname);
2495 /* adjust the stack for the function */
2501 werror (W_STACK_OVERFLOW, sym->name);
2503 if (i > 3 && sym->recvSize < 4)
2506 emitcode ("mov", "a,sp");
2507 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2508 emitcode ("mov", "sp,a");
2513 if (IFFUNC_CALLEESAVES(sym->type))
2515 /* if it's a callee-saves function we need a saved register */
2516 if (calleesaves_saved_register >= 0)
2518 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2519 emitcode ("mov", "a,sp");
2520 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2521 emitcode ("mov", "sp,a");
2522 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2525 /* do it the hard way */
2527 emitcode ("inc", "sp");
2531 /* not callee-saves, we can clobber r0 */
2532 emitcode ("mov", "r0,a");
2533 emitcode ("mov", "a,sp");
2534 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2535 emitcode ("mov", "sp,a");
2536 emitcode ("mov", "a,r0");
2541 emitcode ("inc", "sp");
2547 emitcode ("mov", "a,_spx");
2548 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2549 emitcode ("mov", "_spx,a");
2554 /*-----------------------------------------------------------------*/
2555 /* genEndFunction - generates epilogue for functions */
2556 /*-----------------------------------------------------------------*/
2558 genEndFunction (iCode * ic)
2560 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2562 if (IFFUNC_ISNAKED(sym->type))
2564 emitcode(";", "naked function: no epilogue.");
2568 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2570 emitcode ("mov", "%s,_bp", spname);
2573 /* if use external stack but some variables were
2574 added to the local stack then decrement the
2576 if (options.useXstack && sym->stack)
2578 emitcode ("mov", "a,sp");
2579 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2580 emitcode ("mov", "sp,a");
2584 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2586 if (options.useXstack)
2588 emitcode ("mov", "r0,%s", spname);
2589 emitcode ("movx", "a,@r0");
2590 emitcode ("mov", "_bp,a");
2591 emitcode ("dec", "%s", spname);
2595 emitcode ("pop", "_bp");
2599 /* restore the register bank */
2600 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2602 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2603 || !options.useXstack)
2605 /* Special case of ISR using non-zero bank with useXstack
2608 emitcode ("pop", "psw");
2612 if (IFFUNC_ISISR (sym->type))
2615 /* now we need to restore the registers */
2616 /* if this isr has no bank i.e. is going to
2617 run with bank 0 , then we need to save more
2619 if (!FUNC_REGBANK (sym->type))
2621 /* if this function does not call any other
2622 function then we can be economical and
2623 save only those registers that are used */
2624 if (!IFFUNC_HASFCALL(sym->type))
2628 /* if any registers used */
2631 /* save the registers used */
2632 for (i = sym->regsUsed->size; i >= 0; i--)
2634 if (bitVectBitValue (sym->regsUsed, i) ||
2635 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2636 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2643 if (options.parms_in_bank1) {
2645 for (i = 7 ; i >= 0 ; i-- ) {
2646 emitcode ("pop","%s",rb1regs[i]);
2649 /* this function has a function call cannot
2650 determines register usage so we will have to pop the
2652 unsaveRBank (0, ic, FALSE);
2657 /* This ISR uses a non-zero bank.
2659 * Restore any register banks saved by genFunction
2662 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2665 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2667 if (savedBanks & (1 << ix))
2669 unsaveRBank(ix, NULL, FALSE);
2673 if (options.useXstack)
2675 /* Restore bank AFTER calling unsaveRBank,
2676 * since it can trash r0.
2678 emitcode ("pop", "psw");
2682 if (!inExcludeList ("dph"))
2683 emitcode ("pop", "dph");
2684 if (!inExcludeList ("dpl"))
2685 emitcode ("pop", "dpl");
2686 if (!inExcludeList ("b"))
2687 emitcode ("pop", "b");
2688 if (!inExcludeList ("acc"))
2689 emitcode ("pop", "acc");
2691 if (IFFUNC_ISCRITICAL (sym->type))
2692 emitcode ("setb", "ea");
2694 /* if debug then send end of function */
2695 if (options.debug && currFunc)
2698 emitcode ("", "C$%s$%d$%d$%d ==.",
2699 FileBaseName (ic->filename), currFunc->lastLine,
2700 ic->level, ic->block);
2701 if (IS_STATIC (currFunc->etype))
2702 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2704 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2708 emitcode ("reti", "");
2712 if (IFFUNC_ISCRITICAL (sym->type))
2713 emitcode ("setb", "ea");
2715 if (IFFUNC_CALLEESAVES(sym->type))
2719 /* if any registers used */
2722 /* save the registers used */
2723 for (i = sym->regsUsed->size; i >= 0; i--)
2725 if (bitVectBitValue (sym->regsUsed, i) ||
2726 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2727 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2733 /* if debug then send end of function */
2734 if (options.debug && currFunc)
2737 emitcode ("", "C$%s$%d$%d$%d ==.",
2738 FileBaseName (ic->filename), currFunc->lastLine,
2739 ic->level, ic->block);
2740 if (IS_STATIC (currFunc->etype))
2741 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2743 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2747 emitcode ("ret", "");
2752 /*-----------------------------------------------------------------*/
2753 /* genRet - generate code for return statement */
2754 /*-----------------------------------------------------------------*/
2758 int size, offset = 0, pushed = 0;
2760 D(emitcode ("; genRet",""));
2762 /* if we have no return value then
2763 just generate the "ret" */
2767 /* we have something to return then
2768 move the return value into place */
2769 aopOp (IC_LEFT (ic), ic, FALSE);
2770 size = AOP_SIZE (IC_LEFT (ic));
2775 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2778 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2780 emitcode ("push", "%s", l);
2785 l = aopGet (AOP (IC_LEFT (ic)), offset,
2787 if (strcmp (fReturn[offset], l))
2788 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2797 if (strcmp (fReturn[pushed], "a"))
2798 emitcode ("pop", fReturn[pushed]);
2800 emitcode ("pop", "acc");
2803 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2806 /* generate a jump to the return label
2807 if the next is not the return statement */
2808 if (!(ic->next && ic->next->op == LABEL &&
2809 IC_LABEL (ic->next) == returnLabel))
2811 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2815 /*-----------------------------------------------------------------*/
2816 /* genLabel - generates a label */
2817 /*-----------------------------------------------------------------*/
2819 genLabel (iCode * ic)
2821 /* special case never generate */
2822 if (IC_LABEL (ic) == entryLabel)
2825 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2828 /*-----------------------------------------------------------------*/
2829 /* genGoto - generates a ljmp */
2830 /*-----------------------------------------------------------------*/
2832 genGoto (iCode * ic)
2834 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2837 /*-----------------------------------------------------------------*/
2838 /* findLabelBackwards: walks back through the iCode chain looking */
2839 /* for the given label. Returns number of iCode instructions */
2840 /* between that label and given ic. */
2841 /* Returns zero if label not found. */
2842 /*-----------------------------------------------------------------*/
2844 findLabelBackwards (iCode * ic, int key)
2853 /* If we have any pushes or pops, we cannot predict the distance.
2854 I don't like this at all, this should be dealt with in the
2856 if (ic->op == IPUSH || ic->op == IPOP) {
2860 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2869 /*-----------------------------------------------------------------*/
2870 /* genPlusIncr :- does addition with increment if possible */
2871 /*-----------------------------------------------------------------*/
2873 genPlusIncr (iCode * ic)
2875 unsigned int icount;
2876 unsigned int size = getDataSize (IC_RESULT (ic));
2878 /* will try to generate an increment */
2879 /* if the right side is not a literal
2881 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2884 /* if the literal value of the right hand side
2885 is greater than 4 then it is not worth it */
2886 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2889 D(emitcode ("; genPlusIncr",""));
2891 /* if increment >=16 bits in register or direct space */
2892 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2893 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2901 /* If the next instruction is a goto and the goto target
2902 * is < 10 instructions previous to this, we can generate
2903 * jumps straight to that target.
2905 if (ic->next && ic->next->op == GOTO
2906 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2907 && labelRange <= 10)
2909 emitcode (";", "tail increment optimized");
2910 tlbl = IC_LABEL (ic->next);
2915 tlbl = newiTempLabel (NULL);
2918 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2919 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2920 IS_AOP_PREG (IC_RESULT (ic)))
2921 emitcode ("cjne", "%s,#0x00,%05d$",
2922 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2926 emitcode ("clr", "a");
2927 emitcode ("cjne", "a,%s,%05d$",
2928 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2932 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2935 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2936 IS_AOP_PREG (IC_RESULT (ic)))
2937 emitcode ("cjne", "%s,#0x00,%05d$",
2938 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2941 emitcode ("cjne", "a,%s,%05d$",
2942 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2945 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2949 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2950 IS_AOP_PREG (IC_RESULT (ic)))
2951 emitcode ("cjne", "%s,#0x00,%05d$",
2952 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2956 emitcode ("cjne", "a,%s,%05d$",
2957 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2960 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2965 emitcode ("", "%05d$:", tlbl->key + 100);
2970 /* if the sizes are greater than 1 then we cannot */
2971 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2972 AOP_SIZE (IC_LEFT (ic)) > 1)
2975 /* we can if the aops of the left & result match or
2976 if they are in registers and the registers are the
2978 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2983 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2984 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2985 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
2991 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3000 /*-----------------------------------------------------------------*/
3001 /* outBitAcc - output a bit in acc */
3002 /*-----------------------------------------------------------------*/
3004 outBitAcc (operand * result)
3006 symbol *tlbl = newiTempLabel (NULL);
3007 /* if the result is a bit */
3008 if (AOP_TYPE (result) == AOP_CRY)
3010 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3014 emitcode ("jz", "%05d$", tlbl->key + 100);
3015 emitcode ("mov", "a,%s", one);
3016 emitcode ("", "%05d$:", tlbl->key + 100);
3021 /*-----------------------------------------------------------------*/
3022 /* genPlusBits - generates code for addition of two bits */
3023 /*-----------------------------------------------------------------*/
3025 genPlusBits (iCode * ic)
3027 D(emitcode ("; genPlusBits",""));
3029 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3031 symbol *lbl = newiTempLabel (NULL);
3032 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3033 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3034 emitcode ("cpl", "c");
3035 emitcode ("", "%05d$:", (lbl->key + 100));
3036 outBitC (IC_RESULT (ic));
3040 emitcode ("clr", "a");
3041 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3042 emitcode ("rlc", "a");
3043 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3044 emitcode ("addc", "a,#0x00");
3045 outAcc (IC_RESULT (ic));
3050 /* This is the original version of this code.
3052 * This is being kept around for reference,
3053 * because I am not entirely sure I got it right...
3056 adjustArithmeticResult (iCode * ic)
3058 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3059 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3060 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3061 aopPut (AOP (IC_RESULT (ic)),
3062 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3064 isOperandVolatile (IC_RESULT (ic), FALSE));
3066 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3067 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3068 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3069 aopPut (AOP (IC_RESULT (ic)),
3070 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3072 isOperandVolatile (IC_RESULT (ic), FALSE));
3074 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3075 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3076 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3077 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3078 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3081 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3082 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3086 /* This is the pure and virtuous version of this code.
3087 * I'm pretty certain it's right, but not enough to toss the old
3091 adjustArithmeticResult (iCode * ic)
3093 if (opIsGptr (IC_RESULT (ic)) &&
3094 opIsGptr (IC_LEFT (ic)) &&
3095 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3097 aopPut (AOP (IC_RESULT (ic)),
3098 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3100 isOperandVolatile (IC_RESULT (ic), FALSE));
3103 if (opIsGptr (IC_RESULT (ic)) &&
3104 opIsGptr (IC_RIGHT (ic)) &&
3105 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3107 aopPut (AOP (IC_RESULT (ic)),
3108 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3110 isOperandVolatile (IC_RESULT (ic), FALSE));
3113 if (opIsGptr (IC_RESULT (ic)) &&
3114 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3115 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3116 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3117 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3120 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3121 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3126 /*-----------------------------------------------------------------*/
3127 /* genPlus - generates code for addition */
3128 /*-----------------------------------------------------------------*/
3130 genPlus (iCode * ic)
3132 int size, offset = 0;
3134 asmop *leftOp, *rightOp;
3136 /* special cases :- */
3138 D(emitcode ("; genPlus",""));
3140 aopOp (IC_LEFT (ic), ic, FALSE);
3141 aopOp (IC_RIGHT (ic), ic, FALSE);
3142 aopOp (IC_RESULT (ic), ic, TRUE);
3144 /* if literal, literal on the right or
3145 if left requires ACC or right is already
3147 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3148 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3149 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3151 operand *t = IC_RIGHT (ic);
3152 IC_RIGHT (ic) = IC_LEFT (ic);
3156 /* if both left & right are in bit
3158 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3159 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3165 /* if left in bit space & right literal */
3166 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3167 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3169 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3170 /* if result in bit space */
3171 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3173 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3174 emitcode ("cpl", "c");
3175 outBitC (IC_RESULT (ic));
3179 size = getDataSize (IC_RESULT (ic));
3182 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3183 emitcode ("addc", "a,#00");
3184 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3190 /* if I can do an increment instead
3191 of add then GOOD for ME */
3192 if (genPlusIncr (ic) == TRUE)
3195 size = getDataSize (IC_RESULT (ic));
3197 leftOp = AOP(IC_LEFT(ic));
3198 rightOp = AOP(IC_RIGHT(ic));
3203 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3205 emitcode("mov", "b,a");
3206 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3207 emitcode("xch", "a,b");
3208 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3209 emitcode (add, "a,b");
3211 else if (aopGetUsesAcc (leftOp, offset))
3213 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3214 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3218 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3219 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3221 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3222 add = "addc"; /* further adds must propagate carry */
3225 adjustArithmeticResult (ic);
3228 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3229 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3230 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3233 /*-----------------------------------------------------------------*/
3234 /* genMinusDec :- does subtraction with deccrement if possible */
3235 /*-----------------------------------------------------------------*/
3237 genMinusDec (iCode * ic)
3239 unsigned int icount;
3240 unsigned int size = getDataSize (IC_RESULT (ic));
3242 /* will try to generate an increment */
3243 /* if the right side is not a literal
3245 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3248 /* if the literal value of the right hand side
3249 is greater than 4 then it is not worth it */
3250 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3253 D(emitcode ("; genMinusDec",""));
3255 /* if decrement >=16 bits in register or direct space */
3256 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3257 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3265 /* If the next instruction is a goto and the goto target
3266 * is <= 10 instructions previous to this, we can generate
3267 * jumps straight to that target.
3269 if (ic->next && ic->next->op == GOTO
3270 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3271 && labelRange <= 10)
3273 emitcode (";", "tail decrement optimized");
3274 tlbl = IC_LABEL (ic->next);
3279 tlbl = newiTempLabel (NULL);
3283 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3284 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3285 IS_AOP_PREG (IC_RESULT (ic)))
3286 emitcode ("cjne", "%s,#0xff,%05d$"
3287 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3291 emitcode ("mov", "a,#0xff");
3292 emitcode ("cjne", "a,%s,%05d$"
3293 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3296 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3299 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3300 IS_AOP_PREG (IC_RESULT (ic)))
3301 emitcode ("cjne", "%s,#0xff,%05d$"
3302 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3306 emitcode ("cjne", "a,%s,%05d$"
3307 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3310 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3314 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3315 IS_AOP_PREG (IC_RESULT (ic)))
3316 emitcode ("cjne", "%s,#0xff,%05d$"
3317 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3321 emitcode ("cjne", "a,%s,%05d$"
3322 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3325 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3329 emitcode ("", "%05d$:", tlbl->key + 100);
3334 /* if the sizes are greater than 1 then we cannot */
3335 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3336 AOP_SIZE (IC_LEFT (ic)) > 1)
3339 /* we can if the aops of the left & result match or
3340 if they are in registers and the registers are the
3342 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3346 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3354 /*-----------------------------------------------------------------*/
3355 /* addSign - complete with sign */
3356 /*-----------------------------------------------------------------*/
3358 addSign (operand * result, int offset, int sign)
3360 int size = (getDataSize (result) - offset);
3365 emitcode ("rlc", "a");
3366 emitcode ("subb", "a,acc");
3368 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3372 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3376 /*-----------------------------------------------------------------*/
3377 /* genMinusBits - generates code for subtraction of two bits */
3378 /*-----------------------------------------------------------------*/
3380 genMinusBits (iCode * ic)
3382 symbol *lbl = newiTempLabel (NULL);
3384 D(emitcode ("; genMinusBits",""));
3386 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3388 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3389 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3390 emitcode ("cpl", "c");
3391 emitcode ("", "%05d$:", (lbl->key + 100));
3392 outBitC (IC_RESULT (ic));
3396 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3397 emitcode ("subb", "a,acc");
3398 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3399 emitcode ("inc", "a");
3400 emitcode ("", "%05d$:", (lbl->key + 100));
3401 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3402 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3406 /*-----------------------------------------------------------------*/
3407 /* genMinus - generates code for subtraction */
3408 /*-----------------------------------------------------------------*/
3410 genMinus (iCode * ic)
3412 int size, offset = 0;
3414 D(emitcode ("; genMinus",""));
3416 aopOp (IC_LEFT (ic), ic, FALSE);
3417 aopOp (IC_RIGHT (ic), ic, FALSE);
3418 aopOp (IC_RESULT (ic), ic, TRUE);
3420 /* special cases :- */
3421 /* if both left & right are in bit space */
3422 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3423 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3429 /* if I can do an decrement instead
3430 of subtract then GOOD for ME */
3431 if (genMinusDec (ic) == TRUE)
3434 size = getDataSize (IC_RESULT (ic));
3436 /* if literal, add a,#-lit, else normal subb */
3437 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3439 unsigned long lit = 0L;
3441 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3446 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3447 /* first add without previous c */
3449 if (!size && lit== (unsigned long) -1) {
3450 emitcode ("dec", "a");
3452 emitcode ("add", "a,#0x%02x",
3453 (unsigned int) (lit & 0x0FFL));
3456 emitcode ("addc", "a,#0x%02x",
3457 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3459 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3464 asmop *leftOp, *rightOp;
3466 leftOp = AOP(IC_LEFT(ic));
3467 rightOp = AOP(IC_RIGHT(ic));
3471 if (aopGetUsesAcc(rightOp, offset)) {
3472 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3473 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3475 emitcode( "setb", "c");
3477 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3478 emitcode("cpl", "a");
3480 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3483 emitcode ("subb", "a,%s",
3484 aopGet(rightOp, offset, FALSE, TRUE));
3487 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3492 adjustArithmeticResult (ic);
3495 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3496 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3497 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3501 /*-----------------------------------------------------------------*/
3502 /* genMultbits :- multiplication of bits */
3503 /*-----------------------------------------------------------------*/
3505 genMultbits (operand * left,
3509 D(emitcode ("; genMultbits",""));
3511 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3512 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3517 /*-----------------------------------------------------------------*/
3518 /* genMultOneByte : 8*8=8/16 bit multiplication */
3519 /*-----------------------------------------------------------------*/
3521 genMultOneByte (operand * left,
3525 sym_link *opetype = operandType (result);
3527 int size=AOP_SIZE(result);
3529 D(emitcode ("; genMultOneByte",""));
3531 if (size<1 || size>2) {
3532 // this should never happen
3533 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3534 AOP_SIZE(result), __FILE__, lineno);
3538 /* (if two literals: the value is computed before) */
3539 /* if one literal, literal on the right */
3540 if (AOP_TYPE (left) == AOP_LIT)
3545 //emitcode (";", "swapped left and right");
3548 if (SPEC_USIGN(opetype)
3549 // ignore the sign of left and right, what else can we do?
3550 || (SPEC_USIGN(operandType(left)) &&
3551 SPEC_USIGN(operandType(right)))) {
3552 // just an unsigned 8*8=8/16 multiply
3553 //emitcode (";","unsigned");
3554 // TODO: check for accumulator clash between left & right aops?
3555 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3556 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3557 emitcode ("mul", "ab");
3558 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3560 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3565 // we have to do a signed multiply
3567 //emitcode (";", "signed");
3568 emitcode ("clr", "F0"); // reset sign flag
3569 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3571 lbl=newiTempLabel(NULL);
3572 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3573 // left side is negative, 8-bit two's complement, this fails for -128
3574 emitcode ("setb", "F0"); // set sign flag
3575 emitcode ("cpl", "a");
3576 emitcode ("inc", "a");
3578 emitcode ("", "%05d$:", lbl->key+100);
3581 if (AOP_TYPE(right)==AOP_LIT) {
3582 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3583 /* AND literal negative */
3585 emitcode ("cpl", "F0"); // complement sign flag
3586 emitcode ("mov", "b,#0x%02x", -val);
3588 emitcode ("mov", "b,#0x%02x", val);
3591 lbl=newiTempLabel(NULL);
3592 emitcode ("mov", "b,a");
3593 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3594 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3595 // right side is negative, 8-bit two's complement
3596 emitcode ("cpl", "F0"); // complement sign flag
3597 emitcode ("cpl", "a");
3598 emitcode ("inc", "a");
3599 emitcode ("", "%05d$:", lbl->key+100);
3601 emitcode ("mul", "ab");
3603 lbl=newiTempLabel(NULL);
3604 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3605 // only ONE op was negative, we have to do a 8/16-bit two's complement
3606 emitcode ("cpl", "a"); // lsb
3608 emitcode ("inc", "a");
3610 emitcode ("add", "a,#1");
3611 emitcode ("xch", "a,b");
3612 emitcode ("cpl", "a"); // msb
3613 emitcode ("addc", "a,#0");
3614 emitcode ("xch", "a,b");
3617 emitcode ("", "%05d$:", lbl->key+100);
3618 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3620 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3624 /*-----------------------------------------------------------------*/
3625 /* genMult - generates code for multiplication */
3626 /*-----------------------------------------------------------------*/
3628 genMult (iCode * ic)
3630 operand *left = IC_LEFT (ic);
3631 operand *right = IC_RIGHT (ic);
3632 operand *result = IC_RESULT (ic);
3634 D(emitcode ("; genMult",""));
3636 /* assign the amsops */
3637 aopOp (left, ic, FALSE);
3638 aopOp (right, ic, FALSE);
3639 aopOp (result, ic, TRUE);
3641 /* special cases first */
3643 if (AOP_TYPE (left) == AOP_CRY &&
3644 AOP_TYPE (right) == AOP_CRY)
3646 genMultbits (left, right, result);
3650 /* if both are of size == 1 */
3651 #if 0 // one of them can be a sloc shared with the result
3652 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3654 if (getSize(operandType(left)) == 1 &&
3655 getSize(operandType(right)) == 1)
3658 genMultOneByte (left, right, result);
3662 /* should have been converted to function call */
3663 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3664 getSize(OP_SYMBOL(right)->type));
3668 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3669 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3670 freeAsmop (result, NULL, ic, TRUE);
3673 /*-----------------------------------------------------------------*/
3674 /* genDivbits :- division of bits */
3675 /*-----------------------------------------------------------------*/
3677 genDivbits (operand * left,
3684 D(emitcode ("; genDivbits",""));
3686 /* the result must be bit */
3687 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3688 l = aopGet (AOP (left), 0, FALSE, FALSE);
3692 emitcode ("div", "ab");
3693 emitcode ("rrc", "a");
3694 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3697 /*-----------------------------------------------------------------*/
3698 /* genDivOneByte : 8 bit division */
3699 /*-----------------------------------------------------------------*/
3701 genDivOneByte (operand * left,
3705 sym_link *opetype = operandType (result);
3710 D(emitcode ("; genDivOneByte",""));
3712 size = AOP_SIZE (result) - 1;
3714 /* signed or unsigned */
3715 if (SPEC_USIGN (opetype))
3717 /* unsigned is easy */
3718 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3719 l = aopGet (AOP (left), 0, FALSE, FALSE);
3721 emitcode ("div", "ab");
3722 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3724 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3728 /* signed is a little bit more difficult */
3730 /* save the signs of the operands */
3731 l = aopGet (AOP (left), 0, FALSE, FALSE);
3733 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3734 emitcode ("push", "acc"); /* save it on the stack */
3736 /* now sign adjust for both left & right */
3737 l = aopGet (AOP (right), 0, FALSE, FALSE);
3739 lbl = newiTempLabel (NULL);
3740 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3741 emitcode ("cpl", "a");
3742 emitcode ("inc", "a");
3743 emitcode ("", "%05d$:", (lbl->key + 100));
3744 emitcode ("mov", "b,a");
3746 /* sign adjust left side */
3747 l = aopGet (AOP (left), 0, FALSE, FALSE);
3750 lbl = newiTempLabel (NULL);
3751 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3752 emitcode ("cpl", "a");
3753 emitcode ("inc", "a");
3754 emitcode ("", "%05d$:", (lbl->key + 100));
3756 /* now the division */
3757 emitcode ("div", "ab");
3758 /* we are interested in the lower order
3760 emitcode ("mov", "b,a");
3761 lbl = newiTempLabel (NULL);
3762 emitcode ("pop", "acc");
3763 /* if there was an over flow we don't
3764 adjust the sign of the result */
3765 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3766 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3768 emitcode ("clr", "a");
3769 emitcode ("subb", "a,b");
3770 emitcode ("mov", "b,a");
3771 emitcode ("", "%05d$:", (lbl->key + 100));
3773 /* now we are done */
3774 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3777 emitcode ("mov", "c,b.7");
3778 emitcode ("subb", "a,acc");
3781 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3785 /*-----------------------------------------------------------------*/
3786 /* genDiv - generates code for division */
3787 /*-----------------------------------------------------------------*/
3791 operand *left = IC_LEFT (ic);
3792 operand *right = IC_RIGHT (ic);
3793 operand *result = IC_RESULT (ic);
3795 D(emitcode ("; genDiv",""));
3797 /* assign the amsops */
3798 aopOp (left, ic, FALSE);
3799 aopOp (right, ic, FALSE);
3800 aopOp (result, ic, TRUE);
3802 /* special cases first */
3804 if (AOP_TYPE (left) == AOP_CRY &&
3805 AOP_TYPE (right) == AOP_CRY)
3807 genDivbits (left, right, result);
3811 /* if both are of size == 1 */
3812 if (AOP_SIZE (left) == 1 &&
3813 AOP_SIZE (right) == 1)
3815 genDivOneByte (left, right, result);
3819 /* should have been converted to function call */
3822 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3823 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3824 freeAsmop (result, NULL, ic, TRUE);
3827 /*-----------------------------------------------------------------*/
3828 /* genModbits :- modulus of bits */
3829 /*-----------------------------------------------------------------*/
3831 genModbits (operand * left,
3838 D(emitcode ("; genModbits",""));
3840 /* the result must be bit */
3841 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3842 l = aopGet (AOP (left), 0, FALSE, FALSE);
3846 emitcode ("div", "ab");
3847 emitcode ("mov", "a,b");
3848 emitcode ("rrc", "a");
3849 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3852 /*-----------------------------------------------------------------*/
3853 /* genModOneByte : 8 bit modulus */
3854 /*-----------------------------------------------------------------*/
3856 genModOneByte (operand * left,
3860 sym_link *opetype = operandType (result);
3864 D(emitcode ("; genModOneByte",""));
3866 /* signed or unsigned */
3867 if (SPEC_USIGN (opetype))
3869 /* unsigned is easy */
3870 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3871 l = aopGet (AOP (left), 0, FALSE, FALSE);
3873 emitcode ("div", "ab");
3874 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3878 /* signed is a little bit more difficult */
3880 /* save the signs of the operands */
3881 l = aopGet (AOP (left), 0, FALSE, FALSE);
3884 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3885 emitcode ("push", "acc"); /* save it on the stack */
3887 /* now sign adjust for both left & right */
3888 l = aopGet (AOP (right), 0, FALSE, FALSE);
3891 lbl = newiTempLabel (NULL);
3892 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3893 emitcode ("cpl", "a");
3894 emitcode ("inc", "a");
3895 emitcode ("", "%05d$:", (lbl->key + 100));
3896 emitcode ("mov", "b,a");
3898 /* sign adjust left side */
3899 l = aopGet (AOP (left), 0, FALSE, FALSE);
3902 lbl = newiTempLabel (NULL);
3903 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3904 emitcode ("cpl", "a");
3905 emitcode ("inc", "a");
3906 emitcode ("", "%05d$:", (lbl->key + 100));
3908 /* now the multiplication */
3909 emitcode ("div", "ab");
3910 /* we are interested in the lower order
3912 lbl = newiTempLabel (NULL);
3913 emitcode ("pop", "acc");
3914 /* if there was an over flow we don't
3915 adjust the sign of the result */
3916 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3917 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3919 emitcode ("clr", "a");
3920 emitcode ("subb", "a,b");
3921 emitcode ("mov", "b,a");
3922 emitcode ("", "%05d$:", (lbl->key + 100));
3924 /* now we are done */
3925 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3929 /*-----------------------------------------------------------------*/
3930 /* genMod - generates code for division */
3931 /*-----------------------------------------------------------------*/
3935 operand *left = IC_LEFT (ic);
3936 operand *right = IC_RIGHT (ic);
3937 operand *result = IC_RESULT (ic);
3939 D(emitcode ("; genMod",""));
3941 /* assign the amsops */
3942 aopOp (left, ic, FALSE);
3943 aopOp (right, ic, FALSE);
3944 aopOp (result, ic, TRUE);
3946 /* special cases first */
3948 if (AOP_TYPE (left) == AOP_CRY &&
3949 AOP_TYPE (right) == AOP_CRY)
3951 genModbits (left, right, result);
3955 /* if both are of size == 1 */
3956 if (AOP_SIZE (left) == 1 &&
3957 AOP_SIZE (right) == 1)
3959 genModOneByte (left, right, result);
3963 /* should have been converted to function call */
3967 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3968 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3969 freeAsmop (result, NULL, ic, TRUE);
3972 /*-----------------------------------------------------------------*/
3973 /* genIfxJump :- will create a jump depending on the ifx */
3974 /*-----------------------------------------------------------------*/
3976 genIfxJump (iCode * ic, char *jval)
3979 symbol *tlbl = newiTempLabel (NULL);
3982 D(emitcode ("; genIfxJump",""));
3984 /* if true label then we jump if condition
3988 jlbl = IC_TRUE (ic);
3989 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3990 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3994 /* false label is present */
3995 jlbl = IC_FALSE (ic);
3996 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3997 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3999 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4000 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4002 emitcode (inst, "%05d$", tlbl->key + 100);
4003 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4004 emitcode ("", "%05d$:", tlbl->key + 100);
4006 /* mark the icode as generated */
4010 /*-----------------------------------------------------------------*/
4011 /* genCmp :- greater or less than comparison */
4012 /*-----------------------------------------------------------------*/
4014 genCmp (operand * left, operand * right,
4015 operand * result, iCode * ifx, int sign, iCode *ic)
4017 int size, offset = 0;
4018 unsigned long lit = 0L;
4021 D(emitcode ("; genCmp",""));
4023 /* if left & right are bit variables */
4024 if (AOP_TYPE (left) == AOP_CRY &&
4025 AOP_TYPE (right) == AOP_CRY)
4027 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4028 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4032 /* subtract right from left if at the
4033 end the carry flag is set then we know that
4034 left is greater than right */
4035 size = max (AOP_SIZE (left), AOP_SIZE (right));
4037 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4038 if ((size == 1) && !sign &&
4039 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4041 symbol *lbl = newiTempLabel (NULL);
4042 emitcode ("cjne", "%s,%s,%05d$",
4043 aopGet (AOP (left), offset, FALSE, FALSE),
4044 aopGet (AOP (right), offset, FALSE, FALSE),
4046 emitcode ("", "%05d$:", lbl->key + 100);
4050 if (AOP_TYPE (right) == AOP_LIT)
4052 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4053 /* optimize if(x < 0) or if(x >= 0) */
4062 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4063 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4065 genIfxJump (ifx, "acc.7");
4069 emitcode ("rlc", "a");
4077 rightInB = aopGetUsesAcc(AOP (right), offset);
4079 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4080 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4081 if (sign && size == 0)
4083 emitcode ("xrl", "a,#0x80");
4084 if (AOP_TYPE (right) == AOP_LIT)
4086 unsigned long lit = (unsigned long)
4087 floatFromVal (AOP (right)->aopu.aop_lit);
4088 emitcode ("subb", "a,#0x%02x",
4089 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4094 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4095 emitcode ("xrl", "b,#0x80");
4096 emitcode ("subb", "a,b");
4102 emitcode ("subb", "a,b");
4104 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4112 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4113 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4114 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4120 /* if the result is used in the next
4121 ifx conditional branch then generate
4122 code a little differently */
4124 genIfxJump (ifx, "c");
4127 /* leave the result in acc */
4131 /*-----------------------------------------------------------------*/
4132 /* genCmpGt :- greater than comparison */
4133 /*-----------------------------------------------------------------*/
4135 genCmpGt (iCode * ic, iCode * ifx)
4137 operand *left, *right, *result;
4138 sym_link *letype, *retype;
4141 D(emitcode ("; genCmpGt",""));
4143 left = IC_LEFT (ic);
4144 right = IC_RIGHT (ic);
4145 result = IC_RESULT (ic);
4147 letype = getSpec (operandType (left));
4148 retype = getSpec (operandType (right));
4149 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4150 /* assign the amsops */
4151 aopOp (left, ic, FALSE);
4152 aopOp (right, ic, FALSE);
4153 aopOp (result, ic, TRUE);
4155 genCmp (right, left, result, ifx, sign,ic);
4157 freeAsmop (result, NULL, ic, TRUE);
4160 /*-----------------------------------------------------------------*/
4161 /* genCmpLt - less than comparisons */
4162 /*-----------------------------------------------------------------*/
4164 genCmpLt (iCode * ic, iCode * ifx)
4166 operand *left, *right, *result;
4167 sym_link *letype, *retype;
4170 D(emitcode ("; genCmpLt",""));
4172 left = IC_LEFT (ic);
4173 right = IC_RIGHT (ic);
4174 result = IC_RESULT (ic);
4176 letype = getSpec (operandType (left));
4177 retype = getSpec (operandType (right));
4178 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4180 /* assign the amsops */
4181 aopOp (left, ic, FALSE);
4182 aopOp (right, ic, FALSE);
4183 aopOp (result, ic, TRUE);
4185 genCmp (left, right, result, ifx, sign,ic);
4187 freeAsmop (result, NULL, ic, TRUE);
4190 /*-----------------------------------------------------------------*/
4191 /* gencjneshort - compare and jump if not equal */
4192 /*-----------------------------------------------------------------*/
4194 gencjneshort (operand * left, operand * right, symbol * lbl)
4196 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4198 unsigned long lit = 0L;
4200 /* if the left side is a literal or
4201 if the right is in a pointer register and left
4203 if ((AOP_TYPE (left) == AOP_LIT) ||
4204 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4210 if (AOP_TYPE (right) == AOP_LIT)
4211 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4213 /* if the right side is a literal then anything goes */
4214 if (AOP_TYPE (right) == AOP_LIT &&
4215 AOP_TYPE (left) != AOP_DIR &&
4216 AOP_TYPE (left) != AOP_IMMD)
4220 emitcode ("cjne", "%s,%s,%05d$",
4221 aopGet (AOP (left), offset, FALSE, FALSE),
4222 aopGet (AOP (right), offset, FALSE, FALSE),
4228 /* if the right side is in a register or in direct space or
4229 if the left is a pointer register & right is not */
4230 else if (AOP_TYPE (right) == AOP_REG ||
4231 AOP_TYPE (right) == AOP_DIR ||
4232 AOP_TYPE (right) == AOP_LIT ||
4233 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4234 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4238 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4239 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4240 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4241 emitcode ("jnz", "%05d$", lbl->key + 100);
4243 emitcode ("cjne", "a,%s,%05d$",
4244 aopGet (AOP (right), offset, FALSE, TRUE),
4251 /* right is a pointer reg need both a & b */
4254 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4255 if (strcmp (l, "b"))
4256 emitcode ("mov", "b,%s", l);
4257 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4258 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4264 /*-----------------------------------------------------------------*/
4265 /* gencjne - compare and jump if not equal */
4266 /*-----------------------------------------------------------------*/
4268 gencjne (operand * left, operand * right, symbol * lbl)
4270 symbol *tlbl = newiTempLabel (NULL);
4272 gencjneshort (left, right, lbl);
4274 emitcode ("mov", "a,%s", one);
4275 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4276 emitcode ("", "%05d$:", lbl->key + 100);
4277 emitcode ("clr", "a");
4278 emitcode ("", "%05d$:", tlbl->key + 100);
4281 /*-----------------------------------------------------------------*/
4282 /* genCmpEq - generates code for equal to */
4283 /*-----------------------------------------------------------------*/
4285 genCmpEq (iCode * ic, iCode * ifx)
4287 operand *left, *right, *result;
4289 D(emitcode ("; genCmpEq",""));
4291 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4292 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4293 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4295 /* if literal, literal on the right or
4296 if the right is in a pointer register and left
4298 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4299 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4301 operand *t = IC_RIGHT (ic);
4302 IC_RIGHT (ic) = IC_LEFT (ic);
4306 if (ifx && !AOP_SIZE (result))
4309 /* if they are both bit variables */
4310 if (AOP_TYPE (left) == AOP_CRY &&
4311 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4313 if (AOP_TYPE (right) == AOP_LIT)
4315 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4318 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4319 emitcode ("cpl", "c");
4323 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4327 emitcode ("clr", "c");
4329 /* AOP_TYPE(right) == AOP_CRY */
4333 symbol *lbl = newiTempLabel (NULL);
4334 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4335 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4336 emitcode ("cpl", "c");
4337 emitcode ("", "%05d$:", (lbl->key + 100));
4339 /* if true label then we jump if condition
4341 tlbl = newiTempLabel (NULL);
4344 emitcode ("jnc", "%05d$", tlbl->key + 100);
4345 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4349 emitcode ("jc", "%05d$", tlbl->key + 100);
4350 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4352 emitcode ("", "%05d$:", tlbl->key + 100);
4356 tlbl = newiTempLabel (NULL);
4357 gencjneshort (left, right, tlbl);
4360 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4361 emitcode ("", "%05d$:", tlbl->key + 100);
4365 symbol *lbl = newiTempLabel (NULL);
4366 emitcode ("sjmp", "%05d$", lbl->key + 100);
4367 emitcode ("", "%05d$:", tlbl->key + 100);
4368 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4369 emitcode ("", "%05d$:", lbl->key + 100);
4372 /* mark the icode as generated */
4377 /* if they are both bit variables */
4378 if (AOP_TYPE (left) == AOP_CRY &&
4379 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4381 if (AOP_TYPE (right) == AOP_LIT)
4383 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4386 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4387 emitcode ("cpl", "c");
4391 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4395 emitcode ("clr", "c");
4397 /* AOP_TYPE(right) == AOP_CRY */
4401 symbol *lbl = newiTempLabel (NULL);
4402 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4403 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4404 emitcode ("cpl", "c");
4405 emitcode ("", "%05d$:", (lbl->key + 100));
4408 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4415 genIfxJump (ifx, "c");
4418 /* if the result is used in an arithmetic operation
4419 then put the result in place */
4424 gencjne (left, right, newiTempLabel (NULL));
4425 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4427 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4432 genIfxJump (ifx, "a");
4435 /* if the result is used in an arithmetic operation
4436 then put the result in place */
4437 if (AOP_TYPE (result) != AOP_CRY)
4439 /* leave the result in acc */
4443 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4444 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4445 freeAsmop (result, NULL, ic, TRUE);
4448 /*-----------------------------------------------------------------*/
4449 /* ifxForOp - returns the icode containing the ifx for operand */
4450 /*-----------------------------------------------------------------*/
4452 ifxForOp (operand * op, iCode * ic)
4454 /* if true symbol then needs to be assigned */
4455 if (IS_TRUE_SYMOP (op))
4458 /* if this has register type condition and
4459 the next instruction is ifx with the same operand
4460 and live to of the operand is upto the ifx only then */
4462 ic->next->op == IFX &&
4463 IC_COND (ic->next)->key == op->key &&
4464 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4470 /*-----------------------------------------------------------------*/
4471 /* hasInc - operand is incremented before any other use */
4472 /*-----------------------------------------------------------------*/
4474 hasInc (operand *op, iCode *ic,int osize)
4476 sym_link *type = operandType(op);
4477 sym_link *retype = getSpec (type);
4478 iCode *lic = ic->next;
4481 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4482 if (!IS_SYMOP(op)) return NULL;
4484 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4485 if (IS_AGGREGATE(type->next)) return NULL;
4486 if (osize != (isize = getSize(type->next))) return NULL;
4489 /* if operand of the form op = op + <sizeof *op> */
4490 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4491 isOperandEqual(IC_RESULT(lic),op) &&
4492 isOperandLiteral(IC_RIGHT(lic)) &&
4493 operandLitValue(IC_RIGHT(lic)) == isize) {
4496 /* if the operand used or deffed */
4497 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4500 /* if GOTO or IFX */
4501 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4507 /*-----------------------------------------------------------------*/
4508 /* genAndOp - for && operation */
4509 /*-----------------------------------------------------------------*/
4511 genAndOp (iCode * ic)
4513 operand *left, *right, *result;
4516 D(emitcode ("; genAndOp",""));
4518 /* note here that && operations that are in an
4519 if statement are taken away by backPatchLabels
4520 only those used in arthmetic operations remain */
4521 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4522 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4523 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4525 /* if both are bit variables */
4526 if (AOP_TYPE (left) == AOP_CRY &&
4527 AOP_TYPE (right) == AOP_CRY)
4529 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4530 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4535 tlbl = newiTempLabel (NULL);
4537 emitcode ("jz", "%05d$", tlbl->key + 100);
4539 emitcode ("", "%05d$:", tlbl->key + 100);
4543 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4544 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4545 freeAsmop (result, NULL, ic, TRUE);
4549 /*-----------------------------------------------------------------*/
4550 /* genOrOp - for || operation */
4551 /*-----------------------------------------------------------------*/
4553 genOrOp (iCode * ic)
4555 operand *left, *right, *result;
4558 D(emitcode ("; genOrOp",""));
4560 /* note here that || operations that are in an
4561 if statement are taken away by backPatchLabels
4562 only those used in arthmetic operations remain */
4563 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4564 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4565 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4567 /* if both are bit variables */
4568 if (AOP_TYPE (left) == AOP_CRY &&
4569 AOP_TYPE (right) == AOP_CRY)
4571 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4572 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4577 tlbl = newiTempLabel (NULL);
4579 emitcode ("jnz", "%05d$", tlbl->key + 100);
4581 emitcode ("", "%05d$:", tlbl->key + 100);
4585 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4586 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4587 freeAsmop (result, NULL, ic, TRUE);
4590 /*-----------------------------------------------------------------*/
4591 /* isLiteralBit - test if lit == 2^n */
4592 /*-----------------------------------------------------------------*/
4594 isLiteralBit (unsigned long lit)
4596 unsigned long pw[32] =
4597 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4598 0x100L, 0x200L, 0x400L, 0x800L,
4599 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4600 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4601 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4602 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4603 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4606 for (idx = 0; idx < 32; idx++)
4612 /*-----------------------------------------------------------------*/
4613 /* continueIfTrue - */
4614 /*-----------------------------------------------------------------*/
4616 continueIfTrue (iCode * ic)
4619 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4623 /*-----------------------------------------------------------------*/
4625 /*-----------------------------------------------------------------*/
4627 jumpIfTrue (iCode * ic)
4630 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4634 /*-----------------------------------------------------------------*/
4635 /* jmpTrueOrFalse - */
4636 /*-----------------------------------------------------------------*/
4638 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4640 // ugly but optimized by peephole
4643 symbol *nlbl = newiTempLabel (NULL);
4644 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4645 emitcode ("", "%05d$:", tlbl->key + 100);
4646 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4647 emitcode ("", "%05d$:", nlbl->key + 100);
4651 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4652 emitcode ("", "%05d$:", tlbl->key + 100);
4657 /*-----------------------------------------------------------------*/
4658 /* genAnd - code for and */
4659 /*-----------------------------------------------------------------*/
4661 genAnd (iCode * ic, iCode * ifx)
4663 operand *left, *right, *result;
4664 int size, offset = 0;
4665 unsigned long lit = 0L;
4669 D(emitcode ("; genAnd",""));
4671 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4672 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4673 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4676 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4678 AOP_TYPE (left), AOP_TYPE (right));
4679 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4681 AOP_SIZE (left), AOP_SIZE (right));
4684 /* if left is a literal & right is not then exchange them */
4685 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4686 AOP_NEEDSACC (left))
4688 operand *tmp = right;
4693 /* if result = right then exchange them */
4694 if (sameRegs (AOP (result), AOP (right)))
4696 operand *tmp = right;
4701 /* if right is bit then exchange them */
4702 if (AOP_TYPE (right) == AOP_CRY &&
4703 AOP_TYPE (left) != AOP_CRY)
4705 operand *tmp = right;
4709 if (AOP_TYPE (right) == AOP_LIT)
4710 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4712 size = AOP_SIZE (result);
4715 // result = bit & yy;
4716 if (AOP_TYPE (left) == AOP_CRY)
4718 // c = bit & literal;
4719 if (AOP_TYPE (right) == AOP_LIT)
4723 if (size && sameRegs (AOP (result), AOP (left)))
4726 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4731 if (size && (AOP_TYPE (result) == AOP_CRY))
4733 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4736 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4741 emitcode ("clr", "c");
4746 if (AOP_TYPE (right) == AOP_CRY)
4749 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4750 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4755 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4757 emitcode ("rrc", "a");
4758 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4766 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4767 genIfxJump (ifx, "c");
4771 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4772 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4773 if ((AOP_TYPE (right) == AOP_LIT) &&
4774 (AOP_TYPE (result) == AOP_CRY) &&
4775 (AOP_TYPE (left) != AOP_CRY))
4777 int posbit = isLiteralBit (lit);
4782 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4785 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4791 sprintf (buffer, "acc.%d", posbit & 0x07);
4792 genIfxJump (ifx, buffer);
4799 symbol *tlbl = newiTempLabel (NULL);
4800 int sizel = AOP_SIZE (left);
4802 emitcode ("setb", "c");
4805 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4807 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4809 if ((posbit = isLiteralBit (bytelit)) != 0)
4810 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4813 if (bytelit != 0x0FFL)
4814 emitcode ("anl", "a,%s",
4815 aopGet (AOP (right), offset, FALSE, TRUE));
4816 emitcode ("jnz", "%05d$", tlbl->key + 100);
4821 // bit = left & literal
4824 emitcode ("clr", "c");
4825 emitcode ("", "%05d$:", tlbl->key + 100);
4827 // if(left & literal)
4831 jmpTrueOrFalse (ifx, tlbl);
4839 /* if left is same as result */
4840 if (sameRegs (AOP (result), AOP (left)))
4842 for (; size--; offset++)
4844 if (AOP_TYPE (right) == AOP_LIT)
4846 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4848 else if (bytelit == 0)
4850 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4852 else if (IS_AOP_PREG (result))
4854 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4855 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4856 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4859 emitcode ("anl", "%s,%s",
4860 aopGet (AOP (left), offset, FALSE, TRUE),
4861 aopGet (AOP (right), offset, FALSE, FALSE));
4865 if (AOP_TYPE (left) == AOP_ACC)
4866 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4869 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4870 if (IS_AOP_PREG (result))
4872 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4873 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4877 emitcode ("anl", "%s,a",
4878 aopGet (AOP (left), offset, FALSE, TRUE));
4885 // left & result in different registers
4886 if (AOP_TYPE (result) == AOP_CRY)
4889 // if(size), result in bit
4890 // if(!size && ifx), conditional oper: if(left & right)
4891 symbol *tlbl = newiTempLabel (NULL);
4892 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4894 emitcode ("setb", "c");
4897 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4898 emitcode ("anl", "a,%s",
4899 aopGet (AOP (right), offset, FALSE, FALSE));
4901 if (AOP_TYPE(left)==AOP_ACC) {
4902 emitcode("mov", "b,a");
4903 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4904 emitcode("anl", "a,b");
4906 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4907 emitcode ("anl", "a,%s",
4908 aopGet (AOP (left), offset, FALSE, FALSE));
4911 emitcode ("jnz", "%05d$", tlbl->key + 100);
4917 emitcode ("", "%05d$:", tlbl->key + 100);
4921 jmpTrueOrFalse (ifx, tlbl);
4925 for (; (size--); offset++)
4928 // result = left & right
4929 if (AOP_TYPE (right) == AOP_LIT)
4931 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4933 aopPut (AOP (result),
4934 aopGet (AOP (left), offset, FALSE, FALSE),
4936 isOperandVolatile (result, FALSE));
4939 else if (bytelit == 0)
4941 /* dummy read of volatile operand */
4942 if (isOperandVolatile (left, FALSE))
4943 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4944 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4948 // faster than result <- left, anl result,right
4949 // and better if result is SFR
4950 if (AOP_TYPE (left) == AOP_ACC)
4951 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4954 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4955 emitcode ("anl", "a,%s",
4956 aopGet (AOP (left), offset, FALSE, FALSE));
4958 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4964 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4965 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4966 freeAsmop (result, NULL, ic, TRUE);
4969 /*-----------------------------------------------------------------*/
4970 /* genOr - code for or */
4971 /*-----------------------------------------------------------------*/
4973 genOr (iCode * ic, iCode * ifx)
4975 operand *left, *right, *result;
4976 int size, offset = 0;
4977 unsigned long lit = 0L;
4979 D(emitcode ("; genOr",""));
4981 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4982 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4983 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4986 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4988 AOP_TYPE (left), AOP_TYPE (right));
4989 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4991 AOP_SIZE (left), AOP_SIZE (right));
4994 /* if left is a literal & right is not then exchange them */
4995 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4996 AOP_NEEDSACC (left))
4998 operand *tmp = right;
5003 /* if result = right then exchange them */
5004 if (sameRegs (AOP (result), AOP (right)))
5006 operand *tmp = right;
5011 /* if right is bit then exchange them */
5012 if (AOP_TYPE (right) == AOP_CRY &&
5013 AOP_TYPE (left) != AOP_CRY)
5015 operand *tmp = right;
5019 if (AOP_TYPE (right) == AOP_LIT)
5020 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5022 size = AOP_SIZE (result);
5026 if (AOP_TYPE (left) == AOP_CRY)
5028 if (AOP_TYPE (right) == AOP_LIT)
5030 // c = bit | literal;
5033 // lit != 0 => result = 1
5034 if (AOP_TYPE (result) == AOP_CRY)
5037 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5039 continueIfTrue (ifx);
5042 emitcode ("setb", "c");
5046 // lit == 0 => result = left
5047 if (size && sameRegs (AOP (result), AOP (left)))
5049 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5054 if (AOP_TYPE (right) == AOP_CRY)
5057 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5058 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5063 symbol *tlbl = newiTempLabel (NULL);
5064 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5065 emitcode ("setb", "c");
5066 emitcode ("jb", "%s,%05d$",
5067 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5069 emitcode ("jnz", "%05d$", tlbl->key + 100);
5070 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5072 jmpTrueOrFalse (ifx, tlbl);
5078 emitcode ("", "%05d$:", tlbl->key + 100);
5087 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5088 genIfxJump (ifx, "c");
5092 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5093 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5094 if ((AOP_TYPE (right) == AOP_LIT) &&
5095 (AOP_TYPE (result) == AOP_CRY) &&
5096 (AOP_TYPE (left) != AOP_CRY))
5102 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5104 continueIfTrue (ifx);
5109 // lit = 0, result = boolean(left)
5111 emitcode ("setb", "c");
5115 symbol *tlbl = newiTempLabel (NULL);
5116 emitcode ("jnz", "%05d$", tlbl->key + 100);
5118 emitcode ("", "%05d$:", tlbl->key + 100);
5122 genIfxJump (ifx, "a");
5130 /* if left is same as result */
5131 if (sameRegs (AOP (result), AOP (left)))
5133 for (; size--; offset++)
5135 if (AOP_TYPE (right) == AOP_LIT)
5137 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5139 /* dummy read of volatile operand */
5140 if (isOperandVolatile (left, FALSE))
5141 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5145 else if (IS_AOP_PREG (left))
5147 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5148 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5149 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5152 emitcode ("orl", "%s,%s",
5153 aopGet (AOP (left), offset, FALSE, TRUE),
5154 aopGet (AOP (right), offset, FALSE, FALSE));
5158 if (AOP_TYPE (left) == AOP_ACC)
5159 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5162 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5163 if (IS_AOP_PREG (left))
5165 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5166 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5169 emitcode ("orl", "%s,a",
5170 aopGet (AOP (left), offset, FALSE, TRUE));
5177 // left & result in different registers
5178 if (AOP_TYPE (result) == AOP_CRY)
5181 // if(size), result in bit
5182 // if(!size && ifx), conditional oper: if(left | right)
5183 symbol *tlbl = newiTempLabel (NULL);
5184 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5186 emitcode ("setb", "c");
5189 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5190 emitcode ("orl", "a,%s",
5191 aopGet (AOP (right), offset, FALSE, FALSE));
5193 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5194 emitcode ("orl", "a,%s",
5195 aopGet (AOP (left), offset, FALSE, FALSE));
5197 emitcode ("jnz", "%05d$", tlbl->key + 100);
5203 emitcode ("", "%05d$:", tlbl->key + 100);
5207 jmpTrueOrFalse (ifx, tlbl);
5210 for (; (size--); offset++)
5213 // result = left & right
5214 if (AOP_TYPE (right) == AOP_LIT)
5216 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5218 aopPut (AOP (result),
5219 aopGet (AOP (left), offset, FALSE, FALSE),
5221 isOperandVolatile (result, FALSE));
5225 // faster than result <- left, anl result,right
5226 // and better if result is SFR
5227 if (AOP_TYPE (left) == AOP_ACC)
5228 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5231 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5232 emitcode ("orl", "a,%s",
5233 aopGet (AOP (left), offset, FALSE, FALSE));
5235 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5240 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5241 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5242 freeAsmop (result, NULL, ic, TRUE);
5245 /*-----------------------------------------------------------------*/
5246 /* genXor - code for xclusive or */
5247 /*-----------------------------------------------------------------*/
5249 genXor (iCode * ic, iCode * ifx)
5251 operand *left, *right, *result;
5252 int size, offset = 0;
5253 unsigned long lit = 0L;
5255 D(emitcode ("; genXor",""));
5257 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5258 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5259 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5262 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5264 AOP_TYPE (left), AOP_TYPE (right));
5265 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5267 AOP_SIZE (left), AOP_SIZE (right));
5270 /* if left is a literal & right is not ||
5271 if left needs acc & right does not */
5272 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5273 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5275 operand *tmp = right;
5280 /* if result = right then exchange them */
5281 if (sameRegs (AOP (result), AOP (right)))
5283 operand *tmp = right;
5288 /* if right is bit then exchange them */
5289 if (AOP_TYPE (right) == AOP_CRY &&
5290 AOP_TYPE (left) != AOP_CRY)
5292 operand *tmp = right;
5296 if (AOP_TYPE (right) == AOP_LIT)
5297 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5299 size = AOP_SIZE (result);
5303 if (AOP_TYPE (left) == AOP_CRY)
5305 if (AOP_TYPE (right) == AOP_LIT)
5307 // c = bit & literal;
5310 // lit>>1 != 0 => result = 1
5311 if (AOP_TYPE (result) == AOP_CRY)
5314 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5316 continueIfTrue (ifx);
5319 emitcode ("setb", "c");
5326 // lit == 0, result = left
5327 if (size && sameRegs (AOP (result), AOP (left)))
5329 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5333 // lit == 1, result = not(left)
5334 if (size && sameRegs (AOP (result), AOP (left)))
5336 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5341 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5342 emitcode ("cpl", "c");
5351 symbol *tlbl = newiTempLabel (NULL);
5352 if (AOP_TYPE (right) == AOP_CRY)
5355 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5359 int sizer = AOP_SIZE (right);
5361 // if val>>1 != 0, result = 1
5362 emitcode ("setb", "c");
5365 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5367 // test the msb of the lsb
5368 emitcode ("anl", "a,#0xfe");
5369 emitcode ("jnz", "%05d$", tlbl->key + 100);
5373 emitcode ("rrc", "a");
5375 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5376 emitcode ("cpl", "c");
5377 emitcode ("", "%05d$:", (tlbl->key + 100));
5384 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5385 genIfxJump (ifx, "c");
5389 if (sameRegs (AOP (result), AOP (left)))
5391 /* if left is same as result */
5392 for (; size--; offset++)
5394 if (AOP_TYPE (right) == AOP_LIT)
5396 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5398 else if (IS_AOP_PREG (left))
5400 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5401 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5402 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5405 emitcode ("xrl", "%s,%s",
5406 aopGet (AOP (left), offset, FALSE, TRUE),
5407 aopGet (AOP (right), offset, FALSE, FALSE));
5411 if (AOP_TYPE (left) == AOP_ACC)
5412 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5415 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5416 if (IS_AOP_PREG (left))
5418 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5419 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5422 emitcode ("xrl", "%s,a",
5423 aopGet (AOP (left), offset, FALSE, TRUE));
5430 // left & result in different registers
5431 if (AOP_TYPE (result) == AOP_CRY)
5434 // if(size), result in bit
5435 // if(!size && ifx), conditional oper: if(left ^ right)
5436 symbol *tlbl = newiTempLabel (NULL);
5437 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5439 emitcode ("setb", "c");
5442 if ((AOP_TYPE (right) == AOP_LIT) &&
5443 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5445 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5449 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5450 emitcode ("xrl", "a,%s",
5451 aopGet (AOP (right), offset, FALSE, FALSE));
5453 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5454 emitcode ("xrl", "a,%s",
5455 aopGet (AOP (left), offset, FALSE, FALSE));
5458 emitcode ("jnz", "%05d$", tlbl->key + 100);
5464 emitcode ("", "%05d$:", tlbl->key + 100);
5468 jmpTrueOrFalse (ifx, tlbl);
5471 for (; (size--); offset++)
5474 // result = left & right
5475 if (AOP_TYPE (right) == AOP_LIT)
5477 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5479 aopPut (AOP (result),
5480 aopGet (AOP (left), offset, FALSE, FALSE),
5482 isOperandVolatile (result, FALSE));
5486 // faster than result <- left, anl result,right
5487 // and better if result is SFR
5488 if (AOP_TYPE (left) == AOP_ACC)
5489 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5492 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5493 emitcode ("xrl", "a,%s",
5494 aopGet (AOP (left), offset, FALSE, TRUE));
5496 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5501 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5502 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5503 freeAsmop (result, NULL, ic, TRUE);
5506 /*-----------------------------------------------------------------*/
5507 /* genInline - write the inline code out */
5508 /*-----------------------------------------------------------------*/
5510 genInline (iCode * ic)
5512 char *buffer, *bp, *bp1;
5514 D(emitcode ("; genInline",""));
5516 _G.inLine += (!options.asmpeep);
5518 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5519 strcpy (buffer, IC_INLINE (ic));
5521 /* emit each line as a code */
5546 /* emitcode("",buffer); */
5547 _G.inLine -= (!options.asmpeep);
5550 /*-----------------------------------------------------------------*/
5551 /* genRRC - rotate right with carry */
5552 /*-----------------------------------------------------------------*/
5556 operand *left, *result;
5557 int size, offset = 0;
5560 D(emitcode ("; genRRC",""));
5562 /* rotate right with carry */
5563 left = IC_LEFT (ic);
5564 result = IC_RESULT (ic);
5565 aopOp (left, ic, FALSE);
5566 aopOp (result, ic, FALSE);
5568 /* move it to the result */
5569 size = AOP_SIZE (result);
5571 if (size == 1) { /* special case for 1 byte */
5572 l = aopGet (AOP (left), offset, FALSE, FALSE);
5574 emitcode ("rr", "a");
5580 l = aopGet (AOP (left), offset, FALSE, FALSE);
5582 emitcode ("rrc", "a");
5583 if (AOP_SIZE (result) > 1)
5584 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5586 /* now we need to put the carry into the
5587 highest order byte of the result */
5588 if (AOP_SIZE (result) > 1)
5590 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5593 emitcode ("mov", "acc.7,c");
5595 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5596 freeAsmop (left, NULL, ic, TRUE);
5597 freeAsmop (result, NULL, ic, TRUE);
5600 /*-----------------------------------------------------------------*/
5601 /* genRLC - generate code for rotate left with carry */
5602 /*-----------------------------------------------------------------*/
5606 operand *left, *result;
5607 int size, offset = 0;
5610 D(emitcode ("; genRLC",""));
5612 /* rotate right with carry */
5613 left = IC_LEFT (ic);
5614 result = IC_RESULT (ic);
5615 aopOp (left, ic, FALSE);
5616 aopOp (result, ic, FALSE);
5618 /* move it to the result */
5619 size = AOP_SIZE (result);
5623 l = aopGet (AOP (left), offset, FALSE, FALSE);
5625 if (size == 0) { /* special case for 1 byte */
5629 emitcode ("add", "a,acc");
5630 if (AOP_SIZE (result) > 1)
5631 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5634 l = aopGet (AOP (left), offset, FALSE, FALSE);
5636 emitcode ("rlc", "a");
5637 if (AOP_SIZE (result) > 1)
5638 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5641 /* now we need to put the carry into the
5642 highest order byte of the result */
5643 if (AOP_SIZE (result) > 1)
5645 l = aopGet (AOP (result), 0, FALSE, FALSE);
5648 emitcode ("mov", "acc.0,c");
5650 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5651 freeAsmop (left, NULL, ic, TRUE);
5652 freeAsmop (result, NULL, ic, TRUE);
5655 /*-----------------------------------------------------------------*/
5656 /* genGetHbit - generates code get highest order bit */
5657 /*-----------------------------------------------------------------*/
5659 genGetHbit (iCode * ic)
5661 operand *left, *result;
5663 D(emitcode ("; genGetHbit",""));
5665 left = IC_LEFT (ic);
5666 result = IC_RESULT (ic);
5667 aopOp (left, ic, FALSE);
5668 aopOp (result, ic, FALSE);
5670 /* get the highest order byte into a */
5671 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5672 if (AOP_TYPE (result) == AOP_CRY)
5674 emitcode ("rlc", "a");
5679 emitcode ("rl", "a");
5680 emitcode ("anl", "a,#0x01");
5685 freeAsmop (left, NULL, ic, TRUE);
5686 freeAsmop (result, NULL, ic, TRUE);
5689 /*-----------------------------------------------------------------*/
5690 /* AccRol - rotate left accumulator by known count */
5691 /*-----------------------------------------------------------------*/
5693 AccRol (int shCount)
5695 shCount &= 0x0007; // shCount : 0..7
5702 emitcode ("rl", "a");
5705 emitcode ("rl", "a");
5706 emitcode ("rl", "a");
5709 emitcode ("swap", "a");
5710 emitcode ("rr", "a");
5713 emitcode ("swap", "a");
5716 emitcode ("swap", "a");
5717 emitcode ("rl", "a");
5720 emitcode ("rr", "a");
5721 emitcode ("rr", "a");
5724 emitcode ("rr", "a");
5729 /*-----------------------------------------------------------------*/
5730 /* AccLsh - left shift accumulator by known count */
5731 /*-----------------------------------------------------------------*/
5733 AccLsh (int shCount)
5738 emitcode ("add", "a,acc");
5739 else if (shCount == 2)
5741 emitcode ("add", "a,acc");
5742 emitcode ("add", "a,acc");
5746 /* rotate left accumulator */
5748 /* and kill the lower order bits */
5749 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5754 /*-----------------------------------------------------------------*/
5755 /* AccRsh - right shift accumulator by known count */
5756 /*-----------------------------------------------------------------*/
5758 AccRsh (int shCount)
5765 emitcode ("rrc", "a");
5769 /* rotate right accumulator */
5770 AccRol (8 - shCount);
5771 /* and kill the higher order bits */
5772 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5777 /*-----------------------------------------------------------------*/
5778 /* AccSRsh - signed right shift accumulator by known count */
5779 /*-----------------------------------------------------------------*/
5781 AccSRsh (int shCount)
5788 emitcode ("mov", "c,acc.7");
5789 emitcode ("rrc", "a");
5791 else if (shCount == 2)
5793 emitcode ("mov", "c,acc.7");
5794 emitcode ("rrc", "a");
5795 emitcode ("mov", "c,acc.7");
5796 emitcode ("rrc", "a");
5800 tlbl = newiTempLabel (NULL);
5801 /* rotate right accumulator */
5802 AccRol (8 - shCount);
5803 /* and kill the higher order bits */
5804 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5805 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5806 emitcode ("orl", "a,#0x%02x",
5807 (unsigned char) ~SRMask[shCount]);
5808 emitcode ("", "%05d$:", tlbl->key + 100);
5813 /*-----------------------------------------------------------------*/
5814 /* shiftR1Left2Result - shift right one byte from left to result */
5815 /*-----------------------------------------------------------------*/
5817 shiftR1Left2Result (operand * left, int offl,
5818 operand * result, int offr,
5819 int shCount, int sign)
5821 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5822 /* shift right accumulator */
5827 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5830 /*-----------------------------------------------------------------*/
5831 /* shiftL1Left2Result - shift left one byte from left to result */
5832 /*-----------------------------------------------------------------*/
5834 shiftL1Left2Result (operand * left, int offl,
5835 operand * result, int offr, int shCount)
5838 l = aopGet (AOP (left), offl, FALSE, FALSE);
5840 /* shift left accumulator */
5842 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5845 /*-----------------------------------------------------------------*/
5846 /* movLeft2Result - move byte from left to result */
5847 /*-----------------------------------------------------------------*/
5849 movLeft2Result (operand * left, int offl,
5850 operand * result, int offr, int sign)
5853 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5855 l = aopGet (AOP (left), offl, FALSE, FALSE);
5857 if (*l == '@' && (IS_AOP_PREG (result)))
5859 emitcode ("mov", "a,%s", l);
5860 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5865 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
5868 /* MSB sign in acc.7 ! */
5869 if (getDataSize (left) == offl + 1)
5871 emitcode ("mov", "a,%s", l);
5872 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5879 /*-----------------------------------------------------------------*/
5880 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5881 /*-----------------------------------------------------------------*/
5885 emitcode ("rrc", "a");
5886 emitcode ("xch", "a,%s", x);
5887 emitcode ("rrc", "a");
5888 emitcode ("xch", "a,%s", x);
5891 /*-----------------------------------------------------------------*/
5892 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5893 /*-----------------------------------------------------------------*/
5897 emitcode ("xch", "a,%s", x);
5898 emitcode ("rlc", "a");
5899 emitcode ("xch", "a,%s", x);
5900 emitcode ("rlc", "a");
5903 /*-----------------------------------------------------------------*/
5904 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5905 /*-----------------------------------------------------------------*/
5909 emitcode ("xch", "a,%s", x);
5910 emitcode ("add", "a,acc");
5911 emitcode ("xch", "a,%s", x);
5912 emitcode ("rlc", "a");
5915 /*-----------------------------------------------------------------*/
5916 /* AccAXLsh - left shift a:x by known count (0..7) */
5917 /*-----------------------------------------------------------------*/
5919 AccAXLsh (char *x, int shCount)
5934 case 5: // AAAAABBB:CCCCCDDD
5936 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5938 emitcode ("anl", "a,#0x%02x",
5939 SLMask[shCount]); // BBB00000:CCCCCDDD
5941 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5943 AccRol (shCount); // DDDCCCCC:BBB00000
5945 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5947 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5949 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5951 emitcode ("anl", "a,#0x%02x",
5952 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5954 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5956 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5959 case 6: // AAAAAABB:CCCCCCDD
5960 emitcode ("anl", "a,#0x%02x",
5961 SRMask[shCount]); // 000000BB:CCCCCCDD
5962 emitcode ("mov", "c,acc.0"); // c = B
5963 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5965 AccAXRrl1 (x); // BCCCCCCD:D000000B
5966 AccAXRrl1 (x); // BBCCCCCC:DD000000
5968 emitcode("rrc","a");
5969 emitcode("xch","a,%s", x);
5970 emitcode("rrc","a");
5971 emitcode("mov","c,acc.0"); //<< get correct bit
5972 emitcode("xch","a,%s", x);
5974 emitcode("rrc","a");
5975 emitcode("xch","a,%s", x);
5976 emitcode("rrc","a");
5977 emitcode("xch","a,%s", x);
5980 case 7: // a:x <<= 7
5982 emitcode ("anl", "a,#0x%02x",
5983 SRMask[shCount]); // 0000000B:CCCCCCCD
5985 emitcode ("mov", "c,acc.0"); // c = B
5987 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5989 AccAXRrl1 (x); // BCCCCCCC:D0000000
5997 /*-----------------------------------------------------------------*/
5998 /* AccAXRsh - right shift a:x known count (0..7) */
5999 /*-----------------------------------------------------------------*/
6001 AccAXRsh (char *x, int shCount)
6009 AccAXRrl1 (x); // 0->a:x
6014 AccAXRrl1 (x); // 0->a:x
6017 AccAXRrl1 (x); // 0->a:x
6022 case 5: // AAAAABBB:CCCCCDDD = a:x
6024 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6026 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6028 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6030 emitcode ("anl", "a,#0x%02x",
6031 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6033 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6035 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6037 emitcode ("anl", "a,#0x%02x",
6038 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6040 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6042 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6044 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6047 case 6: // AABBBBBB:CCDDDDDD
6049 emitcode ("mov", "c,acc.7");
6050 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6052 emitcode ("mov", "c,acc.7");
6053 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6055 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6057 emitcode ("anl", "a,#0x%02x",
6058 SRMask[shCount]); // 000000AA:BBBBBBCC
6061 case 7: // ABBBBBBB:CDDDDDDD
6063 emitcode ("mov", "c,acc.7"); // c = A
6065 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6067 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6069 emitcode ("anl", "a,#0x%02x",
6070 SRMask[shCount]); // 0000000A:BBBBBBBC
6078 /*-----------------------------------------------------------------*/
6079 /* AccAXRshS - right shift signed a:x known count (0..7) */
6080 /*-----------------------------------------------------------------*/
6082 AccAXRshS (char *x, int shCount)
6090 emitcode ("mov", "c,acc.7");
6091 AccAXRrl1 (x); // s->a:x
6095 emitcode ("mov", "c,acc.7");
6096 AccAXRrl1 (x); // s->a:x
6098 emitcode ("mov", "c,acc.7");
6099 AccAXRrl1 (x); // s->a:x
6104 case 5: // AAAAABBB:CCCCCDDD = a:x
6106 tlbl = newiTempLabel (NULL);
6107 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6109 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6111 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6113 emitcode ("anl", "a,#0x%02x",
6114 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6116 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6118 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6120 emitcode ("anl", "a,#0x%02x",
6121 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6123 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6125 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6127 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6129 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6130 emitcode ("orl", "a,#0x%02x",
6131 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6133 emitcode ("", "%05d$:", tlbl->key + 100);
6134 break; // SSSSAAAA:BBBCCCCC
6136 case 6: // AABBBBBB:CCDDDDDD
6138 tlbl = newiTempLabel (NULL);
6139 emitcode ("mov", "c,acc.7");
6140 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6142 emitcode ("mov", "c,acc.7");
6143 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6145 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6147 emitcode ("anl", "a,#0x%02x",
6148 SRMask[shCount]); // 000000AA:BBBBBBCC
6150 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6151 emitcode ("orl", "a,#0x%02x",
6152 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6154 emitcode ("", "%05d$:", tlbl->key + 100);
6156 case 7: // ABBBBBBB:CDDDDDDD
6158 tlbl = newiTempLabel (NULL);
6159 emitcode ("mov", "c,acc.7"); // c = A
6161 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6163 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6165 emitcode ("anl", "a,#0x%02x",
6166 SRMask[shCount]); // 0000000A:BBBBBBBC
6168 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6169 emitcode ("orl", "a,#0x%02x",
6170 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6172 emitcode ("", "%05d$:", tlbl->key + 100);
6179 /*-----------------------------------------------------------------*/
6180 /* shiftL2Left2Result - shift left two bytes from left to result */
6181 /*-----------------------------------------------------------------*/
6183 shiftL2Left2Result (operand * left, int offl,
6184 operand * result, int offr, int shCount)
6186 if (sameRegs (AOP (result), AOP (left)) &&
6187 ((offl + MSB16) == offr))
6189 /* don't crash result[offr] */
6190 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6191 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6195 movLeft2Result (left, offl, result, offr, 0);
6196 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6198 /* ax << shCount (x = lsb(result)) */
6199 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6200 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6204 /*-----------------------------------------------------------------*/
6205 /* shiftR2Left2Result - shift right two bytes from left to result */
6206 /*-----------------------------------------------------------------*/
6208 shiftR2Left2Result (operand * left, int offl,
6209 operand * result, int offr,
6210 int shCount, int sign)
6212 if (sameRegs (AOP (result), AOP (left)) &&
6213 ((offl + MSB16) == offr))
6215 /* don't crash result[offr] */
6216 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6217 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6221 movLeft2Result (left, offl, result, offr, 0);
6222 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6224 /* a:x >> shCount (x = lsb(result)) */
6226 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6228 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6229 if (getDataSize (result) > 1)
6230 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6233 /*-----------------------------------------------------------------*/
6234 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6235 /*-----------------------------------------------------------------*/
6237 shiftLLeftOrResult (operand * left, int offl,
6238 operand * result, int offr, int shCount)
6240 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6241 /* shift left accumulator */
6243 /* or with result */
6244 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6245 /* back to result */
6246 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6249 /*-----------------------------------------------------------------*/
6250 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6251 /*-----------------------------------------------------------------*/
6253 shiftRLeftOrResult (operand * left, int offl,
6254 operand * result, int offr, int shCount)
6256 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6257 /* shift right accumulator */
6259 /* or with result */
6260 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6261 /* back to result */
6262 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6265 /*-----------------------------------------------------------------*/
6266 /* genlshOne - left shift a one byte quantity by known count */
6267 /*-----------------------------------------------------------------*/
6269 genlshOne (operand * result, operand * left, int shCount)
6271 D(emitcode ("; genlshOne",""));
6273 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6276 /*-----------------------------------------------------------------*/
6277 /* genlshTwo - left shift two bytes by known amount != 0 */
6278 /*-----------------------------------------------------------------*/
6280 genlshTwo (operand * result, operand * left, int shCount)
6284 D(emitcode ("; genlshTwo",""));
6286 size = getDataSize (result);
6288 /* if shCount >= 8 */
6296 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6298 movLeft2Result (left, LSB, result, MSB16, 0);
6300 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6303 /* 1 <= shCount <= 7 */
6307 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6309 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6313 /*-----------------------------------------------------------------*/
6314 /* shiftLLong - shift left one long from left to result */
6315 /* offl = LSB or MSB16 */
6316 /*-----------------------------------------------------------------*/
6318 shiftLLong (operand * left, operand * result, int offr)
6321 int size = AOP_SIZE (result);
6323 if (size >= LSB + offr)
6325 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6327 emitcode ("add", "a,acc");
6328 if (sameRegs (AOP (left), AOP (result)) &&
6329 size >= MSB16 + offr && offr != LSB)
6330 emitcode ("xch", "a,%s",
6331 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6333 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6336 if (size >= MSB16 + offr)
6338 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6340 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6343 emitcode ("rlc", "a");
6344 if (sameRegs (AOP (left), AOP (result)) &&
6345 size >= MSB24 + offr && offr != LSB)
6346 emitcode ("xch", "a,%s",
6347 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6349 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6352 if (size >= MSB24 + offr)
6354 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6356 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6359 emitcode ("rlc", "a");
6360 if (sameRegs (AOP (left), AOP (result)) &&
6361 size >= MSB32 + offr && offr != LSB)
6362 emitcode ("xch", "a,%s",
6363 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6365 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6368 if (size > MSB32 + offr)
6370 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6372 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6375 emitcode ("rlc", "a");
6376 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6379 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6382 /*-----------------------------------------------------------------*/
6383 /* genlshFour - shift four byte by a known amount != 0 */
6384 /*-----------------------------------------------------------------*/
6386 genlshFour (operand * result, operand * left, int shCount)
6390 D(emitcode ("; genlshFour",""));
6392 size = AOP_SIZE (result);
6394 /* if shifting more that 3 bytes */
6399 /* lowest order of left goes to the highest
6400 order of the destination */
6401 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6403 movLeft2Result (left, LSB, result, MSB32, 0);
6404 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6405 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6406 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6410 /* more than two bytes */
6411 else if (shCount >= 16)
6413 /* lower order two bytes goes to higher order two bytes */
6415 /* if some more remaining */
6417 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6420 movLeft2Result (left, MSB16, result, MSB32, 0);
6421 movLeft2Result (left, LSB, result, MSB24, 0);
6423 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6424 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6428 /* if more than 1 byte */
6429 else if (shCount >= 8)
6431 /* lower order three bytes goes to higher order three bytes */
6436 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6438 movLeft2Result (left, LSB, result, MSB16, 0);
6444 movLeft2Result (left, MSB24, result, MSB32, 0);
6445 movLeft2Result (left, MSB16, result, MSB24, 0);
6446 movLeft2Result (left, LSB, result, MSB16, 0);
6447 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6449 else if (shCount == 1)
6450 shiftLLong (left, result, MSB16);
6453 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6454 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6455 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6456 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6461 /* 1 <= shCount <= 7 */
6462 else if (shCount <= 2)
6464 shiftLLong (left, result, LSB);
6466 shiftLLong (result, result, LSB);
6468 /* 3 <= shCount <= 7, optimize */
6471 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6472 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6473 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6477 /*-----------------------------------------------------------------*/
6478 /* genLeftShiftLiteral - left shifting by known count */
6479 /*-----------------------------------------------------------------*/
6481 genLeftShiftLiteral (operand * left,
6486 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6489 D(emitcode ("; genLeftShiftLiteral",""));
6491 freeAsmop (right, NULL, ic, TRUE);
6493 aopOp (left, ic, FALSE);
6494 aopOp (result, ic, FALSE);
6496 size = getSize (operandType (result));
6499 emitcode ("; shift left ", "result %d, left %d", size,
6503 /* I suppose that the left size >= result size */
6508 movLeft2Result (left, size, result, size, 0);
6512 else if (shCount >= (size * 8))
6514 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6520 genlshOne (result, left, shCount);
6524 genlshTwo (result, left, shCount);
6528 genlshFour (result, left, shCount);
6531 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6532 "*** ack! mystery literal shift!\n");
6536 freeAsmop (left, NULL, ic, TRUE);
6537 freeAsmop (result, NULL, ic, TRUE);
6540 /*-----------------------------------------------------------------*/
6541 /* genLeftShift - generates code for left shifting */
6542 /*-----------------------------------------------------------------*/
6544 genLeftShift (iCode * ic)
6546 operand *left, *right, *result;
6549 symbol *tlbl, *tlbl1;
6551 D(emitcode ("; genLeftShift",""));
6553 right = IC_RIGHT (ic);
6554 left = IC_LEFT (ic);
6555 result = IC_RESULT (ic);
6557 aopOp (right, ic, FALSE);
6559 /* if the shift count is known then do it
6560 as efficiently as possible */
6561 if (AOP_TYPE (right) == AOP_LIT)
6563 genLeftShiftLiteral (left, right, result, ic);
6567 /* shift count is unknown then we have to form
6568 a loop get the loop count in B : Note: we take
6569 only the lower order byte since shifting
6570 more that 32 bits make no sense anyway, ( the
6571 largest size of an object can be only 32 bits ) */
6573 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6574 emitcode ("inc", "b");
6575 freeAsmop (right, NULL, ic, TRUE);
6576 aopOp (left, ic, FALSE);
6577 aopOp (result, ic, FALSE);
6579 /* now move the left to the result if they are not the
6581 if (!sameRegs (AOP (left), AOP (result)) &&
6582 AOP_SIZE (result) > 1)
6585 size = AOP_SIZE (result);
6589 l = aopGet (AOP (left), offset, FALSE, TRUE);
6590 if (*l == '@' && (IS_AOP_PREG (result)))
6593 emitcode ("mov", "a,%s", l);
6594 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6597 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6602 tlbl = newiTempLabel (NULL);
6603 size = AOP_SIZE (result);
6605 tlbl1 = newiTempLabel (NULL);
6607 /* if it is only one byte then */
6610 symbol *tlbl1 = newiTempLabel (NULL);
6612 l = aopGet (AOP (left), 0, FALSE, FALSE);
6614 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6615 emitcode ("", "%05d$:", tlbl->key + 100);
6616 emitcode ("add", "a,acc");
6617 emitcode ("", "%05d$:", tlbl1->key + 100);
6618 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6619 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6623 reAdjustPreg (AOP (result));
6625 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6626 emitcode ("", "%05d$:", tlbl->key + 100);
6627 l = aopGet (AOP (result), offset, FALSE, FALSE);
6629 emitcode ("add", "a,acc");
6630 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6633 l = aopGet (AOP (result), offset, FALSE, FALSE);
6635 emitcode ("rlc", "a");
6636 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6638 reAdjustPreg (AOP (result));
6640 emitcode ("", "%05d$:", tlbl1->key + 100);
6641 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6643 freeAsmop (left, NULL, ic, TRUE);
6644 freeAsmop (result, NULL, ic, TRUE);
6647 /*-----------------------------------------------------------------*/
6648 /* genrshOne - right shift a one byte quantity by known count */
6649 /*-----------------------------------------------------------------*/
6651 genrshOne (operand * result, operand * left,
6652 int shCount, int sign)
6654 D(emitcode ("; genrshOne",""));
6656 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6659 /*-----------------------------------------------------------------*/
6660 /* genrshTwo - right shift two bytes by known amount != 0 */
6661 /*-----------------------------------------------------------------*/
6663 genrshTwo (operand * result, operand * left,
6664 int shCount, int sign)
6666 D(emitcode ("; genrshTwo",""));
6668 /* if shCount >= 8 */
6673 shiftR1Left2Result (left, MSB16, result, LSB,
6676 movLeft2Result (left, MSB16, result, LSB, sign);
6677 addSign (result, MSB16, sign);
6680 /* 1 <= shCount <= 7 */
6682 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6685 /*-----------------------------------------------------------------*/
6686 /* shiftRLong - shift right one long from left to result */
6687 /* offl = LSB or MSB16 */
6688 /*-----------------------------------------------------------------*/
6690 shiftRLong (operand * left, int offl,
6691 operand * result, int sign)
6693 int isSameRegs=sameRegs(AOP(left),AOP(result));
6695 if (isSameRegs && offl>1) {
6696 // we are in big trouble, but this shouldn't happen
6697 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6700 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6705 emitcode ("rlc", "a");
6706 emitcode ("subb", "a,acc");
6708 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6710 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6711 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6714 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6719 emitcode ("clr", "c");
6721 emitcode ("mov", "c,acc.7");
6724 emitcode ("rrc", "a");
6726 if (isSameRegs && offl==MSB16) {
6727 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6729 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6730 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6733 emitcode ("rrc", "a");
6734 if (isSameRegs && offl==1) {
6735 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6737 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6738 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6740 emitcode ("rrc", "a");
6741 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6745 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6746 emitcode ("rrc", "a");
6747 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6751 /*-----------------------------------------------------------------*/
6752 /* genrshFour - shift four byte by a known amount != 0 */
6753 /*-----------------------------------------------------------------*/
6755 genrshFour (operand * result, operand * left,
6756 int shCount, int sign)
6758 D(emitcode ("; genrshFour",""));
6760 /* if shifting more that 3 bytes */
6765 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6767 movLeft2Result (left, MSB32, result, LSB, sign);
6768 addSign (result, MSB16, sign);
6770 else if (shCount >= 16)
6774 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6777 movLeft2Result (left, MSB24, result, LSB, 0);
6778 movLeft2Result (left, MSB32, result, MSB16, sign);
6780 addSign (result, MSB24, sign);
6782 else if (shCount >= 8)
6786 shiftRLong (left, MSB16, result, sign);
6787 else if (shCount == 0)
6789 movLeft2Result (left, MSB16, result, LSB, 0);
6790 movLeft2Result (left, MSB24, result, MSB16, 0);
6791 movLeft2Result (left, MSB32, result, MSB24, sign);
6792 addSign (result, MSB32, sign);
6796 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6797 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6798 /* the last shift is signed */
6799 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6800 addSign (result, MSB32, sign);
6804 { /* 1 <= shCount <= 7 */
6807 shiftRLong (left, LSB, result, sign);
6809 shiftRLong (result, LSB, result, sign);
6813 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6814 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6815 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6820 /*-----------------------------------------------------------------*/
6821 /* genRightShiftLiteral - right shifting by known count */
6822 /*-----------------------------------------------------------------*/
6824 genRightShiftLiteral (operand * left,
6830 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6833 D(emitcode ("; genRightShiftLiteral",""));
6835 freeAsmop (right, NULL, ic, TRUE);
6837 aopOp (left, ic, FALSE);
6838 aopOp (result, ic, FALSE);
6841 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6845 size = getDataSize (left);
6846 /* test the LEFT size !!! */
6848 /* I suppose that the left size >= result size */
6851 size = getDataSize (result);
6853 movLeft2Result (left, size, result, size, 0);
6856 else if (shCount >= (size * 8))
6859 /* get sign in acc.7 */
6860 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6862 addSign (result, LSB, sign);
6869 genrshOne (result, left, shCount, sign);
6873 genrshTwo (result, left, shCount, sign);
6877 genrshFour (result, left, shCount, sign);
6883 freeAsmop (left, NULL, ic, TRUE);
6884 freeAsmop (result, NULL, ic, TRUE);
6887 /*-----------------------------------------------------------------*/
6888 /* genSignedRightShift - right shift of signed number */
6889 /*-----------------------------------------------------------------*/
6891 genSignedRightShift (iCode * ic)
6893 operand *right, *left, *result;
6896 symbol *tlbl, *tlbl1;
6898 D(emitcode ("; genSignedRightShift",""));
6900 /* we do it the hard way put the shift count in b
6901 and loop thru preserving the sign */
6903 right = IC_RIGHT (ic);
6904 left = IC_LEFT (ic);
6905 result = IC_RESULT (ic);
6907 aopOp (right, ic, FALSE);
6910 if (AOP_TYPE (right) == AOP_LIT)
6912 genRightShiftLiteral (left, right, result, ic, 1);
6915 /* shift count is unknown then we have to form
6916 a loop get the loop count in B : Note: we take
6917 only the lower order byte since shifting
6918 more that 32 bits make no sense anyway, ( the
6919 largest size of an object can be only 32 bits ) */
6921 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6922 emitcode ("inc", "b");
6923 freeAsmop (right, NULL, ic, TRUE);
6924 aopOp (left, ic, FALSE);
6925 aopOp (result, ic, FALSE);
6927 /* now move the left to the result if they are not the
6929 if (!sameRegs (AOP (left), AOP (result)) &&
6930 AOP_SIZE (result) > 1)
6933 size = AOP_SIZE (result);
6937 l = aopGet (AOP (left), offset, FALSE, TRUE);
6938 if (*l == '@' && IS_AOP_PREG (result))
6941 emitcode ("mov", "a,%s", l);
6942 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6945 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6950 /* mov the highest order bit to OVR */
6951 tlbl = newiTempLabel (NULL);
6952 tlbl1 = newiTempLabel (NULL);
6954 size = AOP_SIZE (result);
6956 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6957 emitcode ("rlc", "a");
6958 emitcode ("mov", "ov,c");
6959 /* if it is only one byte then */
6962 l = aopGet (AOP (left), 0, FALSE, FALSE);
6964 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6965 emitcode ("", "%05d$:", tlbl->key + 100);
6966 emitcode ("mov", "c,ov");
6967 emitcode ("rrc", "a");
6968 emitcode ("", "%05d$:", tlbl1->key + 100);
6969 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6970 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6974 reAdjustPreg (AOP (result));
6975 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6976 emitcode ("", "%05d$:", tlbl->key + 100);
6977 emitcode ("mov", "c,ov");
6980 l = aopGet (AOP (result), offset, FALSE, FALSE);
6982 emitcode ("rrc", "a");
6983 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6985 reAdjustPreg (AOP (result));
6986 emitcode ("", "%05d$:", tlbl1->key + 100);
6987 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6990 freeAsmop (left, NULL, ic, TRUE);
6991 freeAsmop (result, NULL, ic, TRUE);
6994 /*-----------------------------------------------------------------*/
6995 /* genRightShift - generate code for right shifting */
6996 /*-----------------------------------------------------------------*/
6998 genRightShift (iCode * ic)
7000 operand *right, *left, *result;
7004 symbol *tlbl, *tlbl1;
7006 D(emitcode ("; genRightShift",""));
7008 /* if signed then we do it the hard way preserve the
7009 sign bit moving it inwards */
7010 retype = getSpec (operandType (IC_RESULT (ic)));
7012 if (!SPEC_USIGN (retype))
7014 genSignedRightShift (ic);
7018 /* signed & unsigned types are treated the same : i.e. the
7019 signed is NOT propagated inwards : quoting from the
7020 ANSI - standard : "for E1 >> E2, is equivalent to division
7021 by 2**E2 if unsigned or if it has a non-negative value,
7022 otherwise the result is implementation defined ", MY definition
7023 is that the sign does not get propagated */
7025 right = IC_RIGHT (ic);
7026 left = IC_LEFT (ic);
7027 result = IC_RESULT (ic);
7029 aopOp (right, ic, FALSE);
7031 /* if the shift count is known then do it
7032 as efficiently as possible */
7033 if (AOP_TYPE (right) == AOP_LIT)
7035 genRightShiftLiteral (left, right, result, ic, 0);
7039 /* shift count is unknown then we have to form
7040 a loop get the loop count in B : Note: we take
7041 only the lower order byte since shifting
7042 more that 32 bits make no sense anyway, ( the
7043 largest size of an object can be only 32 bits ) */
7045 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7046 emitcode ("inc", "b");
7047 freeAsmop (right, NULL, ic, TRUE);
7048 aopOp (left, ic, FALSE);
7049 aopOp (result, ic, FALSE);
7051 /* now move the left to the result if they are not the
7053 if (!sameRegs (AOP (left), AOP (result)) &&
7054 AOP_SIZE (result) > 1)
7057 size = AOP_SIZE (result);
7061 l = aopGet (AOP (left), offset, FALSE, TRUE);
7062 if (*l == '@' && IS_AOP_PREG (result))
7065 emitcode ("mov", "a,%s", l);
7066 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7069 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7074 tlbl = newiTempLabel (NULL);
7075 tlbl1 = newiTempLabel (NULL);
7076 size = AOP_SIZE (result);
7079 /* if it is only one byte then */
7082 l = aopGet (AOP (left), 0, FALSE, FALSE);
7084 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7085 emitcode ("", "%05d$:", tlbl->key + 100);
7087 emitcode ("rrc", "a");
7088 emitcode ("", "%05d$:", tlbl1->key + 100);
7089 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7090 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7094 reAdjustPreg (AOP (result));
7095 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7096 emitcode ("", "%05d$:", tlbl->key + 100);
7100 l = aopGet (AOP (result), offset, FALSE, FALSE);
7102 emitcode ("rrc", "a");
7103 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7105 reAdjustPreg (AOP (result));
7107 emitcode ("", "%05d$:", tlbl1->key + 100);
7108 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7111 freeAsmop (left, NULL, ic, TRUE);
7112 freeAsmop (result, NULL, ic, TRUE);
7115 /*-----------------------------------------------------------------*/
7116 /* emitPtrByteGet - emits code to get a byte into A through a */
7117 /* pointer register (R0, R1, or DPTR). The */
7118 /* original value of A can be preserved in B. */
7119 /*-----------------------------------------------------------------*/
7121 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7128 emitcode ("mov", "b,a");
7129 emitcode ("mov", "a,@%s", rname);
7134 emitcode ("mov", "b,a");
7135 emitcode ("movx", "a,@%s", rname);
7140 emitcode ("mov", "b,a");
7141 emitcode ("movx", "a,@dptr");
7146 emitcode ("mov", "b,a");
7147 emitcode ("clr", "a");
7148 emitcode ("movc", "a,@a+dptr");
7154 emitcode ("push", "b");
7155 emitcode ("push", "acc");
7157 emitcode ("lcall", "__gptrget");
7159 emitcode ("pop", "b");
7164 /*-----------------------------------------------------------------*/
7165 /* emitPtrByteSet - emits code to set a byte from src through a */
7166 /* pointer register (R0, R1, or DPTR). */
7167 /*-----------------------------------------------------------------*/
7169 emitPtrByteSet (char *rname, int p_type, char *src)
7178 emitcode ("mov", "@%s,a", rname);
7181 emitcode ("mov", "@%s,%s", rname, src);
7186 emitcode ("movx", "@%s,a", rname);
7191 emitcode ("movx", "@dptr,a");
7196 emitcode ("lcall", "__gptrput");
7201 /*-----------------------------------------------------------------*/
7202 /* genUnpackBits - generates code for unpacking bits */
7203 /*-----------------------------------------------------------------*/
7205 genUnpackBits (operand * result, char *rname, int ptype)
7207 int offset = 0; /* result byte offset */
7208 int rsize; /* result size */
7209 int rlen = 0; /* remaining bitfield length */
7210 sym_link *etype; /* bitfield type information */
7211 int blen; /* bitfield length */
7212 int bstr; /* bitfield starting bit within byte */
7214 D(emitcode ("; genUnpackBits",""));
7216 etype = getSpec (operandType (result));
7217 rsize = getSize (operandType (result));
7218 blen = SPEC_BLEN (etype);
7219 bstr = SPEC_BSTR (etype);
7221 /* If the bitfield length is less than a byte */
7224 emitPtrByteGet (rname, ptype, FALSE);
7226 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7227 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7231 /* Bit field did not fit in a byte. Copy all
7232 but the partial byte at the end. */
7233 for (rlen=blen;rlen>=8;rlen-=8)
7235 emitPtrByteGet (rname, ptype, FALSE);
7236 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7238 emitcode ("inc", "%s", rname);
7241 /* Handle the partial byte at the end */
7244 emitPtrByteGet (rname, ptype, FALSE);
7245 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7246 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7254 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7259 /*-----------------------------------------------------------------*/
7260 /* genDataPointerGet - generates code when ptr offset is known */
7261 /*-----------------------------------------------------------------*/
7263 genDataPointerGet (operand * left,
7269 int size, offset = 0;
7271 D(emitcode ("; genDataPointerGet",""));
7273 aopOp (result, ic, TRUE);
7275 /* get the string representation of the name */
7276 l = aopGet (AOP (left), 0, FALSE, TRUE);
7277 size = AOP_SIZE (result);
7281 sprintf (buffer, "(%s + %d)", l + 1, offset);
7283 sprintf (buffer, "%s", l + 1);
7284 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7287 freeAsmop (left, NULL, ic, TRUE);
7288 freeAsmop (result, NULL, ic, TRUE);
7291 /*-----------------------------------------------------------------*/
7292 /* genNearPointerGet - emitcode for near pointer fetch */
7293 /*-----------------------------------------------------------------*/
7295 genNearPointerGet (operand * left,
7303 sym_link *rtype, *retype;
7304 sym_link *ltype = operandType (left);
7307 D(emitcode ("; genNearPointerGet",""));
7309 rtype = operandType (result);
7310 retype = getSpec (rtype);
7312 aopOp (left, ic, FALSE);
7314 /* if left is rematerialisable and
7315 result is not bit variable type and
7316 the left is pointer to data space i.e
7317 lower 128 bytes of space */
7318 if (AOP_TYPE (left) == AOP_IMMD &&
7319 !IS_BITVAR (retype) &&
7320 DCL_TYPE (ltype) == POINTER)
7322 genDataPointerGet (left, result, ic);
7326 /* if the value is already in a pointer register
7327 then don't need anything more */
7328 if (!AOP_INPREG (AOP (left)))
7330 /* otherwise get a free pointer register */
7332 preg = getFreePtr (ic, &aop, FALSE);
7333 emitcode ("mov", "%s,%s",
7335 aopGet (AOP (left), 0, FALSE, TRUE));
7339 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7341 //aopOp (result, ic, FALSE);
7342 aopOp (result, ic, result?TRUE:FALSE);
7344 /* if bitfield then unpack the bits */
7345 if (IS_BITVAR (retype))
7346 genUnpackBits (result, rname, POINTER);
7349 /* we have can just get the values */
7350 int size = AOP_SIZE (result);
7355 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7358 emitcode ("mov", "a,@%s", rname);
7359 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7363 sprintf (buffer, "@%s", rname);
7364 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7368 emitcode ("inc", "%s", rname);
7372 /* now some housekeeping stuff */
7373 if (aop) /* we had to allocate for this iCode */
7375 if (pi) { /* post increment present */
7376 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7378 freeAsmop (NULL, aop, ic, TRUE);
7382 /* we did not allocate which means left
7383 already in a pointer register, then
7384 if size > 0 && this could be used again
7385 we have to point it back to where it
7387 if ((AOP_SIZE (result) > 1 &&
7388 !OP_SYMBOL (left)->remat &&
7389 (OP_SYMBOL (left)->liveTo > ic->seq ||
7393 int size = AOP_SIZE (result) - 1;
7395 emitcode ("dec", "%s", rname);
7400 freeAsmop (left, NULL, ic, TRUE);
7401 freeAsmop (result, NULL, ic, TRUE);
7402 if (pi) pi->generated = 1;
7405 /*-----------------------------------------------------------------*/
7406 /* genPagedPointerGet - emitcode for paged pointer fetch */
7407 /*-----------------------------------------------------------------*/
7409 genPagedPointerGet (operand * left,
7417 sym_link *rtype, *retype;
7419 D(emitcode ("; genPagedPointerGet",""));
7421 rtype = operandType (result);
7422 retype = getSpec (rtype);
7424 aopOp (left, ic, FALSE);
7426 /* if the value is already in a pointer register
7427 then don't need anything more */
7428 if (!AOP_INPREG (AOP (left)))
7430 /* otherwise get a free pointer register */
7432 preg = getFreePtr (ic, &aop, FALSE);
7433 emitcode ("mov", "%s,%s",
7435 aopGet (AOP (left), 0, FALSE, TRUE));
7439 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7441 aopOp (result, ic, FALSE);
7443 /* if bitfield then unpack the bits */
7444 if (IS_BITVAR (retype))
7445 genUnpackBits (result, rname, PPOINTER);
7448 /* we have can just get the values */
7449 int size = AOP_SIZE (result);
7455 emitcode ("movx", "a,@%s", rname);
7456 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7461 emitcode ("inc", "%s", rname);
7465 /* now some housekeeping stuff */
7466 if (aop) /* we had to allocate for this iCode */
7468 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7469 freeAsmop (NULL, aop, ic, TRUE);
7473 /* we did not allocate which means left
7474 already in a pointer register, then
7475 if size > 0 && this could be used again
7476 we have to point it back to where it
7478 if ((AOP_SIZE (result) > 1 &&
7479 !OP_SYMBOL (left)->remat &&
7480 (OP_SYMBOL (left)->liveTo > ic->seq ||
7484 int size = AOP_SIZE (result) - 1;
7486 emitcode ("dec", "%s", rname);
7491 freeAsmop (left, NULL, ic, TRUE);
7492 freeAsmop (result, NULL, ic, TRUE);
7493 if (pi) pi->generated = 1;
7497 /*-----------------------------------------------------------------*/
7498 /* genFarPointerGet - gget value from far space */
7499 /*-----------------------------------------------------------------*/
7501 genFarPointerGet (operand * left,
7502 operand * result, iCode * ic, iCode * pi)
7505 sym_link *retype = getSpec (operandType (result));
7507 D(emitcode ("; genFarPointerGet",""));
7509 aopOp (left, ic, FALSE);
7511 /* if the operand is already in dptr
7512 then we do nothing else we move the value to dptr */
7513 if (AOP_TYPE (left) != AOP_STR)
7515 /* if this is remateriazable */
7516 if (AOP_TYPE (left) == AOP_IMMD)
7517 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7519 { /* we need to get it byte by byte */
7520 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7521 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7524 /* so dptr know contains the address */
7525 aopOp (result, ic, FALSE);
7527 /* if bit then unpack */
7528 if (IS_BITVAR (retype))
7529 genUnpackBits (result, "dptr", FPOINTER);
7532 size = AOP_SIZE (result);
7537 emitcode ("movx", "a,@dptr");
7538 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7540 emitcode ("inc", "dptr");
7544 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7545 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7546 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7549 freeAsmop (left, NULL, ic, TRUE);
7550 freeAsmop (result, NULL, ic, TRUE);
7553 /*-----------------------------------------------------------------*/
7554 /* genCodePointerGet - gget value from code space */
7555 /*-----------------------------------------------------------------*/
7557 genCodePointerGet (operand * left,
7558 operand * result, iCode * ic, iCode *pi)
7561 sym_link *retype = getSpec (operandType (result));
7563 D(emitcode ("; genCodePointerGet",""));
7565 aopOp (left, ic, FALSE);
7567 /* if the operand is already in dptr
7568 then we do nothing else we move the value to dptr */
7569 if (AOP_TYPE (left) != AOP_STR)
7571 /* if this is remateriazable */
7572 if (AOP_TYPE (left) == AOP_IMMD)
7573 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7575 { /* we need to get it byte by byte */
7576 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7577 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7580 /* so dptr know contains the address */
7581 aopOp (result, ic, FALSE);
7583 /* if bit then unpack */
7584 if (IS_BITVAR (retype))
7585 genUnpackBits (result, "dptr", CPOINTER);
7588 size = AOP_SIZE (result);
7595 emitcode ("clr", "a");
7596 emitcode ("movc", "a,@a+dptr");
7597 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7598 emitcode ("inc", "dptr");
7602 emitcode ("mov", "a,#0x%02x", offset);
7603 emitcode ("movc", "a,@a+dptr");
7604 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7609 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7610 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7611 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7614 freeAsmop (left, NULL, ic, TRUE);
7615 freeAsmop (result, NULL, ic, TRUE);
7618 /*-----------------------------------------------------------------*/
7619 /* genGenPointerGet - gget value from generic pointer space */
7620 /*-----------------------------------------------------------------*/
7622 genGenPointerGet (operand * left,
7623 operand * result, iCode * ic, iCode *pi)
7626 sym_link *retype = getSpec (operandType (result));
7628 D(emitcode ("; genGenPointerGet",""));
7630 aopOp (left, ic, FALSE);
7632 /* if the operand is already in dptr
7633 then we do nothing else we move the value to dptr */
7634 if (AOP_TYPE (left) != AOP_STR)
7636 /* if this is remateriazable */
7637 if (AOP_TYPE (left) == AOP_IMMD)
7639 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7640 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7641 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7643 emitcode ("mov", "b,#%d", pointerCode (retype));
7646 { /* we need to get it byte by byte */
7647 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7648 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7649 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7652 /* so dptr know contains the address */
7653 aopOp (result, ic, FALSE);
7655 /* if bit then unpack */
7656 if (IS_BITVAR (retype))
7657 genUnpackBits (result, "dptr", GPOINTER);
7660 size = AOP_SIZE (result);
7665 emitcode ("lcall", "__gptrget");
7666 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7668 emitcode ("inc", "dptr");
7672 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7673 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7674 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7677 freeAsmop (left, NULL, ic, TRUE);
7678 freeAsmop (result, NULL, ic, TRUE);
7681 /*-----------------------------------------------------------------*/
7682 /* genPointerGet - generate code for pointer get */
7683 /*-----------------------------------------------------------------*/
7685 genPointerGet (iCode * ic, iCode *pi)
7687 operand *left, *result;
7688 sym_link *type, *etype;
7691 D(emitcode ("; genPointerGet",""));
7693 left = IC_LEFT (ic);
7694 result = IC_RESULT (ic);
7696 /* depending on the type of pointer we need to
7697 move it to the correct pointer register */
7698 type = operandType (left);
7699 etype = getSpec (type);
7700 /* if left is of type of pointer then it is simple */
7701 if (IS_PTR (type) && !IS_FUNC (type->next))
7702 p_type = DCL_TYPE (type);
7705 /* we have to go by the storage class */
7706 p_type = PTR_TYPE (SPEC_OCLS (etype));
7709 /* special case when cast remat */
7710 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7711 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7712 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7713 type = operandType (left);
7714 p_type = DCL_TYPE (type);
7716 /* now that we have the pointer type we assign
7717 the pointer values */
7723 genNearPointerGet (left, result, ic, pi);
7727 genPagedPointerGet (left, result, ic, pi);
7731 genFarPointerGet (left, result, ic, pi);
7735 genCodePointerGet (left, result, ic, pi);
7739 genGenPointerGet (left, result, ic, pi);
7747 /*-----------------------------------------------------------------*/
7748 /* genPackBits - generates code for packed bit storage */
7749 /*-----------------------------------------------------------------*/
7751 genPackBits (sym_link * etype,
7753 char *rname, int p_type)
7755 int offset = 0; /* source byte offset */
7756 int rlen = 0; /* remaining bitfield length */
7757 int blen; /* bitfield length */
7758 int bstr; /* bitfield starting bit within byte */
7759 int litval; /* source literal value (if AOP_LIT) */
7760 unsigned char mask; /* bitmask within current byte */
7762 D(emitcode ("; genPackBits",""));
7764 blen = SPEC_BLEN (etype);
7765 bstr = SPEC_BSTR (etype);
7767 /* If the bitfield length is less than a byte */
7770 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7771 (unsigned char) (0xFF >> (8 - bstr)));
7773 if (AOP_TYPE (right) == AOP_LIT)
7775 /* Case with a bitfield length <8 and literal source
7777 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7779 litval &= (~mask) & 0xff;
7780 emitPtrByteGet (rname, p_type, FALSE);
7781 if ((mask|litval)!=0xff)
7782 emitcode ("anl","a,#0x%02x", mask);
7784 emitcode ("orl","a,#0x%02x", litval);
7788 if ((blen==1) && (p_type!=GPOINTER))
7790 /* Case with a bitfield length == 1 and no generic pointer
7792 if (AOP_TYPE (right) == AOP_CRY)
7793 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7796 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7797 emitcode ("rrc","a");
7799 emitPtrByteGet (rname, p_type, FALSE);
7800 emitcode ("mov","acc.%d,c",bstr);
7804 /* Case with a bitfield length < 8 and arbitrary source
7806 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7807 /* shift and mask source value */
7809 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7811 /* transfer A to B and get next byte */
7812 emitPtrByteGet (rname, p_type, TRUE);
7814 emitcode ("anl", "a,#0x%02x", mask);
7815 emitcode ("orl", "a,b");
7816 if (p_type == GPOINTER)
7817 emitcode ("pop", "b");
7821 emitPtrByteSet (rname, p_type, "a");
7825 /* Bit length is greater than 7 bits. In this case, copy */
7826 /* all except the partial byte at the end */
7827 for (rlen=blen;rlen>=8;rlen-=8)
7829 emitPtrByteSet (rname, p_type,
7830 aopGet (AOP (right), offset++, FALSE, FALSE) );
7832 emitcode ("inc", "%s", rname);
7835 /* If there was a partial byte at the end */
7838 mask = (((unsigned char) -1 << rlen) & 0xff);
7840 if (AOP_TYPE (right) == AOP_LIT)
7842 /* Case with partial byte and literal source
7844 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7845 litval >>= (blen-rlen);
7846 litval &= (~mask) & 0xff;
7847 emitPtrByteGet (rname, p_type, FALSE);
7848 if ((mask|litval)!=0xff)
7849 emitcode ("anl","a,#0x%02x", mask);
7851 emitcode ("orl","a,#0x%02x", litval);
7855 /* Case with partial byte and arbitrary source
7857 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
7858 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7860 /* transfer A to B and get next byte */
7861 emitPtrByteGet (rname, p_type, TRUE);
7863 emitcode ("anl", "a,#0x%02x", mask);
7864 emitcode ("orl", "a,b");
7865 if (p_type == GPOINTER)
7866 emitcode ("pop", "b");
7868 emitPtrByteSet (rname, p_type, "a");
7874 /*-----------------------------------------------------------------*/
7875 /* genDataPointerSet - remat pointer to data space */
7876 /*-----------------------------------------------------------------*/
7878 genDataPointerSet (operand * right,
7882 int size, offset = 0;
7883 char *l, buffer[256];
7885 D(emitcode ("; genDataPointerSet",""));
7887 aopOp (right, ic, FALSE);
7889 l = aopGet (AOP (result), 0, FALSE, TRUE);
7890 size = AOP_SIZE (right);
7894 sprintf (buffer, "(%s + %d)", l + 1, offset);
7896 sprintf (buffer, "%s", l + 1);
7897 emitcode ("mov", "%s,%s", buffer,
7898 aopGet (AOP (right), offset++, FALSE, FALSE));
7901 freeAsmop (right, NULL, ic, TRUE);
7902 freeAsmop (result, NULL, ic, TRUE);
7905 /*-----------------------------------------------------------------*/
7906 /* genNearPointerSet - emitcode for near pointer put */
7907 /*-----------------------------------------------------------------*/
7909 genNearPointerSet (operand * right,
7917 sym_link *retype, *letype;
7918 sym_link *ptype = operandType (result);
7920 D(emitcode ("; genNearPointerSet",""));
7922 retype = getSpec (operandType (right));
7923 letype = getSpec (ptype);
7924 aopOp (result, ic, FALSE);
7926 /* if the result is rematerializable &
7927 in data space & not a bit variable */
7928 if (AOP_TYPE (result) == AOP_IMMD &&
7929 DCL_TYPE (ptype) == POINTER &&
7930 !IS_BITVAR (retype) &&
7931 !IS_BITVAR (letype))
7933 genDataPointerSet (right, result, ic);
7937 /* if the value is already in a pointer register
7938 then don't need anything more */
7939 if (!AOP_INPREG (AOP (result)))
7942 //AOP_TYPE (result) == AOP_STK
7946 // Aha, it is a pointer, just in disguise.
7947 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7950 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7951 __FILE__, __LINE__);
7956 rname++; // skip the '@'.
7961 /* otherwise get a free pointer register */
7963 preg = getFreePtr (ic, &aop, FALSE);
7964 emitcode ("mov", "%s,%s",
7966 aopGet (AOP (result), 0, FALSE, TRUE));
7972 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7975 aopOp (right, ic, FALSE);
7977 /* if bitfield then unpack the bits */
7978 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7979 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7982 /* we have can just get the values */
7983 int size = AOP_SIZE (right);
7988 l = aopGet (AOP (right), offset, FALSE, TRUE);
7992 emitcode ("mov", "@%s,a", rname);
7995 emitcode ("mov", "@%s,%s", rname, l);
7997 emitcode ("inc", "%s", rname);
8002 /* now some housekeeping stuff */
8003 if (aop) /* we had to allocate for this iCode */
8006 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8007 freeAsmop (NULL, aop, ic, TRUE);
8011 /* we did not allocate which means left
8012 already in a pointer register, then
8013 if size > 0 && this could be used again
8014 we have to point it back to where it
8016 if ((AOP_SIZE (right) > 1 &&
8017 !OP_SYMBOL (result)->remat &&
8018 (OP_SYMBOL (result)->liveTo > ic->seq ||
8022 int size = AOP_SIZE (right) - 1;
8024 emitcode ("dec", "%s", rname);
8029 if (pi) pi->generated = 1;
8030 freeAsmop (result, NULL, ic, TRUE);
8031 freeAsmop (right, NULL, ic, TRUE);
8034 /*-----------------------------------------------------------------*/
8035 /* genPagedPointerSet - emitcode for Paged pointer put */
8036 /*-----------------------------------------------------------------*/
8038 genPagedPointerSet (operand * right,
8046 sym_link *retype, *letype;
8048 D(emitcode ("; genPagedPointerSet",""));
8050 retype = getSpec (operandType (right));
8051 letype = getSpec (operandType (result));
8053 aopOp (result, ic, FALSE);
8055 /* if the value is already in a pointer register
8056 then don't need anything more */
8057 if (!AOP_INPREG (AOP (result)))
8059 /* otherwise get a free pointer register */
8061 preg = getFreePtr (ic, &aop, FALSE);
8062 emitcode ("mov", "%s,%s",
8064 aopGet (AOP (result), 0, FALSE, TRUE));
8068 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8070 aopOp (right, ic, FALSE);
8072 /* if bitfield then unpack the bits */
8073 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8074 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8077 /* we have can just get the values */
8078 int size = AOP_SIZE (right);
8083 l = aopGet (AOP (right), offset, FALSE, TRUE);
8086 emitcode ("movx", "@%s,a", rname);
8089 emitcode ("inc", "%s", rname);
8095 /* now some housekeeping stuff */
8096 if (aop) /* we had to allocate for this iCode */
8099 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8100 freeAsmop (NULL, aop, ic, TRUE);
8104 /* we did not allocate which means left
8105 already in a pointer register, then
8106 if size > 0 && this could be used again
8107 we have to point it back to where it
8109 if (AOP_SIZE (right) > 1 &&
8110 !OP_SYMBOL (result)->remat &&
8111 (OP_SYMBOL (result)->liveTo > ic->seq ||
8114 int size = AOP_SIZE (right) - 1;
8116 emitcode ("dec", "%s", rname);
8121 if (pi) pi->generated = 1;
8122 freeAsmop (result, NULL, ic, TRUE);
8123 freeAsmop (right, NULL, ic, TRUE);
8128 /*-----------------------------------------------------------------*/
8129 /* genFarPointerSet - set value from far space */
8130 /*-----------------------------------------------------------------*/
8132 genFarPointerSet (operand * right,
8133 operand * result, iCode * ic, iCode * pi)
8136 sym_link *retype = getSpec (operandType (right));
8137 sym_link *letype = getSpec (operandType (result));
8139 D(emitcode ("; genFarPointerSet",""));
8141 aopOp (result, ic, FALSE);
8143 /* if the operand is already in dptr
8144 then we do nothing else we move the value to dptr */
8145 if (AOP_TYPE (result) != AOP_STR)
8147 /* if this is remateriazable */
8148 if (AOP_TYPE (result) == AOP_IMMD)
8149 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8151 { /* we need to get it byte by byte */
8152 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8153 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8156 /* so dptr know contains the address */
8157 aopOp (right, ic, FALSE);
8159 /* if bit then unpack */
8160 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8161 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8164 size = AOP_SIZE (right);
8169 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8171 emitcode ("movx", "@dptr,a");
8173 emitcode ("inc", "dptr");
8176 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8177 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8178 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8181 freeAsmop (result, NULL, ic, TRUE);
8182 freeAsmop (right, NULL, ic, TRUE);
8185 /*-----------------------------------------------------------------*/
8186 /* genGenPointerSet - set value from generic pointer space */
8187 /*-----------------------------------------------------------------*/
8189 genGenPointerSet (operand * right,
8190 operand * result, iCode * ic, iCode * pi)
8193 sym_link *retype = getSpec (operandType (right));
8194 sym_link *letype = getSpec (operandType (result));
8196 D(emitcode ("; genGenPointerSet",""));
8198 aopOp (result, ic, FALSE);
8200 /* if the operand is already in dptr
8201 then we do nothing else we move the value to dptr */
8202 if (AOP_TYPE (result) != AOP_STR)
8204 /* if this is remateriazable */
8205 if (AOP_TYPE (result) == AOP_IMMD)
8207 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8208 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8209 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8211 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8214 { /* we need to get it byte by byte */
8215 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8216 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8217 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8220 /* so dptr know contains the address */
8221 aopOp (right, ic, FALSE);
8223 /* if bit then unpack */
8224 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8225 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8228 size = AOP_SIZE (right);
8233 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8235 emitcode ("lcall", "__gptrput");
8237 emitcode ("inc", "dptr");
8241 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8242 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8243 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8246 freeAsmop (result, NULL, ic, TRUE);
8247 freeAsmop (right, NULL, ic, TRUE);
8250 /*-----------------------------------------------------------------*/
8251 /* genPointerSet - stores the value into a pointer location */
8252 /*-----------------------------------------------------------------*/
8254 genPointerSet (iCode * ic, iCode *pi)
8256 operand *right, *result;
8257 sym_link *type, *etype;
8260 D(emitcode ("; genPointerSet",""));
8262 right = IC_RIGHT (ic);
8263 result = IC_RESULT (ic);
8265 /* depending on the type of pointer we need to
8266 move it to the correct pointer register */
8267 type = operandType (result);
8268 etype = getSpec (type);
8269 /* if left is of type of pointer then it is simple */
8270 if (IS_PTR (type) && !IS_FUNC (type->next))
8272 p_type = DCL_TYPE (type);
8276 /* we have to go by the storage class */
8277 p_type = PTR_TYPE (SPEC_OCLS (etype));
8280 /* special case when cast remat */
8281 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8282 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8283 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8284 type = operandType (result);
8285 p_type = DCL_TYPE (type);
8287 /* now that we have the pointer type we assign
8288 the pointer values */
8294 genNearPointerSet (right, result, ic, pi);
8298 genPagedPointerSet (right, result, ic, pi);
8302 genFarPointerSet (right, result, ic, pi);
8306 genGenPointerSet (right, result, ic, pi);
8310 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8311 "genPointerSet: illegal pointer type");
8316 /*-----------------------------------------------------------------*/
8317 /* genIfx - generate code for Ifx statement */
8318 /*-----------------------------------------------------------------*/
8320 genIfx (iCode * ic, iCode * popIc)
8322 operand *cond = IC_COND (ic);
8325 D(emitcode ("; genIfx",""));
8327 aopOp (cond, ic, FALSE);
8329 /* get the value into acc */
8330 if (AOP_TYPE (cond) != AOP_CRY)
8334 /* the result is now in the accumulator */
8335 freeAsmop (cond, NULL, ic, TRUE);
8337 /* if there was something to be popped then do it */
8341 /* if the condition is a bit variable */
8342 if (isbit && IS_ITEMP (cond) &&
8344 genIfxJump (ic, SPIL_LOC (cond)->rname);
8345 else if (isbit && !IS_ITEMP (cond))
8346 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8348 genIfxJump (ic, "a");
8353 /*-----------------------------------------------------------------*/
8354 /* genAddrOf - generates code for address of */
8355 /*-----------------------------------------------------------------*/
8357 genAddrOf (iCode * ic)
8359 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8362 D(emitcode ("; genAddrOf",""));
8364 aopOp (IC_RESULT (ic), ic, FALSE);
8366 /* if the operand is on the stack then we
8367 need to get the stack offset of this
8371 /* if it has an offset then we need to compute
8375 emitcode ("mov", "a,_bp");
8376 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8377 ((char) (sym->stack - _G.nRegsSaved)) :
8378 ((char) sym->stack)) & 0xff);
8379 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8383 /* we can just move _bp */
8384 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8386 /* fill the result with zero */
8387 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8392 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8398 /* object not on stack then we need the name */
8399 size = AOP_SIZE (IC_RESULT (ic));
8404 char s[SDCC_NAME_MAX];
8406 sprintf (s, "#(%s >> %d)",
8410 sprintf (s, "#%s", sym->rname);
8411 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8415 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8419 /*-----------------------------------------------------------------*/
8420 /* genFarFarAssign - assignment when both are in far space */
8421 /*-----------------------------------------------------------------*/
8423 genFarFarAssign (operand * result, operand * right, iCode * ic)
8425 int size = AOP_SIZE (right);
8429 D(emitcode ("; genFarFarAssign",""));
8431 /* first push the right side on to the stack */
8434 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8436 emitcode ("push", "acc");
8439 freeAsmop (right, NULL, ic, FALSE);
8440 /* now assign DPTR to result */
8441 aopOp (result, ic, FALSE);
8442 size = AOP_SIZE (result);
8445 emitcode ("pop", "acc");
8446 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8448 freeAsmop (result, NULL, ic, FALSE);
8452 /*-----------------------------------------------------------------*/
8453 /* genAssign - generate code for assignment */
8454 /*-----------------------------------------------------------------*/
8456 genAssign (iCode * ic)
8458 operand *result, *right;
8460 unsigned long lit = 0L;
8462 D(emitcode("; genAssign",""));
8464 result = IC_RESULT (ic);
8465 right = IC_RIGHT (ic);
8467 /* if they are the same */
8468 if (operandsEqu (result, right) &&
8469 !isOperandVolatile (result, FALSE) &&
8470 !isOperandVolatile (right, FALSE))
8473 aopOp (right, ic, FALSE);
8475 /* special case both in far space */
8476 if (AOP_TYPE (right) == AOP_DPTR &&
8477 IS_TRUE_SYMOP (result) &&
8478 isOperandInFarSpace (result))
8481 genFarFarAssign (result, right, ic);
8485 aopOp (result, ic, TRUE);
8487 /* if they are the same registers */
8488 if (sameRegs (AOP (right), AOP (result)) &&
8489 !isOperandVolatile (result, FALSE) &&
8490 !isOperandVolatile (right, FALSE))
8493 /* if the result is a bit */
8494 if (AOP_TYPE (result) == AOP_CRY)
8497 /* if the right size is a literal then
8498 we know what the value is */
8499 if (AOP_TYPE (right) == AOP_LIT)
8501 if (((int) operandLitValue (right)))
8502 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8504 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8508 /* the right is also a bit variable */
8509 if (AOP_TYPE (right) == AOP_CRY)
8511 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8512 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8518 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8522 /* bit variables done */
8524 size = AOP_SIZE (result);
8526 if (AOP_TYPE (right) == AOP_LIT)
8527 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8529 (AOP_TYPE (result) != AOP_REG) &&
8530 (AOP_TYPE (right) == AOP_LIT) &&
8531 !IS_FLOAT (operandType (right)) &&
8534 emitcode ("clr", "a");
8537 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8538 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8540 aopPut (AOP (result),
8541 aopGet (AOP (right), size, FALSE, FALSE),
8543 isOperandVolatile (result, FALSE));
8550 aopPut (AOP (result),
8551 aopGet (AOP (right), offset, FALSE, FALSE),
8553 isOperandVolatile (result, FALSE));
8559 freeAsmop (right, NULL, ic, TRUE);
8560 freeAsmop (result, NULL, ic, TRUE);
8563 /*-----------------------------------------------------------------*/
8564 /* genJumpTab - genrates code for jump table */
8565 /*-----------------------------------------------------------------*/
8567 genJumpTab (iCode * ic)
8572 D(emitcode ("; genJumpTab",""));
8574 aopOp (IC_JTCOND (ic), ic, FALSE);
8575 /* get the condition into accumulator */
8576 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8578 /* multiply by three */
8579 emitcode ("add", "a,acc");
8580 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8581 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8583 jtab = newiTempLabel (NULL);
8584 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8585 emitcode ("jmp", "@a+dptr");
8586 emitcode ("", "%05d$:", jtab->key + 100);
8587 /* now generate the jump labels */
8588 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8589 jtab = setNextItem (IC_JTLABELS (ic)))
8590 emitcode ("ljmp", "%05d$", jtab->key + 100);
8594 /*-----------------------------------------------------------------*/
8595 /* genCast - gen code for casting */
8596 /*-----------------------------------------------------------------*/
8598 genCast (iCode * ic)
8600 operand *result = IC_RESULT (ic);
8601 sym_link *ctype = operandType (IC_LEFT (ic));
8602 sym_link *rtype = operandType (IC_RIGHT (ic));
8603 operand *right = IC_RIGHT (ic);
8606 D(emitcode("; genCast",""));
8608 /* if they are equivalent then do nothing */
8609 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8612 aopOp (right, ic, FALSE);
8613 aopOp (result, ic, FALSE);
8615 /* if the result is a bit (and not a bitfield) */
8616 if (AOP_TYPE (result) == AOP_CRY)
8618 /* if the right size is a literal then
8619 we know what the value is */
8620 if (AOP_TYPE (right) == AOP_LIT)
8622 if (((int) operandLitValue (right)))
8623 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8625 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8630 /* the right is also a bit variable */
8631 if (AOP_TYPE (right) == AOP_CRY)
8633 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8634 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8640 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8645 /* if they are the same size : or less */
8646 if (AOP_SIZE (result) <= AOP_SIZE (right))
8649 /* if they are in the same place */
8650 if (sameRegs (AOP (right), AOP (result)))
8653 /* if they in different places then copy */
8654 size = AOP_SIZE (result);
8658 aopPut (AOP (result),
8659 aopGet (AOP (right), offset, FALSE, FALSE),
8661 isOperandVolatile (result, FALSE));
8668 /* if the result is of type pointer */
8673 sym_link *type = operandType (right);
8674 sym_link *etype = getSpec (type);
8676 /* pointer to generic pointer */
8677 if (IS_GENPTR (ctype))
8680 p_type = DCL_TYPE (type);
8683 if (SPEC_SCLS(etype)==S_REGISTER) {
8684 // let's assume it is a generic pointer
8687 /* we have to go by the storage class */
8688 p_type = PTR_TYPE (SPEC_OCLS (etype));
8692 /* the first two bytes are known */
8693 size = GPTRSIZE - 1;
8697 aopPut (AOP (result),
8698 aopGet (AOP (right), offset, FALSE, FALSE),
8700 isOperandVolatile (result, FALSE));
8703 /* the last byte depending on type */
8705 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8710 // pointerTypeToGPByte will have bitched.
8714 sprintf(gpValStr, "#0x%d", gpVal);
8715 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8720 /* just copy the pointers */
8721 size = AOP_SIZE (result);
8725 aopPut (AOP (result),
8726 aopGet (AOP (right), offset, FALSE, FALSE),
8728 isOperandVolatile (result, FALSE));
8734 /* so we now know that the size of destination is greater
8735 than the size of the source */
8736 /* we move to result for the size of source */
8737 size = AOP_SIZE (right);
8741 aopPut (AOP (result),
8742 aopGet (AOP (right), offset, FALSE, FALSE),
8744 isOperandVolatile (result, FALSE));
8748 /* now depending on the sign of the source && destination */
8749 size = AOP_SIZE (result) - AOP_SIZE (right);
8750 /* if unsigned or not an integral type */
8751 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8754 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8758 /* we need to extend the sign :{ */
8759 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8762 emitcode ("rlc", "a");
8763 emitcode ("subb", "a,acc");
8765 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8768 /* we are done hurray !!!! */
8771 freeAsmop (right, NULL, ic, TRUE);
8772 freeAsmop (result, NULL, ic, TRUE);
8776 /*-----------------------------------------------------------------*/
8777 /* genDjnz - generate decrement & jump if not zero instrucion */
8778 /*-----------------------------------------------------------------*/
8780 genDjnz (iCode * ic, iCode * ifx)
8786 D(emitcode ("; genDjnz",""));
8788 /* if the if condition has a false label
8789 then we cannot save */
8793 /* if the minus is not of the form
8795 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8796 !IS_OP_LITERAL (IC_RIGHT (ic)))
8799 if (operandLitValue (IC_RIGHT (ic)) != 1)
8802 /* if the size of this greater than one then no
8804 if (getSize (operandType (IC_RESULT (ic))) > 1)
8807 /* otherwise we can save BIG */
8808 lbl = newiTempLabel (NULL);
8809 lbl1 = newiTempLabel (NULL);
8811 aopOp (IC_RESULT (ic), ic, FALSE);
8813 if (AOP_NEEDSACC(IC_RESULT(ic)))
8815 /* If the result is accessed indirectly via
8816 * the accumulator, we must explicitly write
8817 * it back after the decrement.
8819 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8821 if (strcmp(rByte, "a"))
8823 /* Something is hopelessly wrong */
8824 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8825 __FILE__, __LINE__);
8826 /* We can just give up; the generated code will be inefficient,
8829 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8832 emitcode ("dec", "%s", rByte);
8833 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8834 emitcode ("jnz", "%05d$", lbl->key + 100);
8836 else if (IS_AOP_PREG (IC_RESULT (ic)))
8838 emitcode ("dec", "%s",
8839 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8840 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8841 emitcode ("jnz", "%05d$", lbl->key + 100);
8845 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8848 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8849 emitcode ("", "%05d$:", lbl->key + 100);
8850 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8851 emitcode ("", "%05d$:", lbl1->key + 100);
8853 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8858 /*-----------------------------------------------------------------*/
8859 /* genReceive - generate code for a receive iCode */
8860 /*-----------------------------------------------------------------*/
8862 genReceive (iCode * ic)
8864 int size = getSize (operandType (IC_RESULT (ic)));
8866 D(emitcode ("; genReceive",""));
8868 if (ic->argreg == 1) { /* first parameter */
8869 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8870 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8871 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8873 offset = fReturnSizeMCS51 - size;
8875 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8876 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8879 aopOp (IC_RESULT (ic), ic, FALSE);
8880 size = AOP_SIZE (IC_RESULT (ic));
8883 emitcode ("pop", "acc");
8884 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8889 aopOp (IC_RESULT (ic), ic, FALSE);
8891 assignResultValue (IC_RESULT (ic));
8893 } else { /* second receive onwards */
8895 aopOp (IC_RESULT (ic), ic, FALSE);
8896 rb1off = ic->argreg;
8898 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8901 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8904 /*-----------------------------------------------------------------*/
8905 /* genDummyRead - generate code for dummy read of volatiles */
8906 /*-----------------------------------------------------------------*/
8908 genDummyRead (iCode * ic)
8913 D(emitcode("; genDummyRead",""));
8915 right = IC_RIGHT (ic);
8917 aopOp (right, ic, FALSE);
8919 /* if the result is a bit */
8920 if (AOP_TYPE (right) == AOP_CRY)
8922 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8926 /* bit variables done */
8928 size = AOP_SIZE (right);
8932 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
8937 freeAsmop (right, NULL, ic, TRUE);
8940 /*-----------------------------------------------------------------*/
8941 /* gen51Code - generate code for 8051 based controllers */
8942 /*-----------------------------------------------------------------*/
8944 gen51Code (iCode * lic)
8949 lineHead = lineCurr = NULL;
8951 /* print the allocation information */
8952 if (allocInfo && currFunc)
8953 printAllocInfo (currFunc, codeOutFile);
8954 /* if debug information required */
8955 if (options.debug && currFunc)
8957 debugFile->writeFunction(currFunc);
8959 if (IS_STATIC (currFunc->etype))
8960 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8962 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8965 /* stack pointer name */
8966 if (options.useXstack)
8972 for (ic = lic; ic; ic = ic->next)
8975 if (ic->lineno && cln != ic->lineno)
8980 emitcode ("", "C$%s$%d$%d$%d ==.",
8981 FileBaseName (ic->filename), ic->lineno,
8982 ic->level, ic->block);
8985 if (!options.noCcodeInAsm) {
8986 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8987 printCLine(ic->filename, ic->lineno));
8991 if (options.iCodeInAsm) {
8995 for (i=0; i<8; i++) {
8996 sprintf (®sInUse[i],
8997 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9000 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9002 /* if the result is marked as
9003 spilt and rematerializable or code for
9004 this has already been generated then
9006 if (resultRemat (ic) || ic->generated)
9009 /* depending on the operation */
9029 /* IPOP happens only when trying to restore a
9030 spilt live range, if there is an ifx statement
9031 following this pop then the if statement might
9032 be using some of the registers being popped which
9033 would destory the contents of the register so
9034 we need to check for this condition and handle it */
9036 ic->next->op == IFX &&
9037 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9038 genIfx (ic->next, ic);
9056 genEndFunction (ic);
9076 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9093 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9097 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9104 /* note these two are xlated by algebraic equivalence
9105 during parsing SDCC.y */
9106 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9107 "got '>=' or '<=' shouldn't have come here");
9111 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9123 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9127 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9131 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9158 case GET_VALUE_AT_ADDRESS:
9159 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9163 if (POINTER_SET (ic))
9164 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9190 addSet (&_G.sendSet, ic);
9193 case DUMMY_READ_VOLATILE:
9203 /* now we are ready to call the
9204 peep hole optimizer */
9205 if (!options.nopeep)
9206 peepHole (&lineHead);
9208 /* now do the actual printing */
9209 printLine (lineHead, codeOutFile);