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 /* genUnpackBits - generates code for unpacking bits */
7117 /*-----------------------------------------------------------------*/
7119 genUnpackBits (operand * result, char *rname, int ptype)
7127 D(emitcode ("; genUnpackBits",""));
7129 etype = getSpec (operandType (result));
7130 rsize = getSize (operandType (result));
7131 /* read the first byte */
7137 emitcode ("mov", "a,@%s", rname);
7141 emitcode ("movx", "a,@%s", rname);
7145 emitcode ("movx", "a,@dptr");
7149 emitcode ("clr", "a");
7150 emitcode ("movc", "a,@a+dptr");
7154 emitcode ("lcall", "__gptrget");
7158 rlen = SPEC_BLEN (etype);
7160 /* if we have bitdisplacement then it fits */
7161 /* into this byte completely or if length is */
7162 /* less than a byte */
7163 if ((shCnt = SPEC_BSTR (etype)) ||
7164 (SPEC_BLEN (etype) <= 8))
7167 /* shift right acc */
7170 emitcode ("anl", "a,#0x%02x",
7171 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
7172 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7176 /* bit field did not fit in a byte */
7177 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7186 emitcode ("inc", "%s", rname);
7187 emitcode ("mov", "a,@%s", rname);
7191 emitcode ("inc", "%s", rname);
7192 emitcode ("movx", "a,@%s", rname);
7196 emitcode ("inc", "dptr");
7197 emitcode ("movx", "a,@dptr");
7201 emitcode ("clr", "a");
7202 emitcode ("inc", "dptr");
7203 emitcode ("movc", "a,@a+dptr");
7207 emitcode ("inc", "dptr");
7208 emitcode ("lcall", "__gptrget");
7213 /* if we are done */
7217 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7223 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7224 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7232 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7237 /*-----------------------------------------------------------------*/
7238 /* genDataPointerGet - generates code when ptr offset is known */
7239 /*-----------------------------------------------------------------*/
7241 genDataPointerGet (operand * left,
7247 int size, offset = 0;
7249 D(emitcode ("; genDataPointerGet",""));
7251 aopOp (result, ic, TRUE);
7253 /* get the string representation of the name */
7254 l = aopGet (AOP (left), 0, FALSE, TRUE);
7255 size = AOP_SIZE (result);
7259 sprintf (buffer, "(%s + %d)", l + 1, offset);
7261 sprintf (buffer, "%s", l + 1);
7262 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7265 freeAsmop (left, NULL, ic, TRUE);
7266 freeAsmop (result, NULL, ic, TRUE);
7269 /*-----------------------------------------------------------------*/
7270 /* genNearPointerGet - emitcode for near pointer fetch */
7271 /*-----------------------------------------------------------------*/
7273 genNearPointerGet (operand * left,
7281 sym_link *rtype, *retype;
7282 sym_link *ltype = operandType (left);
7285 D(emitcode ("; genNearPointerGet",""));
7287 rtype = operandType (result);
7288 retype = getSpec (rtype);
7290 aopOp (left, ic, FALSE);
7292 /* if left is rematerialisable and
7293 result is not bit variable type and
7294 the left is pointer to data space i.e
7295 lower 128 bytes of space */
7296 if (AOP_TYPE (left) == AOP_IMMD &&
7297 !IS_BITVAR (retype) &&
7298 DCL_TYPE (ltype) == POINTER)
7300 genDataPointerGet (left, result, ic);
7304 /* if the value is already in a pointer register
7305 then don't need anything more */
7306 if (!AOP_INPREG (AOP (left)))
7308 /* otherwise get a free pointer register */
7310 preg = getFreePtr (ic, &aop, FALSE);
7311 emitcode ("mov", "%s,%s",
7313 aopGet (AOP (left), 0, FALSE, TRUE));
7317 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7319 //aopOp (result, ic, FALSE);
7320 aopOp (result, ic, result?TRUE:FALSE);
7322 /* if bitfield then unpack the bits */
7323 if (IS_BITVAR (retype))
7324 genUnpackBits (result, rname, POINTER);
7327 /* we have can just get the values */
7328 int size = AOP_SIZE (result);
7333 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7336 emitcode ("mov", "a,@%s", rname);
7337 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7341 sprintf (buffer, "@%s", rname);
7342 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7346 emitcode ("inc", "%s", rname);
7350 /* now some housekeeping stuff */
7351 if (aop) /* we had to allocate for this iCode */
7353 if (pi) { /* post increment present */
7354 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7356 freeAsmop (NULL, aop, ic, TRUE);
7360 /* we did not allocate which means left
7361 already in a pointer register, then
7362 if size > 0 && this could be used again
7363 we have to point it back to where it
7365 if ((AOP_SIZE (result) > 1 &&
7366 !OP_SYMBOL (left)->remat &&
7367 (OP_SYMBOL (left)->liveTo > ic->seq ||
7371 int size = AOP_SIZE (result) - 1;
7373 emitcode ("dec", "%s", rname);
7378 freeAsmop (left, NULL, ic, TRUE);
7379 freeAsmop (result, NULL, ic, TRUE);
7380 if (pi) pi->generated = 1;
7383 /*-----------------------------------------------------------------*/
7384 /* genPagedPointerGet - emitcode for paged pointer fetch */
7385 /*-----------------------------------------------------------------*/
7387 genPagedPointerGet (operand * left,
7395 sym_link *rtype, *retype;
7397 D(emitcode ("; genPagedPointerGet",""));
7399 rtype = operandType (result);
7400 retype = getSpec (rtype);
7402 aopOp (left, ic, FALSE);
7404 /* if the value is already in a pointer register
7405 then don't need anything more */
7406 if (!AOP_INPREG (AOP (left)))
7408 /* otherwise get a free pointer register */
7410 preg = getFreePtr (ic, &aop, FALSE);
7411 emitcode ("mov", "%s,%s",
7413 aopGet (AOP (left), 0, FALSE, TRUE));
7417 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7419 aopOp (result, ic, FALSE);
7421 /* if bitfield then unpack the bits */
7422 if (IS_BITVAR (retype))
7423 genUnpackBits (result, rname, PPOINTER);
7426 /* we have can just get the values */
7427 int size = AOP_SIZE (result);
7433 emitcode ("movx", "a,@%s", rname);
7434 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7439 emitcode ("inc", "%s", rname);
7443 /* now some housekeeping stuff */
7444 if (aop) /* we had to allocate for this iCode */
7446 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7447 freeAsmop (NULL, aop, ic, TRUE);
7451 /* we did not allocate which means left
7452 already in a pointer register, then
7453 if size > 0 && this could be used again
7454 we have to point it back to where it
7456 if ((AOP_SIZE (result) > 1 &&
7457 !OP_SYMBOL (left)->remat &&
7458 (OP_SYMBOL (left)->liveTo > ic->seq ||
7462 int size = AOP_SIZE (result) - 1;
7464 emitcode ("dec", "%s", rname);
7469 freeAsmop (left, NULL, ic, TRUE);
7470 freeAsmop (result, NULL, ic, TRUE);
7471 if (pi) pi->generated = 1;
7475 /*-----------------------------------------------------------------*/
7476 /* genFarPointerGet - gget value from far space */
7477 /*-----------------------------------------------------------------*/
7479 genFarPointerGet (operand * left,
7480 operand * result, iCode * ic, iCode * pi)
7483 sym_link *retype = getSpec (operandType (result));
7485 D(emitcode ("; genFarPointerGet",""));
7487 aopOp (left, ic, FALSE);
7489 /* if the operand is already in dptr
7490 then we do nothing else we move the value to dptr */
7491 if (AOP_TYPE (left) != AOP_STR)
7493 /* if this is remateriazable */
7494 if (AOP_TYPE (left) == AOP_IMMD)
7495 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7497 { /* we need to get it byte by byte */
7498 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7499 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7502 /* so dptr know contains the address */
7503 aopOp (result, ic, FALSE);
7505 /* if bit then unpack */
7506 if (IS_BITVAR (retype))
7507 genUnpackBits (result, "dptr", FPOINTER);
7510 size = AOP_SIZE (result);
7515 emitcode ("movx", "a,@dptr");
7516 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7518 emitcode ("inc", "dptr");
7522 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7523 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7524 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7527 freeAsmop (left, NULL, ic, TRUE);
7528 freeAsmop (result, NULL, ic, TRUE);
7531 /*-----------------------------------------------------------------*/
7532 /* genCodePointerGet - gget value from code space */
7533 /*-----------------------------------------------------------------*/
7535 genCodePointerGet (operand * left,
7536 operand * result, iCode * ic, iCode *pi)
7539 sym_link *retype = getSpec (operandType (result));
7541 D(emitcode ("; genCodePointerGet",""));
7543 aopOp (left, ic, FALSE);
7545 /* if the operand is already in dptr
7546 then we do nothing else we move the value to dptr */
7547 if (AOP_TYPE (left) != AOP_STR)
7549 /* if this is remateriazable */
7550 if (AOP_TYPE (left) == AOP_IMMD)
7551 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7553 { /* we need to get it byte by byte */
7554 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7555 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7558 /* so dptr know contains the address */
7559 aopOp (result, ic, FALSE);
7561 /* if bit then unpack */
7562 if (IS_BITVAR (retype))
7563 genUnpackBits (result, "dptr", CPOINTER);
7566 size = AOP_SIZE (result);
7573 emitcode ("clr", "a");
7574 emitcode ("movc", "a,@a+dptr");
7575 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7576 emitcode ("inc", "dptr");
7580 emitcode ("mov", "a,#0x%02x", offset);
7581 emitcode ("movc", "a,@a+dptr");
7582 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7587 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7588 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7589 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7592 freeAsmop (left, NULL, ic, TRUE);
7593 freeAsmop (result, NULL, ic, TRUE);
7596 /*-----------------------------------------------------------------*/
7597 /* genGenPointerGet - gget value from generic pointer space */
7598 /*-----------------------------------------------------------------*/
7600 genGenPointerGet (operand * left,
7601 operand * result, iCode * ic, iCode *pi)
7604 sym_link *retype = getSpec (operandType (result));
7606 D(emitcode ("; genGenPointerGet",""));
7608 aopOp (left, ic, FALSE);
7610 /* if the operand is already in dptr
7611 then we do nothing else we move the value to dptr */
7612 if (AOP_TYPE (left) != AOP_STR)
7614 /* if this is remateriazable */
7615 if (AOP_TYPE (left) == AOP_IMMD)
7617 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7618 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7619 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7621 emitcode ("mov", "b,#%d", pointerCode (retype));
7624 { /* we need to get it byte by byte */
7625 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7626 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7627 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7630 /* so dptr know contains the address */
7631 aopOp (result, ic, FALSE);
7633 /* if bit then unpack */
7634 if (IS_BITVAR (retype))
7635 genUnpackBits (result, "dptr", GPOINTER);
7638 size = AOP_SIZE (result);
7643 emitcode ("lcall", "__gptrget");
7644 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7646 emitcode ("inc", "dptr");
7650 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7651 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7652 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7655 freeAsmop (left, NULL, ic, TRUE);
7656 freeAsmop (result, NULL, ic, TRUE);
7659 /*-----------------------------------------------------------------*/
7660 /* genPointerGet - generate code for pointer get */
7661 /*-----------------------------------------------------------------*/
7663 genPointerGet (iCode * ic, iCode *pi)
7665 operand *left, *result;
7666 sym_link *type, *etype;
7669 D(emitcode ("; genPointerGet",""));
7671 left = IC_LEFT (ic);
7672 result = IC_RESULT (ic);
7674 /* depending on the type of pointer we need to
7675 move it to the correct pointer register */
7676 type = operandType (left);
7677 etype = getSpec (type);
7678 /* if left is of type of pointer then it is simple */
7679 if (IS_PTR (type) && !IS_FUNC (type->next))
7680 p_type = DCL_TYPE (type);
7683 /* we have to go by the storage class */
7684 p_type = PTR_TYPE (SPEC_OCLS (etype));
7687 /* special case when cast remat */
7688 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7689 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7690 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7691 type = operandType (left);
7692 p_type = DCL_TYPE (type);
7694 /* now that we have the pointer type we assign
7695 the pointer values */
7701 genNearPointerGet (left, result, ic, pi);
7705 genPagedPointerGet (left, result, ic, pi);
7709 genFarPointerGet (left, result, ic, pi);
7713 genCodePointerGet (left, result, ic, pi);
7717 genGenPointerGet (left, result, ic, pi);
7723 /*-----------------------------------------------------------------*/
7724 /* genPackBits - generates code for packed bit storage */
7725 /*-----------------------------------------------------------------*/
7727 genPackBits (sym_link * etype,
7729 char *rname, int p_type)
7737 D(emitcode ("; genPackBits",""));
7739 blen = SPEC_BLEN (etype);
7740 bstr = SPEC_BSTR (etype);
7742 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7745 /* if the bit lenth is less than or */
7746 /* it exactly fits a byte then */
7747 if (SPEC_BLEN (etype) <= 8)
7749 unsigned char mask = ((unsigned char) (0xFF << (blen + bstr)) |
7750 (unsigned char) (0xFF >> (8 - bstr)));
7751 shCount = SPEC_BSTR (etype);
7753 /* shift left acc */
7756 if (SPEC_BLEN (etype) < 8)
7757 { /* if smaller than a byte */
7759 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7764 emitcode ("mov", "b,a");
7765 emitcode ("mov", "a,@%s", rname);
7769 emitcode ("mov", "b,a");
7770 emitcode ("movx", "a,@dptr");
7774 emitcode ("push", "b");
7775 emitcode ("push", "acc");
7776 emitcode ("lcall", "__gptrget");
7777 emitcode ("pop", "b");
7781 emitcode ("anl", "a,#0x%02x", mask);
7782 emitcode ("orl", "a,b");
7783 if (p_type == GPOINTER)
7784 emitcode ("pop", "b");
7791 emitcode ("mov", "@%s,a", rname);
7795 emitcode ("movx", "@dptr,a");
7799 emitcode ("lcall", "__gptrput");
7804 if (SPEC_BLEN (etype) <= 8)
7807 emitcode ("inc", "%s", rname);
7808 rLen = SPEC_BLEN (etype);
7810 /* now generate for lengths greater than one byte */
7814 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7826 emitcode ("mov", "@%s,a", rname);
7829 emitcode ("mov", "@%s,%s", rname, l);
7834 emitcode ("movx", "@dptr,a");
7839 emitcode ("lcall", "__gptrput");
7842 emitcode ("inc", "%s", rname);
7847 /* last last was not complete */
7850 emitcode ("anl", "a,#0x%02x",
7851 (~(((unsigned char) -1 << rLen) & 0xff)) &0xff);
7853 /* save the byte & read byte */
7857 emitcode ("mov", "b,a");
7858 emitcode ("mov", "a,@%s", rname);
7862 emitcode ("mov", "b,a");
7863 emitcode ("movx", "a,@dptr");
7867 emitcode ("push", "b");
7868 emitcode ("push", "acc");
7869 emitcode ("lcall", "__gptrget");
7870 emitcode ("pop", "b");
7874 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7875 emitcode ("orl", "a,b");
7878 if (p_type == GPOINTER)
7879 emitcode ("pop", "b");
7885 emitcode ("mov", "@%s,a", rname);
7889 emitcode ("movx", "@dptr,a");
7893 emitcode ("lcall", "__gptrput");
7897 /*-----------------------------------------------------------------*/
7898 /* genDataPointerSet - remat pointer to data space */
7899 /*-----------------------------------------------------------------*/
7901 genDataPointerSet (operand * right,
7905 int size, offset = 0;
7906 char *l, buffer[256];
7908 D(emitcode ("; genDataPointerSet",""));
7910 aopOp (right, ic, FALSE);
7912 l = aopGet (AOP (result), 0, FALSE, TRUE);
7913 size = AOP_SIZE (right);
7917 sprintf (buffer, "(%s + %d)", l + 1, offset);
7919 sprintf (buffer, "%s", l + 1);
7920 emitcode ("mov", "%s,%s", buffer,
7921 aopGet (AOP (right), offset++, FALSE, FALSE));
7924 freeAsmop (right, NULL, ic, TRUE);
7925 freeAsmop (result, NULL, ic, TRUE);
7928 /*-----------------------------------------------------------------*/
7929 /* genNearPointerSet - emitcode for near pointer put */
7930 /*-----------------------------------------------------------------*/
7932 genNearPointerSet (operand * right,
7940 sym_link *retype, *letype;
7941 sym_link *ptype = operandType (result);
7943 D(emitcode ("; genNearPointerSet",""));
7945 retype = getSpec (operandType (right));
7946 letype = getSpec (ptype);
7947 aopOp (result, ic, FALSE);
7949 /* if the result is rematerializable &
7950 in data space & not a bit variable */
7951 if (AOP_TYPE (result) == AOP_IMMD &&
7952 DCL_TYPE (ptype) == POINTER &&
7953 !IS_BITVAR (retype) &&
7954 !IS_BITVAR (letype))
7956 genDataPointerSet (right, result, ic);
7960 /* if the value is already in a pointer register
7961 then don't need anything more */
7962 if (!AOP_INPREG (AOP (result)))
7965 //AOP_TYPE (result) == AOP_STK
7969 // Aha, it is a pointer, just in disguise.
7970 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7973 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7974 __FILE__, __LINE__);
7979 rname++; // skip the '@'.
7984 /* otherwise get a free pointer register */
7986 preg = getFreePtr (ic, &aop, FALSE);
7987 emitcode ("mov", "%s,%s",
7989 aopGet (AOP (result), 0, FALSE, TRUE));
7995 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7998 aopOp (right, ic, FALSE);
8000 /* if bitfield then unpack the bits */
8001 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8002 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8005 /* we have can just get the values */
8006 int size = AOP_SIZE (right);
8011 l = aopGet (AOP (right), offset, FALSE, TRUE);
8015 emitcode ("mov", "@%s,a", rname);
8018 emitcode ("mov", "@%s,%s", rname, l);
8020 emitcode ("inc", "%s", rname);
8025 /* now some housekeeping stuff */
8026 if (aop) /* we had to allocate for this iCode */
8029 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8030 freeAsmop (NULL, aop, ic, TRUE);
8034 /* we did not allocate which means left
8035 already in a pointer register, then
8036 if size > 0 && this could be used again
8037 we have to point it back to where it
8039 if ((AOP_SIZE (right) > 1 &&
8040 !OP_SYMBOL (result)->remat &&
8041 (OP_SYMBOL (result)->liveTo > ic->seq ||
8045 int size = AOP_SIZE (right) - 1;
8047 emitcode ("dec", "%s", rname);
8052 if (pi) pi->generated = 1;
8053 freeAsmop (result, NULL, ic, TRUE);
8054 freeAsmop (right, NULL, ic, TRUE);
8057 /*-----------------------------------------------------------------*/
8058 /* genPagedPointerSet - emitcode for Paged pointer put */
8059 /*-----------------------------------------------------------------*/
8061 genPagedPointerSet (operand * right,
8069 sym_link *retype, *letype;
8071 D(emitcode ("; genPagedPointerSet",""));
8073 retype = getSpec (operandType (right));
8074 letype = getSpec (operandType (result));
8076 aopOp (result, ic, FALSE);
8078 /* if the value is already in a pointer register
8079 then don't need anything more */
8080 if (!AOP_INPREG (AOP (result)))
8082 /* otherwise get a free pointer register */
8084 preg = getFreePtr (ic, &aop, FALSE);
8085 emitcode ("mov", "%s,%s",
8087 aopGet (AOP (result), 0, FALSE, TRUE));
8091 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8093 aopOp (right, ic, FALSE);
8095 /* if bitfield then unpack the bits */
8096 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8097 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8100 /* we have can just get the values */
8101 int size = AOP_SIZE (right);
8106 l = aopGet (AOP (right), offset, FALSE, TRUE);
8109 emitcode ("movx", "@%s,a", rname);
8112 emitcode ("inc", "%s", rname);
8118 /* now some housekeeping stuff */
8119 if (aop) /* we had to allocate for this iCode */
8122 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8123 freeAsmop (NULL, aop, ic, TRUE);
8127 /* we did not allocate which means left
8128 already in a pointer register, then
8129 if size > 0 && this could be used again
8130 we have to point it back to where it
8132 if (AOP_SIZE (right) > 1 &&
8133 !OP_SYMBOL (result)->remat &&
8134 (OP_SYMBOL (result)->liveTo > ic->seq ||
8137 int size = AOP_SIZE (right) - 1;
8139 emitcode ("dec", "%s", rname);
8144 if (pi) pi->generated = 1;
8145 freeAsmop (result, NULL, ic, TRUE);
8146 freeAsmop (right, NULL, ic, TRUE);
8151 /*-----------------------------------------------------------------*/
8152 /* genFarPointerSet - set value from far space */
8153 /*-----------------------------------------------------------------*/
8155 genFarPointerSet (operand * right,
8156 operand * result, iCode * ic, iCode * pi)
8159 sym_link *retype = getSpec (operandType (right));
8160 sym_link *letype = getSpec (operandType (result));
8162 D(emitcode ("; genFarPointerSet",""));
8164 aopOp (result, ic, FALSE);
8166 /* if the operand is already in dptr
8167 then we do nothing else we move the value to dptr */
8168 if (AOP_TYPE (result) != AOP_STR)
8170 /* if this is remateriazable */
8171 if (AOP_TYPE (result) == AOP_IMMD)
8172 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8174 { /* we need to get it byte by byte */
8175 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8176 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8179 /* so dptr know contains the address */
8180 aopOp (right, ic, FALSE);
8182 /* if bit then unpack */
8183 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8184 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8187 size = AOP_SIZE (right);
8192 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8194 emitcode ("movx", "@dptr,a");
8196 emitcode ("inc", "dptr");
8199 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8200 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8201 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8204 freeAsmop (result, NULL, ic, TRUE);
8205 freeAsmop (right, NULL, ic, TRUE);
8208 /*-----------------------------------------------------------------*/
8209 /* genGenPointerSet - set value from generic pointer space */
8210 /*-----------------------------------------------------------------*/
8212 genGenPointerSet (operand * right,
8213 operand * result, iCode * ic, iCode * pi)
8216 sym_link *retype = getSpec (operandType (right));
8217 sym_link *letype = getSpec (operandType (result));
8219 D(emitcode ("; genGenPointerSet",""));
8221 aopOp (result, ic, FALSE);
8223 /* if the operand is already in dptr
8224 then we do nothing else we move the value to dptr */
8225 if (AOP_TYPE (result) != AOP_STR)
8227 /* if this is remateriazable */
8228 if (AOP_TYPE (result) == AOP_IMMD)
8230 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8231 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8232 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8234 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8237 { /* we need to get it byte by byte */
8238 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8239 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8240 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8243 /* so dptr know contains the address */
8244 aopOp (right, ic, FALSE);
8246 /* if bit then unpack */
8247 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8248 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8251 size = AOP_SIZE (right);
8256 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8258 emitcode ("lcall", "__gptrput");
8260 emitcode ("inc", "dptr");
8264 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8265 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8266 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8269 freeAsmop (result, NULL, ic, TRUE);
8270 freeAsmop (right, NULL, ic, TRUE);
8273 /*-----------------------------------------------------------------*/
8274 /* genPointerSet - stores the value into a pointer location */
8275 /*-----------------------------------------------------------------*/
8277 genPointerSet (iCode * ic, iCode *pi)
8279 operand *right, *result;
8280 sym_link *type, *etype;
8283 D(emitcode ("; genPointerSet",""));
8285 right = IC_RIGHT (ic);
8286 result = IC_RESULT (ic);
8288 /* depending on the type of pointer we need to
8289 move it to the correct pointer register */
8290 type = operandType (result);
8291 etype = getSpec (type);
8292 /* if left is of type of pointer then it is simple */
8293 if (IS_PTR (type) && !IS_FUNC (type->next))
8295 p_type = DCL_TYPE (type);
8299 /* we have to go by the storage class */
8300 p_type = PTR_TYPE (SPEC_OCLS (etype));
8303 /* special case when cast remat */
8304 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8305 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8306 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8307 type = operandType (result);
8308 p_type = DCL_TYPE (type);
8310 /* now that we have the pointer type we assign
8311 the pointer values */
8317 genNearPointerSet (right, result, ic, pi);
8321 genPagedPointerSet (right, result, ic, pi);
8325 genFarPointerSet (right, result, ic, pi);
8329 genGenPointerSet (right, result, ic, pi);
8333 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8334 "genPointerSet: illegal pointer type");
8339 /*-----------------------------------------------------------------*/
8340 /* genIfx - generate code for Ifx statement */
8341 /*-----------------------------------------------------------------*/
8343 genIfx (iCode * ic, iCode * popIc)
8345 operand *cond = IC_COND (ic);
8348 D(emitcode ("; genIfx",""));
8350 aopOp (cond, ic, FALSE);
8352 /* get the value into acc */
8353 if (AOP_TYPE (cond) != AOP_CRY)
8357 /* the result is now in the accumulator */
8358 freeAsmop (cond, NULL, ic, TRUE);
8360 /* if there was something to be popped then do it */
8364 /* if the condition is a bit variable */
8365 if (isbit && IS_ITEMP (cond) &&
8367 genIfxJump (ic, SPIL_LOC (cond)->rname);
8368 else if (isbit && !IS_ITEMP (cond))
8369 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8371 genIfxJump (ic, "a");
8376 /*-----------------------------------------------------------------*/
8377 /* genAddrOf - generates code for address of */
8378 /*-----------------------------------------------------------------*/
8380 genAddrOf (iCode * ic)
8382 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8385 D(emitcode ("; genAddrOf",""));
8387 aopOp (IC_RESULT (ic), ic, FALSE);
8389 /* if the operand is on the stack then we
8390 need to get the stack offset of this
8394 /* if it has an offset then we need to compute
8398 emitcode ("mov", "a,_bp");
8399 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8400 ((char) (sym->stack - _G.nRegsSaved)) :
8401 ((char) sym->stack)) & 0xff);
8402 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8406 /* we can just move _bp */
8407 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8409 /* fill the result with zero */
8410 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8415 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8421 /* object not on stack then we need the name */
8422 size = AOP_SIZE (IC_RESULT (ic));
8427 char s[SDCC_NAME_MAX];
8429 sprintf (s, "#(%s >> %d)",
8433 sprintf (s, "#%s", sym->rname);
8434 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8438 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8442 /*-----------------------------------------------------------------*/
8443 /* genFarFarAssign - assignment when both are in far space */
8444 /*-----------------------------------------------------------------*/
8446 genFarFarAssign (operand * result, operand * right, iCode * ic)
8448 int size = AOP_SIZE (right);
8452 D(emitcode ("; genFarFarAssign",""));
8454 /* first push the right side on to the stack */
8457 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8459 emitcode ("push", "acc");
8462 freeAsmop (right, NULL, ic, FALSE);
8463 /* now assign DPTR to result */
8464 aopOp (result, ic, FALSE);
8465 size = AOP_SIZE (result);
8468 emitcode ("pop", "acc");
8469 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8471 freeAsmop (result, NULL, ic, FALSE);
8475 /*-----------------------------------------------------------------*/
8476 /* genAssign - generate code for assignment */
8477 /*-----------------------------------------------------------------*/
8479 genAssign (iCode * ic)
8481 operand *result, *right;
8483 unsigned long lit = 0L;
8485 D(emitcode("; genAssign",""));
8487 result = IC_RESULT (ic);
8488 right = IC_RIGHT (ic);
8490 /* if they are the same */
8491 if (operandsEqu (result, right) &&
8492 !isOperandVolatile (result, FALSE) &&
8493 !isOperandVolatile (right, FALSE))
8496 aopOp (right, ic, FALSE);
8498 /* special case both in far space */
8499 if (AOP_TYPE (right) == AOP_DPTR &&
8500 IS_TRUE_SYMOP (result) &&
8501 isOperandInFarSpace (result))
8504 genFarFarAssign (result, right, ic);
8508 aopOp (result, ic, TRUE);
8510 /* if they are the same registers */
8511 if (sameRegs (AOP (right), AOP (result)) &&
8512 !isOperandVolatile (result, FALSE) &&
8513 !isOperandVolatile (right, FALSE))
8516 /* if the result is a bit */
8517 if (AOP_TYPE (result) == AOP_CRY)
8520 /* if the right size is a literal then
8521 we know what the value is */
8522 if (AOP_TYPE (right) == AOP_LIT)
8524 if (((int) operandLitValue (right)))
8525 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8527 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8531 /* the right is also a bit variable */
8532 if (AOP_TYPE (right) == AOP_CRY)
8534 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8535 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8541 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8545 /* bit variables done */
8547 size = AOP_SIZE (result);
8549 if (AOP_TYPE (right) == AOP_LIT)
8550 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8552 (AOP_TYPE (result) != AOP_REG) &&
8553 (AOP_TYPE (right) == AOP_LIT) &&
8554 !IS_FLOAT (operandType (right)) &&
8557 emitcode ("clr", "a");
8560 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8561 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8563 aopPut (AOP (result),
8564 aopGet (AOP (right), size, FALSE, FALSE),
8566 isOperandVolatile (result, FALSE));
8573 aopPut (AOP (result),
8574 aopGet (AOP (right), offset, FALSE, FALSE),
8576 isOperandVolatile (result, FALSE));
8582 freeAsmop (right, NULL, ic, TRUE);
8583 freeAsmop (result, NULL, ic, TRUE);
8586 /*-----------------------------------------------------------------*/
8587 /* genJumpTab - genrates code for jump table */
8588 /*-----------------------------------------------------------------*/
8590 genJumpTab (iCode * ic)
8595 D(emitcode ("; genJumpTab",""));
8597 aopOp (IC_JTCOND (ic), ic, FALSE);
8598 /* get the condition into accumulator */
8599 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8601 /* multiply by three */
8602 emitcode ("add", "a,acc");
8603 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8604 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8606 jtab = newiTempLabel (NULL);
8607 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8608 emitcode ("jmp", "@a+dptr");
8609 emitcode ("", "%05d$:", jtab->key + 100);
8610 /* now generate the jump labels */
8611 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8612 jtab = setNextItem (IC_JTLABELS (ic)))
8613 emitcode ("ljmp", "%05d$", jtab->key + 100);
8617 /*-----------------------------------------------------------------*/
8618 /* genCast - gen code for casting */
8619 /*-----------------------------------------------------------------*/
8621 genCast (iCode * ic)
8623 operand *result = IC_RESULT (ic);
8624 sym_link *ctype = operandType (IC_LEFT (ic));
8625 sym_link *rtype = operandType (IC_RIGHT (ic));
8626 operand *right = IC_RIGHT (ic);
8629 D(emitcode("; genCast",""));
8631 /* if they are equivalent then do nothing */
8632 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8635 aopOp (right, ic, FALSE);
8636 aopOp (result, ic, FALSE);
8638 /* if the result is a bit (and not a bitfield) */
8639 if (AOP_TYPE (result) == AOP_CRY)
8641 /* if the right size is a literal then
8642 we know what the value is */
8643 if (AOP_TYPE (right) == AOP_LIT)
8645 if (((int) operandLitValue (right)))
8646 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8648 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8653 /* the right is also a bit variable */
8654 if (AOP_TYPE (right) == AOP_CRY)
8656 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8657 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8663 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8668 /* if they are the same size : or less */
8669 if (AOP_SIZE (result) <= AOP_SIZE (right))
8672 /* if they are in the same place */
8673 if (sameRegs (AOP (right), AOP (result)))
8676 /* if they in different places then copy */
8677 size = AOP_SIZE (result);
8681 aopPut (AOP (result),
8682 aopGet (AOP (right), offset, FALSE, FALSE),
8684 isOperandVolatile (result, FALSE));
8691 /* if the result is of type pointer */
8696 sym_link *type = operandType (right);
8697 sym_link *etype = getSpec (type);
8699 /* pointer to generic pointer */
8700 if (IS_GENPTR (ctype))
8703 p_type = DCL_TYPE (type);
8706 if (SPEC_SCLS(etype)==S_REGISTER) {
8707 // let's assume it is a generic pointer
8710 /* we have to go by the storage class */
8711 p_type = PTR_TYPE (SPEC_OCLS (etype));
8715 /* the first two bytes are known */
8716 size = GPTRSIZE - 1;
8720 aopPut (AOP (result),
8721 aopGet (AOP (right), offset, FALSE, FALSE),
8723 isOperandVolatile (result, FALSE));
8726 /* the last byte depending on type */
8728 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8733 // pointerTypeToGPByte will have bitched.
8737 sprintf(gpValStr, "#0x%d", gpVal);
8738 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8743 /* just copy the pointers */
8744 size = AOP_SIZE (result);
8748 aopPut (AOP (result),
8749 aopGet (AOP (right), offset, FALSE, FALSE),
8751 isOperandVolatile (result, FALSE));
8757 /* so we now know that the size of destination is greater
8758 than the size of the source */
8759 /* we move to result for the size of source */
8760 size = AOP_SIZE (right);
8764 aopPut (AOP (result),
8765 aopGet (AOP (right), offset, FALSE, FALSE),
8767 isOperandVolatile (result, FALSE));
8771 /* now depending on the sign of the source && destination */
8772 size = AOP_SIZE (result) - AOP_SIZE (right);
8773 /* if unsigned or not an integral type */
8774 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8777 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8781 /* we need to extend the sign :{ */
8782 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8785 emitcode ("rlc", "a");
8786 emitcode ("subb", "a,acc");
8788 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8791 /* we are done hurray !!!! */
8794 freeAsmop (right, NULL, ic, TRUE);
8795 freeAsmop (result, NULL, ic, TRUE);
8799 /*-----------------------------------------------------------------*/
8800 /* genDjnz - generate decrement & jump if not zero instrucion */
8801 /*-----------------------------------------------------------------*/
8803 genDjnz (iCode * ic, iCode * ifx)
8809 D(emitcode ("; genDjnz",""));
8811 /* if the if condition has a false label
8812 then we cannot save */
8816 /* if the minus is not of the form
8818 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8819 !IS_OP_LITERAL (IC_RIGHT (ic)))
8822 if (operandLitValue (IC_RIGHT (ic)) != 1)
8825 /* if the size of this greater than one then no
8827 if (getSize (operandType (IC_RESULT (ic))) > 1)
8830 /* otherwise we can save BIG */
8831 lbl = newiTempLabel (NULL);
8832 lbl1 = newiTempLabel (NULL);
8834 aopOp (IC_RESULT (ic), ic, FALSE);
8836 if (AOP_NEEDSACC(IC_RESULT(ic)))
8838 /* If the result is accessed indirectly via
8839 * the accumulator, we must explicitly write
8840 * it back after the decrement.
8842 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8844 if (strcmp(rByte, "a"))
8846 /* Something is hopelessly wrong */
8847 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8848 __FILE__, __LINE__);
8849 /* We can just give up; the generated code will be inefficient,
8852 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8855 emitcode ("dec", "%s", rByte);
8856 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8857 emitcode ("jnz", "%05d$", lbl->key + 100);
8859 else if (IS_AOP_PREG (IC_RESULT (ic)))
8861 emitcode ("dec", "%s",
8862 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8863 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8864 emitcode ("jnz", "%05d$", lbl->key + 100);
8868 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8871 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8872 emitcode ("", "%05d$:", lbl->key + 100);
8873 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8874 emitcode ("", "%05d$:", lbl1->key + 100);
8876 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8881 /*-----------------------------------------------------------------*/
8882 /* genReceive - generate code for a receive iCode */
8883 /*-----------------------------------------------------------------*/
8885 genReceive (iCode * ic)
8887 int size = getSize (operandType (IC_RESULT (ic)));
8889 D(emitcode ("; genReceive",""));
8891 if (ic->argreg == 1) { /* first parameter */
8892 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8893 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8894 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8896 offset = fReturnSizeMCS51 - size;
8898 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8899 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8902 aopOp (IC_RESULT (ic), ic, FALSE);
8903 size = AOP_SIZE (IC_RESULT (ic));
8906 emitcode ("pop", "acc");
8907 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8912 aopOp (IC_RESULT (ic), ic, FALSE);
8914 assignResultValue (IC_RESULT (ic));
8916 } else { /* second receive onwards */
8918 aopOp (IC_RESULT (ic), ic, FALSE);
8919 rb1off = ic->argreg;
8921 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8924 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8927 /*-----------------------------------------------------------------*/
8928 /* genDummyRead - generate code for dummy read of volatiles */
8929 /*-----------------------------------------------------------------*/
8931 genDummyRead (iCode * ic)
8936 D(emitcode("; genDummyRead",""));
8938 right = IC_RIGHT (ic);
8940 aopOp (right, ic, FALSE);
8942 /* if the result is a bit */
8943 if (AOP_TYPE (right) == AOP_CRY)
8945 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8949 /* bit variables done */
8951 size = AOP_SIZE (right);
8955 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
8960 freeAsmop (right, NULL, ic, TRUE);
8963 /*-----------------------------------------------------------------*/
8964 /* gen51Code - generate code for 8051 based controllers */
8965 /*-----------------------------------------------------------------*/
8967 gen51Code (iCode * lic)
8972 lineHead = lineCurr = NULL;
8974 /* print the allocation information */
8975 if (allocInfo && currFunc)
8976 printAllocInfo (currFunc, codeOutFile);
8977 /* if debug information required */
8978 if (options.debug && currFunc)
8980 debugFile->writeFunction(currFunc);
8982 if (IS_STATIC (currFunc->etype))
8983 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8985 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8988 /* stack pointer name */
8989 if (options.useXstack)
8995 for (ic = lic; ic; ic = ic->next)
8998 if (ic->lineno && cln != ic->lineno)
9003 emitcode ("", "C$%s$%d$%d$%d ==.",
9004 FileBaseName (ic->filename), ic->lineno,
9005 ic->level, ic->block);
9008 if (!options.noCcodeInAsm) {
9009 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9010 printCLine(ic->filename, ic->lineno));
9014 if (options.iCodeInAsm) {
9018 for (i=0; i<8; i++) {
9019 sprintf (®sInUse[i],
9020 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9023 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9025 /* if the result is marked as
9026 spilt and rematerializable or code for
9027 this has already been generated then
9029 if (resultRemat (ic) || ic->generated)
9032 /* depending on the operation */
9052 /* IPOP happens only when trying to restore a
9053 spilt live range, if there is an ifx statement
9054 following this pop then the if statement might
9055 be using some of the registers being popped which
9056 would destory the contents of the register so
9057 we need to check for this condition and handle it */
9059 ic->next->op == IFX &&
9060 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9061 genIfx (ic->next, ic);
9079 genEndFunction (ic);
9099 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9116 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9120 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9127 /* note these two are xlated by algebraic equivalence
9128 during parsing SDCC.y */
9129 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9130 "got '>=' or '<=' shouldn't have come here");
9134 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9146 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9150 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9154 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9181 case GET_VALUE_AT_ADDRESS:
9182 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9186 if (POINTER_SET (ic))
9187 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9213 addSet (&_G.sendSet, ic);
9216 case DUMMY_READ_VOLATILE:
9226 /* now we are ready to call the
9227 peep hole optimizer */
9228 if (!options.nopeep)
9229 peepHole (&lineHead);
9231 /* now do the actual printing */
9232 printLine (lineHead, codeOutFile);