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;
80 static char *rb1regs[] = {
81 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
84 extern int mcs51_ptrRegReq;
85 extern int mcs51_nRegs;
86 extern FILE *codeOutFile;
87 static void saveRBank (int, iCode *, bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
93 #define CLRC emitcode("clr","c")
94 #define SETC emitcode("setb","c")
96 static lineNode *lineHead = NULL;
97 static lineNode *lineCurr = NULL;
99 static unsigned char SLMask[] =
100 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
101 0xE0, 0xC0, 0x80, 0x00};
102 static unsigned char SRMask[] =
103 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
104 0x07, 0x03, 0x01, 0x00};
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple */
113 /*-----------------------------------------------------------------*/
115 emitcode (char *inst, const char *fmt,...)
118 char lb[INITIAL_INLINEASM];
126 sprintf (lb, "%s\t", inst);
128 sprintf (lb, "%s", inst);
129 vsprintf (lb + (strlen (lb)), fmt, ap);
132 vsprintf (lb, fmt, ap);
134 while (isspace (*lbp))
138 lineCurr = (lineCurr ?
139 connectLine (lineCurr, newLineNode (lb)) :
140 (lineHead = newLineNode (lb)));
141 lineCurr->isInline = _G.inLine;
142 lineCurr->isDebug = _G.debugLine;
143 lineCurr->ic = _G.current_iCode;
144 lineCurr->isComment = (*lbp==';');
148 /*-----------------------------------------------------------------*/
149 /* mova - moves specified value into accumulator */
150 /*-----------------------------------------------------------------*/
154 /* do some early peephole optimization */
155 if (!strcmp(x, "a") || !strcmp(x, "acc"))
158 emitcode("mov","a,%s", x);
161 /*-----------------------------------------------------------------*/
162 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
163 /*-----------------------------------------------------------------*/
165 getFreePtr (iCode * ic, asmop ** aopp, bool result)
167 bool r0iu = FALSE, r1iu = FALSE;
168 bool r0ou = FALSE, r1ou = FALSE;
170 /* the logic: if r0 & r1 used in the instruction
171 then we are in trouble otherwise */
173 /* first check if r0 & r1 are used by this
174 instruction, in which case we are in trouble */
175 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
176 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
181 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
182 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
184 /* if no usage of r0 then return it */
187 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
188 (*aopp)->type = AOP_R0;
190 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
193 /* if no usage of r1 then return it */
196 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
197 (*aopp)->type = AOP_R1;
199 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
202 /* now we know they both have usage */
203 /* if r0 not used in this instruction */
206 /* push it if not already pushed */
209 emitcode ("push", "%s",
210 mcs51_regWithIdx (R0_IDX)->dname);
214 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
215 (*aopp)->type = AOP_R0;
217 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
220 /* if r1 not used then */
224 /* push it if not already pushed */
227 emitcode ("push", "%s",
228 mcs51_regWithIdx (R1_IDX)->dname);
232 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
233 (*aopp)->type = AOP_R1;
234 return mcs51_regWithIdx (R1_IDX);
237 /* I said end of world, but not quite end of world yet */
239 /* we can push it on the stack */
240 (*aopp)->type = AOP_STK;
243 /* in the case that result AND left AND right needs a pointer reg
244 we can safely use the result's */
245 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
246 (*aopp)->type = AOP_R0;
247 return mcs51_regWithIdx (R0_IDX);
249 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
250 (*aopp)->type = AOP_R1;
251 return mcs51_regWithIdx (R1_IDX);
255 /* now this is REALLY the end of the world */
256 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
257 "getFreePtr should never reach here");
261 /*-----------------------------------------------------------------*/
262 /* newAsmop - creates a new asmOp */
263 /*-----------------------------------------------------------------*/
265 newAsmop (short type)
269 aop = Safe_calloc (1, sizeof (asmop));
274 /*-----------------------------------------------------------------*/
275 /* pointerCode - returns the code for a pointer type */
276 /*-----------------------------------------------------------------*/
278 pointerCode (sym_link * etype)
281 return PTR_TYPE (SPEC_OCLS (etype));
286 /*-----------------------------------------------------------------*/
287 /* leftRightUseAcc - returns size of accumulator use by operands */
288 /*-----------------------------------------------------------------*/
290 leftRightUseAcc(iCode *ic)
299 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
300 "null iCode pointer");
307 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
310 size = getSize (OP_SYMBOL (op)->type);
315 else if (ic->op == JUMPTABLE)
318 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
321 size = getSize (OP_SYMBOL (op)->type);
329 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
332 size = getSize (OP_SYMBOL (op)->type);
337 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
340 size = getSize (OP_SYMBOL (op)->type);
353 /*-----------------------------------------------------------------*/
354 /* aopForSym - for a true symbol */
355 /*-----------------------------------------------------------------*/
357 aopForSym (iCode * ic, symbol * sym, bool result)
362 wassertl (ic != NULL, "Got a null iCode");
363 wassertl (sym != NULL, "Got a null symbol");
365 space = SPEC_OCLS (sym->etype);
367 /* if already has one */
371 /* assign depending on the storage class */
372 /* if it is on the stack or indirectly addressable */
373 /* space we need to assign either r0 or r1 to it */
374 if (sym->onStack || sym->iaccess)
376 sym->aop = aop = newAsmop (0);
377 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
378 aop->size = getSize (sym->type);
380 /* now assign the address of the variable to
381 the pointer register */
382 if (aop->type != AOP_STK)
387 if (_G.accInUse || leftRightUseAcc (ic))
388 emitcode ("push", "acc");
390 emitcode ("mov", "a,_bp");
391 emitcode ("add", "a,#0x%02x",
393 ((char) (sym->stack - _G.nRegsSaved)) :
394 ((char) sym->stack)) & 0xff);
395 emitcode ("mov", "%s,a",
396 aop->aopu.aop_ptr->name);
398 if (_G.accInUse || leftRightUseAcc (ic))
399 emitcode ("pop", "acc");
402 emitcode ("mov", "%s,#%s",
403 aop->aopu.aop_ptr->name,
405 aop->paged = space->paged;
408 aop->aopu.aop_stk = sym->stack;
412 /* if in bit space */
413 if (IN_BITSPACE (space))
415 sym->aop = aop = newAsmop (AOP_CRY);
416 aop->aopu.aop_dir = sym->rname;
417 aop->size = getSize (sym->type);
420 /* if it is in direct space */
421 if (IN_DIRSPACE (space))
423 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
424 //printTypeChainRaw(sym->type, NULL);
425 //printf("space = %s\n", space ? space->sname : "NULL");
426 sym->aop = aop = newAsmop (AOP_DIR);
427 aop->aopu.aop_dir = sym->rname;
428 aop->size = getSize (sym->type);
432 /* special case for a function */
433 if (IS_FUNC (sym->type))
435 sym->aop = aop = newAsmop (AOP_IMMD);
436 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
437 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
438 aop->size = FPTRSIZE;
442 /* only remaining is far space */
443 /* in which case DPTR gets the address */
444 sym->aop = aop = newAsmop (AOP_DPTR);
445 emitcode ("mov", "dptr,#%s", sym->rname);
446 aop->size = getSize (sym->type);
448 /* if it is in code space */
449 if (IN_CODESPACE (space))
455 /*-----------------------------------------------------------------*/
456 /* aopForRemat - rematerialzes an object */
457 /*-----------------------------------------------------------------*/
459 aopForRemat (symbol * sym)
461 iCode *ic = sym->rematiCode;
462 asmop *aop = newAsmop (AOP_IMMD);
469 val += (int) operandLitValue (IC_RIGHT (ic));
470 else if (ic->op == '-')
471 val -= (int) operandLitValue (IC_RIGHT (ic));
472 else if (IS_CAST_ICODE(ic)) {
473 sym_link *from_type = operandType(IC_RIGHT(ic));
474 aop->aopu.aop_immd.from_cast_remat = 1;
475 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
476 ptr_type = DCL_TYPE(from_type);
477 if (ptr_type == IPOINTER) {
484 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
488 sprintf (buffer, "(%s %c 0x%04x)",
489 OP_SYMBOL (IC_LEFT (ic))->rname,
490 val >= 0 ? '+' : '-',
493 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
495 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
496 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
497 /* set immd2 field if required */
498 if (aop->aopu.aop_immd.from_cast_remat) {
499 sprintf(buffer,"#0x%02x",ptr_type);
500 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
501 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
507 /*-----------------------------------------------------------------*/
508 /* regsInCommon - two operands have some registers in common */
509 /*-----------------------------------------------------------------*/
511 regsInCommon (operand * op1, operand * op2)
516 /* if they have registers in common */
517 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
520 sym1 = OP_SYMBOL (op1);
521 sym2 = OP_SYMBOL (op2);
523 if (sym1->nRegs == 0 || sym2->nRegs == 0)
526 for (i = 0; i < sym1->nRegs; i++)
532 for (j = 0; j < sym2->nRegs; j++)
537 if (sym2->regs[j] == sym1->regs[i])
545 /*-----------------------------------------------------------------*/
546 /* operandsEqu - equivalent */
547 /*-----------------------------------------------------------------*/
549 operandsEqu (operand * op1, operand * op2)
553 /* if they not symbols */
554 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
557 sym1 = OP_SYMBOL (op1);
558 sym2 = OP_SYMBOL (op2);
560 /* if both are itemps & one is spilt
561 and the other is not then false */
562 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
563 sym1->isspilt != sym2->isspilt)
566 /* if they are the same */
570 if (strcmp (sym1->rname, sym2->rname) == 0)
574 /* if left is a tmp & right is not */
575 if (IS_ITEMP (op1) &&
578 (sym1->usl.spillLoc == sym2))
581 if (IS_ITEMP (op2) &&
585 (sym2->usl.spillLoc == sym1))
591 /*-----------------------------------------------------------------*/
592 /* sameRegs - two asmops have the same registers */
593 /*-----------------------------------------------------------------*/
595 sameRegs (asmop * aop1, asmop * aop2)
602 if (aop1->type != AOP_REG ||
603 aop2->type != AOP_REG)
606 if (aop1->size != aop2->size)
609 for (i = 0; i < aop1->size; i++)
610 if (aop1->aopu.aop_reg[i] !=
611 aop2->aopu.aop_reg[i])
617 /*-----------------------------------------------------------------*/
618 /* aopOp - allocates an asmop for an operand : */
619 /*-----------------------------------------------------------------*/
621 aopOp (operand * op, iCode * ic, bool result)
630 /* if this a literal */
631 if (IS_OP_LITERAL (op))
633 op->aop = aop = newAsmop (AOP_LIT);
634 aop->aopu.aop_lit = op->operand.valOperand;
635 aop->size = getSize (operandType (op));
639 /* if already has a asmop then continue */
643 /* if the underlying symbol has a aop */
644 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
646 op->aop = OP_SYMBOL (op)->aop;
650 /* if this is a true symbol */
651 if (IS_TRUE_SYMOP (op))
653 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
657 /* this is a temporary : this has
663 e) can be a return use only */
665 sym = OP_SYMBOL (op);
667 /* if the type is a conditional */
668 if (sym->regType == REG_CND)
670 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
675 /* if it is spilt then two situations
677 b) has a spill location */
678 if (sym->isspilt || sym->nRegs == 0)
681 /* rematerialize it NOW */
684 sym->aop = op->aop = aop =
686 aop->size = getSize (sym->type);
693 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
694 aop->size = getSize (sym->type);
695 for (i = 0; i < 2; i++)
696 aop->aopu.aop_str[i] = accUse[i];
704 aop = op->aop = sym->aop = newAsmop (AOP_STR);
705 aop->size = getSize (sym->type);
706 for (i = 0; i < fReturnSizeMCS51; i++)
707 aop->aopu.aop_str[i] = fReturn[i];
711 if (sym->usl.spillLoc)
713 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
715 /* force a new aop if sizes differ */
716 sym->usl.spillLoc->aop = NULL;
718 sym->aop = op->aop = aop =
719 aopForSym (ic, sym->usl.spillLoc, result);
720 aop->size = getSize (sym->type);
724 /* else must be a dummy iTemp */
725 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
726 aop->size = getSize (sym->type);
730 /* must be in a register */
731 sym->aop = op->aop = aop = newAsmop (AOP_REG);
732 aop->size = sym->nRegs;
733 for (i = 0; i < sym->nRegs; i++)
734 aop->aopu.aop_reg[i] = sym->regs[i];
737 /*-----------------------------------------------------------------*/
738 /* freeAsmop - free up the asmop given to an operand */
739 /*----------------------------------------------------------------*/
741 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
758 /* depending on the asmop type only three cases need work AOP_RO
759 , AOP_R1 && AOP_STK */
767 emitcode ("pop", "ar0");
771 bitVectUnSetBit (ic->rUsed, R0_IDX);
779 emitcode ("pop", "ar1");
783 bitVectUnSetBit (ic->rUsed, R1_IDX);
789 int stk = aop->aopu.aop_stk + aop->size - 1;
790 bitVectUnSetBit (ic->rUsed, R0_IDX);
791 bitVectUnSetBit (ic->rUsed, R1_IDX);
793 getFreePtr (ic, &aop, FALSE);
797 emitcode ("mov", "a,_bp");
798 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
799 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
803 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
808 emitcode ("pop", "acc");
809 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
812 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
815 freeAsmop (op, NULL, ic, TRUE);
818 emitcode ("pop", "ar1");
824 emitcode ("pop", "ar0");
831 /* all other cases just dealloc */
837 OP_SYMBOL (op)->aop = NULL;
838 /* if the symbol has a spill */
840 SPIL_LOC (op)->aop = NULL;
845 /*-----------------------------------------------------------------*/
846 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
847 /* clobber the accumulator */
848 /*-----------------------------------------------------------------*/
850 aopGetUsesAcc (asmop *aop, int offset)
852 if (offset > (aop->size - 1))
870 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
879 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
885 /* Error case --- will have been caught already */
891 /*-----------------------------------------------------------------*/
892 /* aopGet - for fetching value of the aop */
893 /*-----------------------------------------------------------------*/
895 aopGet (asmop * aop, int offset, bool bit16, bool dname)
900 /* offset is greater than
902 if (offset > (aop->size - 1) &&
903 aop->type != AOP_LIT)
906 /* depending on type */
914 /* if we need to increment it */
915 while (offset > aop->coff)
917 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
921 while (offset < aop->coff)
923 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
930 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
931 return (dname ? "acc" : "a");
933 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
934 rs = Safe_calloc (1, strlen (s) + 1);
939 if (aop->code && aop->coff==0 && offset>=1) {
940 emitcode ("mov", "a,#0x%02x", offset);
941 emitcode ("movc", "a,@a+dptr");
942 return (dname ? "acc" : "a");
945 while (offset > aop->coff)
947 emitcode ("inc", "dptr");
951 while (offset < aop->coff)
953 emitcode ("lcall", "__decdptr");
960 emitcode ("clr", "a");
961 emitcode ("movc", "a,@a+dptr");
965 emitcode ("movx", "a,@dptr");
967 return (dname ? "acc" : "a");
971 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
972 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
974 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
976 sprintf (s, "#(%s >> %d)",
977 aop->aopu.aop_immd.aop_immd1,
981 aop->aopu.aop_immd.aop_immd1);
982 rs = Safe_calloc (1, strlen (s) + 1);
988 sprintf (s, "(%s + %d)",
992 sprintf (s, "%s", aop->aopu.aop_dir);
993 rs = Safe_calloc (1, strlen (s) + 1);
999 return aop->aopu.aop_reg[offset]->dname;
1001 return aop->aopu.aop_reg[offset]->name;
1004 emitcode ("clr", "a");
1005 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1006 emitcode ("rlc", "a");
1007 return (dname ? "acc" : "a");
1010 if (!offset && dname)
1012 return aop->aopu.aop_str[offset];
1015 return aopLiteral (aop->aopu.aop_lit, offset);
1019 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1023 return aop->aopu.aop_str[offset];
1027 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1028 "aopget got unsupported aop->type");
1031 /*-----------------------------------------------------------------*/
1032 /* aopPut - puts a string for a aop */
1033 /*-----------------------------------------------------------------*/
1035 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1039 if (aop->size && offset > (aop->size - 1))
1041 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1042 "aopPut got offset > aop->size");
1046 /* will assign value to value */
1047 /* depending on where it is ofcourse */
1051 MOVA (s); /* read s in case it was volatile */
1056 sprintf (d, "(%s + %d)",
1057 aop->aopu.aop_dir, offset);
1059 sprintf (d, "%s", aop->aopu.aop_dir);
1061 if (strcmp (d, s) ||
1063 emitcode ("mov", "%s,%s", d, s);
1068 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1069 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1072 strcmp (s, "r0") == 0 ||
1073 strcmp (s, "r1") == 0 ||
1074 strcmp (s, "r2") == 0 ||
1075 strcmp (s, "r3") == 0 ||
1076 strcmp (s, "r4") == 0 ||
1077 strcmp (s, "r5") == 0 ||
1078 strcmp (s, "r6") == 0 ||
1079 strcmp (s, "r7") == 0)
1080 emitcode ("mov", "%s,%s",
1081 aop->aopu.aop_reg[offset]->dname, s);
1083 emitcode ("mov", "%s,%s",
1084 aop->aopu.aop_reg[offset]->name, s);
1091 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1092 "aopPut writing to code space");
1096 while (offset > aop->coff)
1099 emitcode ("inc", "dptr");
1102 while (offset < aop->coff)
1105 emitcode ("lcall", "__decdptr");
1110 /* if not in accumulater */
1113 emitcode ("movx", "@dptr,a");
1118 while (offset > aop->coff)
1121 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1123 while (offset < aop->coff)
1126 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1133 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1139 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1141 else if (strcmp (s, "r0") == 0 ||
1142 strcmp (s, "r1") == 0 ||
1143 strcmp (s, "r2") == 0 ||
1144 strcmp (s, "r3") == 0 ||
1145 strcmp (s, "r4") == 0 ||
1146 strcmp (s, "r5") == 0 ||
1147 strcmp (s, "r6") == 0 ||
1148 strcmp (s, "r7") == 0)
1151 sprintf (buffer, "a%s", s);
1152 emitcode ("mov", "@%s,%s",
1153 aop->aopu.aop_ptr->name, buffer);
1156 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1161 if (strcmp (s, "a") == 0)
1162 emitcode ("push", "acc");
1166 emitcode ("push", "acc");
1168 emitcode ("push", s);
1174 /* if bit variable */
1175 if (!aop->aopu.aop_dir)
1177 emitcode ("clr", "a");
1178 emitcode ("rlc", "a");
1183 emitcode ("clr", "%s", aop->aopu.aop_dir);
1185 emitcode ("setb", "%s", aop->aopu.aop_dir);
1186 else if (!strcmp (s, "c"))
1187 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1190 if (strcmp (s, "a"))
1195 /* set C, if a >= 1 */
1196 emitcode ("add", "a,#0xff");
1197 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1205 if (strcmp (aop->aopu.aop_str[offset], s) ||
1207 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1212 if (!offset && (strcmp (s, "acc") == 0) &&
1216 if (strcmp (aop->aopu.aop_str[offset], s) &&
1218 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1222 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1223 "aopPut got unsupported aop->type");
1231 /*-----------------------------------------------------------------*/
1232 /* pointToEnd :- points to the last byte of the operand */
1233 /*-----------------------------------------------------------------*/
1235 pointToEnd (asmop * aop)
1241 aop->coff = count = (aop->size - 1);
1247 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1251 emitcode ("inc", "dptr");
1258 /*-----------------------------------------------------------------*/
1259 /* reAdjustPreg - points a register back to where it should */
1260 /*-----------------------------------------------------------------*/
1262 reAdjustPreg (asmop * aop)
1264 if ((aop->coff==0) || aop->size <= 1)
1272 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1277 emitcode ("lcall", "__decdptr");
1284 #define AOP(op) op->aop
1285 #define AOP_TYPE(op) AOP(op)->type
1286 #define AOP_SIZE(op) AOP(op)->size
1287 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1288 AOP_TYPE(x) == AOP_R0))
1290 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1291 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1293 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1294 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1295 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1298 /*-----------------------------------------------------------------*/
1299 /* opIsGptr: returns non-zero if the passed operand is */
1300 /* a generic pointer type. */
1301 /*-----------------------------------------------------------------*/
1303 opIsGptr (operand * op)
1305 sym_link *type = operandType (op);
1307 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1314 /*-----------------------------------------------------------------*/
1315 /* getDataSize - get the operand data size */
1316 /*-----------------------------------------------------------------*/
1318 getDataSize (operand * op)
1321 size = AOP_SIZE (op);
1322 if (size == GPTRSIZE)
1324 sym_link *type = operandType (op);
1325 if (IS_GENPTR (type))
1327 /* generic pointer; arithmetic operations
1328 * should ignore the high byte (pointer type).
1336 /*-----------------------------------------------------------------*/
1337 /* outAcc - output Acc */
1338 /*-----------------------------------------------------------------*/
1340 outAcc (operand * result)
1343 size = getDataSize (result);
1346 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1349 /* unsigned or positive */
1352 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1357 /*-----------------------------------------------------------------*/
1358 /* outBitC - output a bit C */
1359 /*-----------------------------------------------------------------*/
1361 outBitC (operand * result)
1363 /* if the result is bit */
1364 if (AOP_TYPE (result) == AOP_CRY)
1365 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1368 emitcode ("clr", "a");
1369 emitcode ("rlc", "a");
1374 /*-----------------------------------------------------------------*/
1375 /* toBoolean - emit code for orl a,operator(sizeop) */
1376 /*-----------------------------------------------------------------*/
1378 toBoolean (operand * oper)
1380 int size = AOP_SIZE (oper) - 1;
1382 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1384 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1388 /*-----------------------------------------------------------------*/
1389 /* genNot - generate code for ! operation */
1390 /*-----------------------------------------------------------------*/
1396 D(emitcode ("; genNot",""));
1398 /* assign asmOps to operand & result */
1399 aopOp (IC_LEFT (ic), ic, FALSE);
1400 aopOp (IC_RESULT (ic), ic, TRUE);
1402 /* if in bit space then a special case */
1403 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1405 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1406 emitcode ("cpl", "c");
1407 outBitC (IC_RESULT (ic));
1411 toBoolean (IC_LEFT (ic));
1413 tlbl = newiTempLabel (NULL);
1414 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1415 emitcode ("", "%05d$:", tlbl->key + 100);
1416 outBitC (IC_RESULT (ic));
1419 /* release the aops */
1420 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1421 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1425 /*-----------------------------------------------------------------*/
1426 /* genCpl - generate code for complement */
1427 /*-----------------------------------------------------------------*/
1435 D(emitcode ("; genCpl",""));
1437 /* assign asmOps to operand & result */
1438 aopOp (IC_LEFT (ic), ic, FALSE);
1439 aopOp (IC_RESULT (ic), ic, TRUE);
1441 /* special case if in bit space */
1442 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1443 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1444 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1445 emitcode ("cpl", "c");
1446 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1449 tlbl=newiTempLabel(NULL);
1450 emitcode ("cjne", "%s,#0x01,%05d$",
1451 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1452 emitcode ("", "%05d$:", tlbl->key+100);
1453 outBitC (IC_RESULT(ic));
1457 size = AOP_SIZE (IC_RESULT (ic));
1460 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1462 emitcode ("cpl", "a");
1463 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1468 /* release the aops */
1469 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1470 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1473 /*-----------------------------------------------------------------*/
1474 /* genUminusFloat - unary minus for floating points */
1475 /*-----------------------------------------------------------------*/
1477 genUminusFloat (operand * op, operand * result)
1479 int size, offset = 0;
1482 D(emitcode ("; genUminusFloat",""));
1484 /* for this we just copy and then flip the bit */
1486 size = AOP_SIZE (op) - 1;
1490 aopPut (AOP (result),
1491 aopGet (AOP (op), offset, FALSE, FALSE),
1493 isOperandVolatile (result, FALSE));
1497 l = aopGet (AOP (op), offset, FALSE, FALSE);
1501 emitcode ("cpl", "acc.7");
1502 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1505 /*-----------------------------------------------------------------*/
1506 /* genUminus - unary minus code generation */
1507 /*-----------------------------------------------------------------*/
1509 genUminus (iCode * ic)
1512 sym_link *optype, *rtype;
1515 D(emitcode ("; genUminus",""));
1518 aopOp (IC_LEFT (ic), ic, FALSE);
1519 aopOp (IC_RESULT (ic), ic, TRUE);
1521 /* if both in bit space then special
1523 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1524 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1527 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1528 emitcode ("cpl", "c");
1529 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1533 optype = operandType (IC_LEFT (ic));
1534 rtype = operandType (IC_RESULT (ic));
1536 /* if float then do float stuff */
1537 if (IS_FLOAT (optype))
1539 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1543 /* otherwise subtract from zero */
1544 size = AOP_SIZE (IC_LEFT (ic));
1549 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1550 if (!strcmp (l, "a"))
1554 emitcode ("cpl", "a");
1555 emitcode ("addc", "a,#0");
1561 emitcode ("clr", "a");
1562 emitcode ("subb", "a,%s", l);
1564 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1567 /* if any remaining bytes in the result */
1568 /* we just need to propagate the sign */
1569 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1571 emitcode ("rlc", "a");
1572 emitcode ("subb", "a,acc");
1574 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1578 /* release the aops */
1579 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1580 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1583 /*-----------------------------------------------------------------*/
1584 /* saveRegisters - will look for a call and save the registers */
1585 /*-----------------------------------------------------------------*/
1587 saveRegisters (iCode * lic)
1594 for (ic = lic; ic; ic = ic->next)
1595 if (ic->op == CALL || ic->op == PCALL)
1600 fprintf (stderr, "found parameter push with no function call\n");
1604 /* if the registers have been saved already or don't need to be then
1608 if (IS_SYMOP(IC_LEFT(ic)) &&
1609 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1610 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1613 /* safe the registers in use at this time but skip the
1614 ones for the result */
1615 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1616 mcs51_rUmaskForOp (IC_RESULT(ic)));
1619 if (options.useXstack)
1621 if (bitVectBitValue (rsave, R0_IDX))
1622 emitcode ("mov", "b,r0");
1623 emitcode ("mov", "r0,%s", spname);
1624 for (i = 0; i < mcs51_nRegs; i++)
1626 if (bitVectBitValue (rsave, i))
1629 emitcode ("mov", "a,b");
1631 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1632 emitcode ("movx", "@r0,a");
1633 emitcode ("inc", "r0");
1636 emitcode ("mov", "%s,r0", spname);
1637 if (bitVectBitValue (rsave, R0_IDX))
1638 emitcode ("mov", "r0,b");
1641 for (i = 0; i < mcs51_nRegs; i++)
1643 if (bitVectBitValue (rsave, i))
1644 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1648 /*-----------------------------------------------------------------*/
1649 /* unsaveRegisters - pop the pushed registers */
1650 /*-----------------------------------------------------------------*/
1652 unsaveRegisters (iCode * ic)
1657 /* restore the registers in use at this time but skip the
1658 ones for the result */
1659 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1660 mcs51_rUmaskForOp (IC_RESULT(ic)));
1662 if (options.useXstack)
1664 emitcode ("mov", "r0,%s", spname);
1665 for (i = mcs51_nRegs; i >= 0; i--)
1667 if (bitVectBitValue (rsave, i))
1669 emitcode ("dec", "r0");
1670 emitcode ("movx", "a,@r0");
1672 emitcode ("mov", "b,a");
1674 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1678 emitcode ("mov", "%s,r0", spname);
1679 if (bitVectBitValue (rsave, R0_IDX))
1680 emitcode ("mov", "r0,b");
1683 for (i = mcs51_nRegs; i >= 0; i--)
1685 if (bitVectBitValue (rsave, i))
1686 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1692 /*-----------------------------------------------------------------*/
1694 /*-----------------------------------------------------------------*/
1696 pushSide (operand * oper, int size)
1701 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1702 if (AOP_TYPE (oper) != AOP_REG &&
1703 AOP_TYPE (oper) != AOP_DIR &&
1706 emitcode ("mov", "a,%s", l);
1707 emitcode ("push", "acc");
1710 emitcode ("push", "%s", l);
1714 /*-----------------------------------------------------------------*/
1715 /* assignResultValue - */
1716 /*-----------------------------------------------------------------*/
1718 assignResultValue (operand * oper)
1721 int size = AOP_SIZE (oper);
1724 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1730 /*-----------------------------------------------------------------*/
1731 /* genXpush - pushes onto the external stack */
1732 /*-----------------------------------------------------------------*/
1734 genXpush (iCode * ic)
1736 asmop *aop = newAsmop (0);
1738 int size, offset = 0;
1740 D(emitcode ("; genXpush",""));
1742 aopOp (IC_LEFT (ic), ic, FALSE);
1743 r = getFreePtr (ic, &aop, FALSE);
1746 emitcode ("mov", "%s,_spx", r->name);
1748 size = AOP_SIZE (IC_LEFT (ic));
1752 char *l = aopGet (AOP (IC_LEFT (ic)),
1753 offset++, FALSE, FALSE);
1755 emitcode ("movx", "@%s,a", r->name);
1756 emitcode ("inc", "%s", r->name);
1761 emitcode ("mov", "_spx,%s", r->name);
1763 freeAsmop (NULL, aop, ic, TRUE);
1764 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1767 /*-----------------------------------------------------------------*/
1768 /* genIpush - genrate code for pushing this gets a little complex */
1769 /*-----------------------------------------------------------------*/
1771 genIpush (iCode * ic)
1773 int size, offset = 0;
1776 D(emitcode ("; genIpush",""));
1778 /* if this is not a parm push : ie. it is spill push
1779 and spill push is always done on the local stack */
1783 /* and the item is spilt then do nothing */
1784 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1787 aopOp (IC_LEFT (ic), ic, FALSE);
1788 size = AOP_SIZE (IC_LEFT (ic));
1789 /* push it on the stack */
1792 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1798 emitcode ("push", "%s", l);
1803 /* this is a paramter push: in this case we call
1804 the routine to find the call and save those
1805 registers that need to be saved */
1808 /* if use external stack then call the external
1809 stack pushing routine */
1810 if (options.useXstack)
1816 /* then do the push */
1817 aopOp (IC_LEFT (ic), ic, FALSE);
1820 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1821 size = AOP_SIZE (IC_LEFT (ic));
1825 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1826 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1827 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1830 emitcode ("mov", "a,%s", l);
1831 emitcode ("push", "acc");
1834 emitcode ("push", "%s", l);
1837 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1840 /*-----------------------------------------------------------------*/
1841 /* genIpop - recover the registers: can happen only for spilling */
1842 /*-----------------------------------------------------------------*/
1844 genIpop (iCode * ic)
1848 D(emitcode ("; genIpop",""));
1850 /* if the temp was not pushed then */
1851 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1854 aopOp (IC_LEFT (ic), ic, FALSE);
1855 size = AOP_SIZE (IC_LEFT (ic));
1856 offset = (size - 1);
1858 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1861 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1864 /*-----------------------------------------------------------------*/
1865 /* unsaveRBank - restores the resgister bank from stack */
1866 /*-----------------------------------------------------------------*/
1868 unsaveRBank (int bank, iCode * ic, bool popPsw)
1874 if (options.useXstack)
1878 /* Assume r0 is available for use. */
1879 r = mcs51_regWithIdx (R0_IDX);;
1884 r = getFreePtr (ic, &aop, FALSE);
1886 emitcode ("mov", "%s,_spx", r->name);
1891 if (options.useXstack)
1893 emitcode ("movx", "a,@%s", r->name);
1894 emitcode ("mov", "psw,a");
1895 emitcode ("dec", "%s", r->name);
1899 emitcode ("pop", "psw");
1903 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1905 if (options.useXstack)
1907 emitcode ("movx", "a,@%s", r->name);
1908 emitcode ("mov", "(%s+%d),a",
1909 regs8051[i].base, 8 * bank + regs8051[i].offset);
1910 emitcode ("dec", "%s", r->name);
1914 emitcode ("pop", "(%s+%d)",
1915 regs8051[i].base, 8 * bank + regs8051[i].offset);
1918 if (options.useXstack)
1920 emitcode ("mov", "_spx,%s", r->name);
1925 freeAsmop (NULL, aop, ic, TRUE);
1929 /*-----------------------------------------------------------------*/
1930 /* saveRBank - saves an entire register bank on the stack */
1931 /*-----------------------------------------------------------------*/
1933 saveRBank (int bank, iCode * ic, bool pushPsw)
1939 if (options.useXstack)
1943 /* Assume r0 is available for use. */
1944 r = mcs51_regWithIdx (R0_IDX);;
1949 r = getFreePtr (ic, &aop, FALSE);
1951 emitcode ("mov", "%s,_spx", r->name);
1954 for (i = 0; i < mcs51_nRegs; i++)
1956 if (options.useXstack)
1958 emitcode ("inc", "%s", r->name);
1959 emitcode ("mov", "a,(%s+%d)",
1960 regs8051[i].base, 8 * bank + regs8051[i].offset);
1961 emitcode ("movx", "@%s,a", r->name);
1964 emitcode ("push", "(%s+%d)",
1965 regs8051[i].base, 8 * bank + regs8051[i].offset);
1970 if (options.useXstack)
1972 emitcode ("mov", "a,psw");
1973 emitcode ("movx", "@%s,a", r->name);
1974 emitcode ("inc", "%s", r->name);
1975 emitcode ("mov", "_spx,%s", r->name);
1980 emitcode ("push", "psw");
1983 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1988 freeAsmop (NULL, aop, ic, TRUE);
1997 /*-----------------------------------------------------------------*/
1998 /* genSend - gen code for SEND */
1999 /*-----------------------------------------------------------------*/
2000 static void genSend(set *sendSet)
2005 for (sic = setFirstItem (_G.sendSet); sic;
2006 sic = setNextItem (_G.sendSet)) {
2007 int size, offset = 0;
2008 aopOp (IC_LEFT (sic), sic, FALSE);
2009 size = AOP_SIZE (IC_LEFT (sic));
2011 if (sic->argreg == 1) {
2013 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2015 if (strcmp (l, fReturn[offset]))
2016 emitcode ("mov", "%s,%s", fReturn[offset], l);
2022 emitcode ("mov","b1_%d,%s",rb1_count++,
2023 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2026 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2030 /*-----------------------------------------------------------------*/
2031 /* genCall - generates a call statement */
2032 /*-----------------------------------------------------------------*/
2034 genCall (iCode * ic)
2037 // bool restoreBank = FALSE;
2038 bool swapBanks = FALSE;
2040 D(emitcode("; genCall",""));
2042 dtype = operandType (IC_LEFT (ic));
2043 /* if send set is not empty the assign */
2046 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2047 genSend(reverseSet(_G.sendSet));
2049 genSend(_G.sendSet);
2055 /* if we are calling a not _naked function that is not using
2056 the same register bank then we need to save the
2057 destination registers on the stack */
2058 dtype = operandType (IC_LEFT (ic));
2059 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2060 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2061 !IFFUNC_ISISR (dtype))
2066 /* if caller saves & we have not saved then */
2072 emitcode ("mov", "psw,#0x%02x",
2073 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2077 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2078 OP_SYMBOL (IC_LEFT (ic))->rname :
2079 OP_SYMBOL (IC_LEFT (ic))->name));
2083 emitcode ("mov", "psw,#0x%02x",
2084 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2087 /* if we need assign a result value */
2088 if ((IS_ITEMP (IC_RESULT (ic)) &&
2089 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2090 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2091 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2092 IS_TRUE_SYMOP (IC_RESULT (ic)))
2096 aopOp (IC_RESULT (ic), ic, FALSE);
2099 assignResultValue (IC_RESULT (ic));
2101 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2104 /* adjust the stack for parameters if
2109 if (ic->parmBytes > 3)
2111 emitcode ("mov", "a,%s", spname);
2112 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2113 emitcode ("mov", "%s,a", spname);
2116 for (i = 0; i < ic->parmBytes; i++)
2117 emitcode ("dec", "%s", spname);
2120 /* if we hade saved some registers then unsave them */
2121 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2122 unsaveRegisters (ic);
2124 // /* if register bank was saved then pop them */
2126 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2129 /*-----------------------------------------------------------------*/
2130 /* -10l - generates a call by pointer statement */
2131 /*-----------------------------------------------------------------*/
2133 genPcall (iCode * ic)
2136 symbol *rlbl = newiTempLabel (NULL);
2137 // bool restoreBank=FALSE;
2138 bool swapBanks = FALSE;
2140 D(emitcode("; genPCall",""));
2142 /* if caller saves & we have not saved then */
2146 /* if we are calling a not _naked function that is not using
2147 the same register bank then we need to save the
2148 destination registers on the stack */
2149 dtype = operandType (IC_LEFT (ic))->next;
2150 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2151 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2152 !IFFUNC_ISISR (dtype))
2154 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2155 // restoreBank=TRUE;
2157 // need caution message to user here
2160 /* push the return address on to the stack */
2161 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2162 emitcode ("push", "acc");
2163 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2164 emitcode ("push", "acc");
2166 /* now push the calling address */
2167 aopOp (IC_LEFT (ic), ic, FALSE);
2169 pushSide (IC_LEFT (ic), FPTRSIZE);
2171 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2173 /* if send set is not empty the assign */
2176 genSend(reverseSet(_G.sendSet));
2182 emitcode ("mov", "psw,#0x%02x",
2183 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2187 emitcode ("ret", "");
2188 emitcode ("", "%05d$:", (rlbl->key + 100));
2193 emitcode ("mov", "psw,#0x%02x",
2194 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2197 /* if we need assign a result value */
2198 if ((IS_ITEMP (IC_RESULT (ic)) &&
2199 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2200 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2201 IS_TRUE_SYMOP (IC_RESULT (ic)))
2205 aopOp (IC_RESULT (ic), ic, FALSE);
2208 assignResultValue (IC_RESULT (ic));
2210 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2213 /* adjust the stack for parameters if
2218 if (ic->parmBytes > 3)
2220 emitcode ("mov", "a,%s", spname);
2221 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2222 emitcode ("mov", "%s,a", spname);
2225 for (i = 0; i < ic->parmBytes; i++)
2226 emitcode ("dec", "%s", spname);
2230 // /* if register bank was saved then unsave them */
2232 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2234 /* if we hade saved some registers then
2236 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2237 unsaveRegisters (ic);
2240 /*-----------------------------------------------------------------*/
2241 /* resultRemat - result is rematerializable */
2242 /*-----------------------------------------------------------------*/
2244 resultRemat (iCode * ic)
2246 if (SKIP_IC (ic) || ic->op == IFX)
2249 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2251 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2252 if (sym->remat && !POINTER_SET (ic))
2259 #if defined(__BORLANDC__) || defined(_MSC_VER)
2260 #define STRCASECMP stricmp
2262 #define STRCASECMP strcasecmp
2265 /*-----------------------------------------------------------------*/
2266 /* inExcludeList - return 1 if the string is in exclude Reg list */
2267 /*-----------------------------------------------------------------*/
2269 regsCmp(void *p1, void *p2)
2271 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2275 inExcludeList (char *s)
2277 const char *p = setFirstItem(options.excludeRegsSet);
2279 if (p == NULL || STRCASECMP(p, "none") == 0)
2283 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2286 /*-----------------------------------------------------------------*/
2287 /* genFunction - generated code for function entry */
2288 /*-----------------------------------------------------------------*/
2290 genFunction (iCode * ic)
2294 bool switchedPSW = FALSE;
2295 int calleesaves_saved_register = -1;
2298 /* create the function header */
2299 emitcode (";", "-----------------------------------------");
2300 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2301 emitcode (";", "-----------------------------------------");
2303 emitcode ("", "%s:", sym->rname);
2304 ftype = operandType (IC_LEFT (ic));
2306 if (IFFUNC_ISNAKED(ftype))
2308 emitcode(";", "naked function: no prologue.");
2312 /* here we need to generate the equates for the
2313 register bank if required */
2314 if (FUNC_REGBANK (ftype) != rbank)
2318 rbank = FUNC_REGBANK (ftype);
2319 for (i = 0; i < mcs51_nRegs; i++)
2321 if (strcmp (regs8051[i].base, "0") == 0)
2322 emitcode ("", "%s = 0x%02x",
2324 8 * rbank + regs8051[i].offset);
2326 emitcode ("", "%s = %s + 0x%02x",
2329 8 * rbank + regs8051[i].offset);
2333 /* if this is an interrupt service routine then
2334 save acc, b, dpl, dph */
2335 if (IFFUNC_ISISR (sym->type))
2338 if (!inExcludeList ("acc"))
2339 emitcode ("push", "acc");
2340 if (!inExcludeList ("b"))
2341 emitcode ("push", "b");
2342 if (!inExcludeList ("dpl"))
2343 emitcode ("push", "dpl");
2344 if (!inExcludeList ("dph"))
2345 emitcode ("push", "dph");
2346 /* if this isr has no bank i.e. is going to
2347 run with bank 0 , then we need to save more
2349 if (!FUNC_REGBANK (sym->type))
2352 /* if this function does not call any other
2353 function then we can be economical and
2354 save only those registers that are used */
2355 if (!IFFUNC_HASFCALL(sym->type))
2359 /* if any registers used */
2362 /* save the registers used */
2363 for (i = 0; i < sym->regsUsed->size; i++)
2365 if (bitVectBitValue (sym->regsUsed, i) ||
2366 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2367 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2375 /* this function has a function call cannot
2376 determines register usage so we will have to push the
2378 saveRBank (0, ic, FALSE);
2379 if (options.parms_in_bank1) {
2381 for (i=0; i < 8 ; i++ ) {
2382 emitcode ("push","%s",rb1regs[i]);
2389 /* This ISR uses a non-zero bank.
2391 * We assume that the bank is available for our
2394 * However, if this ISR calls a function which uses some
2395 * other bank, we must save that bank entirely.
2397 unsigned long banksToSave = 0;
2399 if (IFFUNC_HASFCALL(sym->type))
2402 #define MAX_REGISTER_BANKS 4
2407 for (i = ic; i; i = i->next)
2409 if (i->op == ENDFUNCTION)
2411 /* we got to the end OK. */
2419 dtype = operandType (IC_LEFT(i));
2421 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2423 /* Mark this bank for saving. */
2424 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2426 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2430 banksToSave |= (1 << FUNC_REGBANK(dtype));
2433 /* And note that we don't need to do it in
2441 /* This is a mess; we have no idea what
2442 * register bank the called function might
2445 * The only thing I can think of to do is
2446 * throw a warning and hope.
2448 werror(W_FUNCPTR_IN_USING_ISR);
2452 if (banksToSave && options.useXstack)
2454 /* Since we aren't passing it an ic,
2455 * saveRBank will assume r0 is available to abuse.
2457 * So switch to our (trashable) bank now, so
2458 * the caller's R0 isn't trashed.
2460 emitcode ("push", "psw");
2461 emitcode ("mov", "psw,#0x%02x",
2462 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2466 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2468 if (banksToSave & (1 << ix))
2470 saveRBank(ix, NULL, FALSE);
2474 // TODO: this needs a closer look
2475 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2480 /* if callee-save to be used for this function
2481 then save the registers being used in this function */
2482 if (IFFUNC_CALLEESAVES(sym->type))
2486 /* if any registers used */
2489 /* save the registers used */
2490 for (i = 0; i < sym->regsUsed->size; i++)
2492 if (bitVectBitValue (sym->regsUsed, i) ||
2493 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2495 /* remember one saved register for later usage */
2496 if (calleesaves_saved_register < 0)
2497 calleesaves_saved_register = i;
2498 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2506 /* set the register bank to the desired value */
2507 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2510 emitcode ("push", "psw");
2511 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2514 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2517 if (options.useXstack)
2519 emitcode ("mov", "r0,%s", spname);
2520 emitcode ("mov", "a,_bp");
2521 emitcode ("movx", "@r0,a");
2522 emitcode ("inc", "%s", spname);
2526 /* set up the stack */
2527 emitcode ("push", "_bp"); /* save the callers stack */
2529 emitcode ("mov", "_bp,%s", spname);
2532 /* adjust the stack for the function */
2538 werror (W_STACK_OVERFLOW, sym->name);
2540 if (i > 3 && sym->recvSize < 4)
2543 emitcode ("mov", "a,sp");
2544 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2545 emitcode ("mov", "sp,a");
2550 if (IFFUNC_CALLEESAVES(sym->type))
2552 /* if it's a callee-saves function we need a saved register */
2553 if (calleesaves_saved_register >= 0)
2555 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2556 emitcode ("mov", "a,sp");
2557 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2558 emitcode ("mov", "sp,a");
2559 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2562 /* do it the hard way */
2564 emitcode ("inc", "sp");
2568 /* not callee-saves, we can clobber r0 */
2569 emitcode ("mov", "r0,a");
2570 emitcode ("mov", "a,sp");
2571 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2572 emitcode ("mov", "sp,a");
2573 emitcode ("mov", "a,r0");
2578 emitcode ("inc", "sp");
2584 emitcode ("mov", "a,_spx");
2585 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2586 emitcode ("mov", "_spx,a");
2589 /* if critical function then turn interrupts off */
2590 if (IFFUNC_ISCRITICAL (ftype))
2592 emitcode ("mov", "c,ea");
2593 emitcode ("push", "psw"); /* save old ea via c in psw */
2594 emitcode ("clr", "ea");
2598 /*-----------------------------------------------------------------*/
2599 /* genEndFunction - generates epilogue for functions */
2600 /*-----------------------------------------------------------------*/
2602 genEndFunction (iCode * ic)
2604 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2606 if (IFFUNC_ISNAKED(sym->type))
2608 emitcode(";", "naked function: no epilogue.");
2612 if (IFFUNC_ISCRITICAL (sym->type))
2614 emitcode ("pop", "psw"); /* restore ea via c in psw */
2615 emitcode ("mov", "ea,c");
2618 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2620 emitcode ("mov", "%s,_bp", spname);
2623 /* if use external stack but some variables were
2624 added to the local stack then decrement the
2626 if (options.useXstack && sym->stack)
2628 emitcode ("mov", "a,sp");
2629 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2630 emitcode ("mov", "sp,a");
2634 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2636 if (options.useXstack)
2638 emitcode ("mov", "r0,%s", spname);
2639 emitcode ("movx", "a,@r0");
2640 emitcode ("mov", "_bp,a");
2641 emitcode ("dec", "%s", spname);
2645 emitcode ("pop", "_bp");
2649 /* restore the register bank */
2650 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2652 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2653 || !options.useXstack)
2655 /* Special case of ISR using non-zero bank with useXstack
2658 emitcode ("pop", "psw");
2662 if (IFFUNC_ISISR (sym->type))
2665 /* now we need to restore the registers */
2666 /* if this isr has no bank i.e. is going to
2667 run with bank 0 , then we need to save more
2669 if (!FUNC_REGBANK (sym->type))
2671 /* if this function does not call any other
2672 function then we can be economical and
2673 save only those registers that are used */
2674 if (!IFFUNC_HASFCALL(sym->type))
2678 /* if any registers used */
2681 /* save the registers used */
2682 for (i = sym->regsUsed->size; i >= 0; i--)
2684 if (bitVectBitValue (sym->regsUsed, i) ||
2685 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2686 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2693 if (options.parms_in_bank1) {
2695 for (i = 7 ; i >= 0 ; i-- ) {
2696 emitcode ("pop","%s",rb1regs[i]);
2699 /* this function has a function call cannot
2700 determines register usage so we will have to pop the
2702 unsaveRBank (0, ic, FALSE);
2707 /* This ISR uses a non-zero bank.
2709 * Restore any register banks saved by genFunction
2712 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2715 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2717 if (savedBanks & (1 << ix))
2719 unsaveRBank(ix, NULL, FALSE);
2723 if (options.useXstack)
2725 /* Restore bank AFTER calling unsaveRBank,
2726 * since it can trash r0.
2728 emitcode ("pop", "psw");
2732 if (!inExcludeList ("dph"))
2733 emitcode ("pop", "dph");
2734 if (!inExcludeList ("dpl"))
2735 emitcode ("pop", "dpl");
2736 if (!inExcludeList ("b"))
2737 emitcode ("pop", "b");
2738 if (!inExcludeList ("acc"))
2739 emitcode ("pop", "acc");
2741 /* if debug then send end of function */
2742 if (options.debug && currFunc)
2745 emitcode ("", "C$%s$%d$%d$%d ==.",
2746 FileBaseName (ic->filename), currFunc->lastLine,
2747 ic->level, ic->block);
2748 if (IS_STATIC (currFunc->etype))
2749 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2751 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2755 emitcode ("reti", "");
2759 if (IFFUNC_CALLEESAVES(sym->type))
2763 /* if any registers used */
2766 /* save the registers used */
2767 for (i = sym->regsUsed->size; i >= 0; i--)
2769 if (bitVectBitValue (sym->regsUsed, i) ||
2770 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2771 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2777 /* if debug then send end of function */
2778 if (options.debug && currFunc)
2781 emitcode ("", "C$%s$%d$%d$%d ==.",
2782 FileBaseName (ic->filename), currFunc->lastLine,
2783 ic->level, ic->block);
2784 if (IS_STATIC (currFunc->etype))
2785 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2787 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2791 emitcode ("ret", "");
2796 /*-----------------------------------------------------------------*/
2797 /* genRet - generate code for return statement */
2798 /*-----------------------------------------------------------------*/
2802 int size, offset = 0, pushed = 0;
2804 D(emitcode ("; genRet",""));
2806 /* if we have no return value then
2807 just generate the "ret" */
2811 /* we have something to return then
2812 move the return value into place */
2813 aopOp (IC_LEFT (ic), ic, FALSE);
2814 size = AOP_SIZE (IC_LEFT (ic));
2819 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2822 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2824 emitcode ("push", "%s", l);
2829 l = aopGet (AOP (IC_LEFT (ic)), offset,
2831 if (strcmp (fReturn[offset], l))
2832 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2841 if (strcmp (fReturn[pushed], "a"))
2842 emitcode ("pop", fReturn[pushed]);
2844 emitcode ("pop", "acc");
2847 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2850 /* generate a jump to the return label
2851 if the next is not the return statement */
2852 if (!(ic->next && ic->next->op == LABEL &&
2853 IC_LABEL (ic->next) == returnLabel))
2855 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2859 /*-----------------------------------------------------------------*/
2860 /* genLabel - generates a label */
2861 /*-----------------------------------------------------------------*/
2863 genLabel (iCode * ic)
2865 /* special case never generate */
2866 if (IC_LABEL (ic) == entryLabel)
2869 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2872 /*-----------------------------------------------------------------*/
2873 /* genGoto - generates a ljmp */
2874 /*-----------------------------------------------------------------*/
2876 genGoto (iCode * ic)
2878 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2881 /*-----------------------------------------------------------------*/
2882 /* findLabelBackwards: walks back through the iCode chain looking */
2883 /* for the given label. Returns number of iCode instructions */
2884 /* between that label and given ic. */
2885 /* Returns zero if label not found. */
2886 /*-----------------------------------------------------------------*/
2888 findLabelBackwards (iCode * ic, int key)
2897 /* If we have any pushes or pops, we cannot predict the distance.
2898 I don't like this at all, this should be dealt with in the
2900 if (ic->op == IPUSH || ic->op == IPOP) {
2904 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2913 /*-----------------------------------------------------------------*/
2914 /* genPlusIncr :- does addition with increment if possible */
2915 /*-----------------------------------------------------------------*/
2917 genPlusIncr (iCode * ic)
2919 unsigned int icount;
2920 unsigned int size = getDataSize (IC_RESULT (ic));
2922 /* will try to generate an increment */
2923 /* if the right side is not a literal
2925 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2928 /* if the literal value of the right hand side
2929 is greater than 4 then it is not worth it */
2930 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2933 D(emitcode ("; genPlusIncr",""));
2935 /* if increment >=16 bits in register or direct space */
2936 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2937 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2945 /* If the next instruction is a goto and the goto target
2946 * is < 10 instructions previous to this, we can generate
2947 * jumps straight to that target.
2949 if (ic->next && ic->next->op == GOTO
2950 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2951 && labelRange <= 10)
2953 emitcode (";", "tail increment optimized");
2954 tlbl = IC_LABEL (ic->next);
2959 tlbl = newiTempLabel (NULL);
2962 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2963 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2964 IS_AOP_PREG (IC_RESULT (ic)))
2965 emitcode ("cjne", "%s,#0x00,%05d$",
2966 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2970 emitcode ("clr", "a");
2971 emitcode ("cjne", "a,%s,%05d$",
2972 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2976 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2979 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2980 IS_AOP_PREG (IC_RESULT (ic)))
2981 emitcode ("cjne", "%s,#0x00,%05d$",
2982 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2985 emitcode ("cjne", "a,%s,%05d$",
2986 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2989 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2993 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2994 IS_AOP_PREG (IC_RESULT (ic)))
2995 emitcode ("cjne", "%s,#0x00,%05d$",
2996 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3000 emitcode ("cjne", "a,%s,%05d$",
3001 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3004 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3009 emitcode ("", "%05d$:", tlbl->key + 100);
3014 /* if the sizes are greater than 1 then we cannot */
3015 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3016 AOP_SIZE (IC_LEFT (ic)) > 1)
3019 /* we can if the aops of the left & result match or
3020 if they are in registers and the registers are the
3022 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3027 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3028 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3029 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3035 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3044 /*-----------------------------------------------------------------*/
3045 /* outBitAcc - output a bit in acc */
3046 /*-----------------------------------------------------------------*/
3048 outBitAcc (operand * result)
3050 symbol *tlbl = newiTempLabel (NULL);
3051 /* if the result is a bit */
3052 if (AOP_TYPE (result) == AOP_CRY)
3054 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3058 emitcode ("jz", "%05d$", tlbl->key + 100);
3059 emitcode ("mov", "a,%s", one);
3060 emitcode ("", "%05d$:", tlbl->key + 100);
3065 /*-----------------------------------------------------------------*/
3066 /* genPlusBits - generates code for addition of two bits */
3067 /*-----------------------------------------------------------------*/
3069 genPlusBits (iCode * ic)
3071 D(emitcode ("; genPlusBits",""));
3073 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3075 symbol *lbl = newiTempLabel (NULL);
3076 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3077 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3078 emitcode ("cpl", "c");
3079 emitcode ("", "%05d$:", (lbl->key + 100));
3080 outBitC (IC_RESULT (ic));
3084 emitcode ("clr", "a");
3085 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3086 emitcode ("rlc", "a");
3087 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3088 emitcode ("addc", "a,#0x00");
3089 outAcc (IC_RESULT (ic));
3094 /* This is the original version of this code.
3096 * This is being kept around for reference,
3097 * because I am not entirely sure I got it right...
3100 adjustArithmeticResult (iCode * ic)
3102 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3103 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3104 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3105 aopPut (AOP (IC_RESULT (ic)),
3106 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3108 isOperandVolatile (IC_RESULT (ic), FALSE));
3110 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3111 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3112 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3113 aopPut (AOP (IC_RESULT (ic)),
3114 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3116 isOperandVolatile (IC_RESULT (ic), FALSE));
3118 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3119 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3120 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3121 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3122 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3125 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3126 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3130 /* This is the pure and virtuous version of this code.
3131 * I'm pretty certain it's right, but not enough to toss the old
3135 adjustArithmeticResult (iCode * ic)
3137 if (opIsGptr (IC_RESULT (ic)) &&
3138 opIsGptr (IC_LEFT (ic)) &&
3139 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3141 aopPut (AOP (IC_RESULT (ic)),
3142 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3144 isOperandVolatile (IC_RESULT (ic), FALSE));
3147 if (opIsGptr (IC_RESULT (ic)) &&
3148 opIsGptr (IC_RIGHT (ic)) &&
3149 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3151 aopPut (AOP (IC_RESULT (ic)),
3152 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3154 isOperandVolatile (IC_RESULT (ic), FALSE));
3157 if (opIsGptr (IC_RESULT (ic)) &&
3158 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3159 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3160 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3161 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3164 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3165 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3170 /*-----------------------------------------------------------------*/
3171 /* genPlus - generates code for addition */
3172 /*-----------------------------------------------------------------*/
3174 genPlus (iCode * ic)
3176 int size, offset = 0;
3178 asmop *leftOp, *rightOp;
3180 /* special cases :- */
3182 D(emitcode ("; genPlus",""));
3184 aopOp (IC_LEFT (ic), ic, FALSE);
3185 aopOp (IC_RIGHT (ic), ic, FALSE);
3186 aopOp (IC_RESULT (ic), ic, TRUE);
3188 /* if literal, literal on the right or
3189 if left requires ACC or right is already
3191 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3192 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3193 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3195 operand *t = IC_RIGHT (ic);
3196 IC_RIGHT (ic) = IC_LEFT (ic);
3200 /* if both left & right are in bit
3202 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3203 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3209 /* if left in bit space & right literal */
3210 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3211 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3213 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3214 /* if result in bit space */
3215 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3217 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3218 emitcode ("cpl", "c");
3219 outBitC (IC_RESULT (ic));
3223 size = getDataSize (IC_RESULT (ic));
3226 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3227 emitcode ("addc", "a,#00");
3228 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3234 /* if I can do an increment instead
3235 of add then GOOD for ME */
3236 if (genPlusIncr (ic) == TRUE)
3239 size = getDataSize (IC_RESULT (ic));
3241 leftOp = AOP(IC_LEFT(ic));
3242 rightOp = AOP(IC_RIGHT(ic));
3247 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3249 emitcode("mov", "b,a");
3250 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3251 emitcode("xch", "a,b");
3252 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3253 emitcode (add, "a,b");
3255 else if (aopGetUsesAcc (leftOp, offset))
3257 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3258 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3262 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3263 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3265 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3266 add = "addc"; /* further adds must propagate carry */
3269 adjustArithmeticResult (ic);
3272 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3273 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3274 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3277 /*-----------------------------------------------------------------*/
3278 /* genMinusDec :- does subtraction with deccrement if possible */
3279 /*-----------------------------------------------------------------*/
3281 genMinusDec (iCode * ic)
3283 unsigned int icount;
3284 unsigned int size = getDataSize (IC_RESULT (ic));
3286 /* will try to generate an increment */
3287 /* if the right side is not a literal
3289 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3292 /* if the literal value of the right hand side
3293 is greater than 4 then it is not worth it */
3294 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3297 D(emitcode ("; genMinusDec",""));
3299 /* if decrement >=16 bits in register or direct space */
3300 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3301 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3309 /* If the next instruction is a goto and the goto target
3310 * is <= 10 instructions previous to this, we can generate
3311 * jumps straight to that target.
3313 if (ic->next && ic->next->op == GOTO
3314 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3315 && labelRange <= 10)
3317 emitcode (";", "tail decrement optimized");
3318 tlbl = IC_LABEL (ic->next);
3323 tlbl = newiTempLabel (NULL);
3327 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3328 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3329 IS_AOP_PREG (IC_RESULT (ic)))
3330 emitcode ("cjne", "%s,#0xff,%05d$"
3331 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3335 emitcode ("mov", "a,#0xff");
3336 emitcode ("cjne", "a,%s,%05d$"
3337 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3340 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3343 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3344 IS_AOP_PREG (IC_RESULT (ic)))
3345 emitcode ("cjne", "%s,#0xff,%05d$"
3346 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3350 emitcode ("cjne", "a,%s,%05d$"
3351 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3354 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3358 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3359 IS_AOP_PREG (IC_RESULT (ic)))
3360 emitcode ("cjne", "%s,#0xff,%05d$"
3361 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3365 emitcode ("cjne", "a,%s,%05d$"
3366 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3369 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3373 emitcode ("", "%05d$:", tlbl->key + 100);
3378 /* if the sizes are greater than 1 then we cannot */
3379 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3380 AOP_SIZE (IC_LEFT (ic)) > 1)
3383 /* we can if the aops of the left & result match or
3384 if they are in registers and the registers are the
3386 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3390 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3398 /*-----------------------------------------------------------------*/
3399 /* addSign - complete with sign */
3400 /*-----------------------------------------------------------------*/
3402 addSign (operand * result, int offset, int sign)
3404 int size = (getDataSize (result) - offset);
3409 emitcode ("rlc", "a");
3410 emitcode ("subb", "a,acc");
3412 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3416 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3420 /*-----------------------------------------------------------------*/
3421 /* genMinusBits - generates code for subtraction of two bits */
3422 /*-----------------------------------------------------------------*/
3424 genMinusBits (iCode * ic)
3426 symbol *lbl = newiTempLabel (NULL);
3428 D(emitcode ("; genMinusBits",""));
3430 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3432 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3433 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3434 emitcode ("cpl", "c");
3435 emitcode ("", "%05d$:", (lbl->key + 100));
3436 outBitC (IC_RESULT (ic));
3440 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3441 emitcode ("subb", "a,acc");
3442 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3443 emitcode ("inc", "a");
3444 emitcode ("", "%05d$:", (lbl->key + 100));
3445 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3446 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3450 /*-----------------------------------------------------------------*/
3451 /* genMinus - generates code for subtraction */
3452 /*-----------------------------------------------------------------*/
3454 genMinus (iCode * ic)
3456 int size, offset = 0;
3458 D(emitcode ("; genMinus",""));
3460 aopOp (IC_LEFT (ic), ic, FALSE);
3461 aopOp (IC_RIGHT (ic), ic, FALSE);
3462 aopOp (IC_RESULT (ic), ic, TRUE);
3464 /* special cases :- */
3465 /* if both left & right are in bit space */
3466 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3467 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3473 /* if I can do an decrement instead
3474 of subtract then GOOD for ME */
3475 if (genMinusDec (ic) == TRUE)
3478 size = getDataSize (IC_RESULT (ic));
3480 /* if literal, add a,#-lit, else normal subb */
3481 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3483 unsigned long lit = 0L;
3485 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3490 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3491 /* first add without previous c */
3493 if (!size && lit== (unsigned long) -1) {
3494 emitcode ("dec", "a");
3496 emitcode ("add", "a,#0x%02x",
3497 (unsigned int) (lit & 0x0FFL));
3500 emitcode ("addc", "a,#0x%02x",
3501 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3503 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3508 asmop *leftOp, *rightOp;
3510 leftOp = AOP(IC_LEFT(ic));
3511 rightOp = AOP(IC_RIGHT(ic));
3515 if (aopGetUsesAcc(rightOp, offset)) {
3516 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3517 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3519 emitcode( "setb", "c");
3521 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3522 emitcode("cpl", "a");
3524 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3527 emitcode ("subb", "a,%s",
3528 aopGet(rightOp, offset, FALSE, TRUE));
3531 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3536 adjustArithmeticResult (ic);
3539 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3540 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3541 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3545 /*-----------------------------------------------------------------*/
3546 /* genMultbits :- multiplication of bits */
3547 /*-----------------------------------------------------------------*/
3549 genMultbits (operand * left,
3553 D(emitcode ("; genMultbits",""));
3555 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3556 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3561 /*-----------------------------------------------------------------*/
3562 /* genMultOneByte : 8*8=8/16 bit multiplication */
3563 /*-----------------------------------------------------------------*/
3565 genMultOneByte (operand * left,
3569 sym_link *opetype = operandType (result);
3571 int size=AOP_SIZE(result);
3573 D(emitcode ("; genMultOneByte",""));
3575 if (size<1 || size>2) {
3576 // this should never happen
3577 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3578 AOP_SIZE(result), __FILE__, lineno);
3582 /* (if two literals: the value is computed before) */
3583 /* if one literal, literal on the right */
3584 if (AOP_TYPE (left) == AOP_LIT)
3589 //emitcode (";", "swapped left and right");
3592 if (SPEC_USIGN(opetype)
3593 // ignore the sign of left and right, what else can we do?
3594 || (SPEC_USIGN(operandType(left)) &&
3595 SPEC_USIGN(operandType(right)))) {
3596 // just an unsigned 8*8=8/16 multiply
3597 //emitcode (";","unsigned");
3598 // TODO: check for accumulator clash between left & right aops?
3599 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3600 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3601 emitcode ("mul", "ab");
3602 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3604 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3609 // we have to do a signed multiply
3611 //emitcode (";", "signed");
3612 emitcode ("clr", "F0"); // reset sign flag
3613 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3615 lbl=newiTempLabel(NULL);
3616 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3617 // left side is negative, 8-bit two's complement, this fails for -128
3618 emitcode ("setb", "F0"); // set sign flag
3619 emitcode ("cpl", "a");
3620 emitcode ("inc", "a");
3622 emitcode ("", "%05d$:", lbl->key+100);
3625 if (AOP_TYPE(right)==AOP_LIT) {
3626 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3627 /* AND literal negative */
3629 emitcode ("cpl", "F0"); // complement sign flag
3630 emitcode ("mov", "b,#0x%02x", -val);
3632 emitcode ("mov", "b,#0x%02x", val);
3635 lbl=newiTempLabel(NULL);
3636 emitcode ("mov", "b,a");
3637 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3638 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3639 // right side is negative, 8-bit two's complement
3640 emitcode ("cpl", "F0"); // complement sign flag
3641 emitcode ("cpl", "a");
3642 emitcode ("inc", "a");
3643 emitcode ("", "%05d$:", lbl->key+100);
3645 emitcode ("mul", "ab");
3647 lbl=newiTempLabel(NULL);
3648 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3649 // only ONE op was negative, we have to do a 8/16-bit two's complement
3650 emitcode ("cpl", "a"); // lsb
3652 emitcode ("inc", "a");
3654 emitcode ("add", "a,#1");
3655 emitcode ("xch", "a,b");
3656 emitcode ("cpl", "a"); // msb
3657 emitcode ("addc", "a,#0");
3658 emitcode ("xch", "a,b");
3661 emitcode ("", "%05d$:", lbl->key+100);
3662 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3664 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3668 /*-----------------------------------------------------------------*/
3669 /* genMult - generates code for multiplication */
3670 /*-----------------------------------------------------------------*/
3672 genMult (iCode * ic)
3674 operand *left = IC_LEFT (ic);
3675 operand *right = IC_RIGHT (ic);
3676 operand *result = IC_RESULT (ic);
3678 D(emitcode ("; genMult",""));
3680 /* assign the amsops */
3681 aopOp (left, ic, FALSE);
3682 aopOp (right, ic, FALSE);
3683 aopOp (result, ic, TRUE);
3685 /* special cases first */
3687 if (AOP_TYPE (left) == AOP_CRY &&
3688 AOP_TYPE (right) == AOP_CRY)
3690 genMultbits (left, right, result);
3694 /* if both are of size == 1 */
3695 #if 0 // one of them can be a sloc shared with the result
3696 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3698 if (getSize(operandType(left)) == 1 &&
3699 getSize(operandType(right)) == 1)
3702 genMultOneByte (left, right, result);
3706 /* should have been converted to function call */
3707 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3708 getSize(OP_SYMBOL(right)->type));
3712 freeAsmop (result, NULL, ic, TRUE);
3713 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3714 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3717 /*-----------------------------------------------------------------*/
3718 /* genDivbits :- division of bits */
3719 /*-----------------------------------------------------------------*/
3721 genDivbits (operand * left,
3728 D(emitcode ("; genDivbits",""));
3730 /* the result must be bit */
3731 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3732 l = aopGet (AOP (left), 0, FALSE, FALSE);
3736 emitcode ("div", "ab");
3737 emitcode ("rrc", "a");
3738 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3741 /*-----------------------------------------------------------------*/
3742 /* genDivOneByte : 8 bit division */
3743 /*-----------------------------------------------------------------*/
3745 genDivOneByte (operand * left,
3749 sym_link *opetype = operandType (result);
3754 D(emitcode ("; genDivOneByte",""));
3756 size = AOP_SIZE (result) - 1;
3758 /* signed or unsigned */
3759 if (SPEC_USIGN (opetype))
3761 /* unsigned is easy */
3762 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3763 l = aopGet (AOP (left), 0, FALSE, FALSE);
3765 emitcode ("div", "ab");
3766 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3768 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3772 /* signed is a little bit more difficult */
3774 /* save the signs of the operands */
3775 l = aopGet (AOP (left), 0, FALSE, FALSE);
3777 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3778 emitcode ("push", "acc"); /* save it on the stack */
3780 /* now sign adjust for both left & right */
3781 l = aopGet (AOP (right), 0, FALSE, FALSE);
3783 lbl = newiTempLabel (NULL);
3784 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3785 emitcode ("cpl", "a");
3786 emitcode ("inc", "a");
3787 emitcode ("", "%05d$:", (lbl->key + 100));
3788 emitcode ("mov", "b,a");
3790 /* sign adjust left side */
3791 l = aopGet (AOP (left), 0, FALSE, FALSE);
3794 lbl = newiTempLabel (NULL);
3795 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3796 emitcode ("cpl", "a");
3797 emitcode ("inc", "a");
3798 emitcode ("", "%05d$:", (lbl->key + 100));
3800 /* now the division */
3801 emitcode ("div", "ab");
3802 /* we are interested in the lower order
3804 emitcode ("mov", "b,a");
3805 lbl = newiTempLabel (NULL);
3806 emitcode ("pop", "acc");
3807 /* if there was an over flow we don't
3808 adjust the sign of the result */
3809 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3810 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3812 emitcode ("clr", "a");
3813 emitcode ("subb", "a,b");
3814 emitcode ("mov", "b,a");
3815 emitcode ("", "%05d$:", (lbl->key + 100));
3817 /* now we are done */
3818 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3821 emitcode ("mov", "c,b.7");
3822 emitcode ("subb", "a,acc");
3825 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3829 /*-----------------------------------------------------------------*/
3830 /* genDiv - generates code for division */
3831 /*-----------------------------------------------------------------*/
3835 operand *left = IC_LEFT (ic);
3836 operand *right = IC_RIGHT (ic);
3837 operand *result = IC_RESULT (ic);
3839 D(emitcode ("; genDiv",""));
3841 /* assign the amsops */
3842 aopOp (left, ic, FALSE);
3843 aopOp (right, ic, FALSE);
3844 aopOp (result, ic, TRUE);
3846 /* special cases first */
3848 if (AOP_TYPE (left) == AOP_CRY &&
3849 AOP_TYPE (right) == AOP_CRY)
3851 genDivbits (left, right, result);
3855 /* if both are of size == 1 */
3856 if (AOP_SIZE (left) == 1 &&
3857 AOP_SIZE (right) == 1)
3859 genDivOneByte (left, right, result);
3863 /* should have been converted to function call */
3866 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3867 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3868 freeAsmop (result, NULL, ic, TRUE);
3871 /*-----------------------------------------------------------------*/
3872 /* genModbits :- modulus of bits */
3873 /*-----------------------------------------------------------------*/
3875 genModbits (operand * left,
3882 D(emitcode ("; genModbits",""));
3884 /* the result must be bit */
3885 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3886 l = aopGet (AOP (left), 0, FALSE, FALSE);
3890 emitcode ("div", "ab");
3891 emitcode ("mov", "a,b");
3892 emitcode ("rrc", "a");
3893 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3896 /*-----------------------------------------------------------------*/
3897 /* genModOneByte : 8 bit modulus */
3898 /*-----------------------------------------------------------------*/
3900 genModOneByte (operand * left,
3904 sym_link *opetype = operandType (result);
3908 D(emitcode ("; genModOneByte",""));
3910 /* signed or unsigned */
3911 if (SPEC_USIGN (opetype))
3913 /* unsigned is easy */
3914 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3915 l = aopGet (AOP (left), 0, FALSE, FALSE);
3917 emitcode ("div", "ab");
3918 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3922 /* signed is a little bit more difficult */
3924 /* save the signs of the operands */
3925 l = aopGet (AOP (left), 0, FALSE, FALSE);
3928 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3929 emitcode ("push", "acc"); /* save it on the stack */
3931 /* now sign adjust for both left & right */
3932 l = aopGet (AOP (right), 0, FALSE, FALSE);
3935 lbl = newiTempLabel (NULL);
3936 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3937 emitcode ("cpl", "a");
3938 emitcode ("inc", "a");
3939 emitcode ("", "%05d$:", (lbl->key + 100));
3940 emitcode ("mov", "b,a");
3942 /* sign adjust left side */
3943 l = aopGet (AOP (left), 0, FALSE, FALSE);
3946 lbl = newiTempLabel (NULL);
3947 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3948 emitcode ("cpl", "a");
3949 emitcode ("inc", "a");
3950 emitcode ("", "%05d$:", (lbl->key + 100));
3952 /* now the multiplication */
3953 emitcode ("div", "ab");
3954 /* we are interested in the lower order
3956 lbl = newiTempLabel (NULL);
3957 emitcode ("pop", "acc");
3958 /* if there was an over flow we don't
3959 adjust the sign of the result */
3960 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3961 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3963 emitcode ("clr", "a");
3964 emitcode ("subb", "a,b");
3965 emitcode ("mov", "b,a");
3966 emitcode ("", "%05d$:", (lbl->key + 100));
3968 /* now we are done */
3969 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3973 /*-----------------------------------------------------------------*/
3974 /* genMod - generates code for division */
3975 /*-----------------------------------------------------------------*/
3979 operand *left = IC_LEFT (ic);
3980 operand *right = IC_RIGHT (ic);
3981 operand *result = IC_RESULT (ic);
3983 D(emitcode ("; genMod",""));
3985 /* assign the amsops */
3986 aopOp (left, ic, FALSE);
3987 aopOp (right, ic, FALSE);
3988 aopOp (result, ic, TRUE);
3990 /* special cases first */
3992 if (AOP_TYPE (left) == AOP_CRY &&
3993 AOP_TYPE (right) == AOP_CRY)
3995 genModbits (left, right, result);
3999 /* if both are of size == 1 */
4000 if (AOP_SIZE (left) == 1 &&
4001 AOP_SIZE (right) == 1)
4003 genModOneByte (left, right, result);
4007 /* should have been converted to function call */
4011 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4012 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4013 freeAsmop (result, NULL, ic, TRUE);
4016 /*-----------------------------------------------------------------*/
4017 /* genIfxJump :- will create a jump depending on the ifx */
4018 /*-----------------------------------------------------------------*/
4020 genIfxJump (iCode * ic, char *jval)
4023 symbol *tlbl = newiTempLabel (NULL);
4026 D(emitcode ("; genIfxJump",""));
4028 /* if true label then we jump if condition
4032 jlbl = IC_TRUE (ic);
4033 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4034 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4038 /* false label is present */
4039 jlbl = IC_FALSE (ic);
4040 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4041 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4043 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4044 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4046 emitcode (inst, "%05d$", tlbl->key + 100);
4047 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4048 emitcode ("", "%05d$:", tlbl->key + 100);
4050 /* mark the icode as generated */
4054 /*-----------------------------------------------------------------*/
4055 /* genCmp :- greater or less than comparison */
4056 /*-----------------------------------------------------------------*/
4058 genCmp (operand * left, operand * right,
4059 operand * result, iCode * ifx, int sign, iCode *ic)
4061 int size, offset = 0;
4062 unsigned long lit = 0L;
4065 D(emitcode ("; genCmp",""));
4067 /* if left & right are bit variables */
4068 if (AOP_TYPE (left) == AOP_CRY &&
4069 AOP_TYPE (right) == AOP_CRY)
4071 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4072 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4076 /* subtract right from left if at the
4077 end the carry flag is set then we know that
4078 left is greater than right */
4079 size = max (AOP_SIZE (left), AOP_SIZE (right));
4081 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4082 if ((size == 1) && !sign &&
4083 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4085 symbol *lbl = newiTempLabel (NULL);
4086 emitcode ("cjne", "%s,%s,%05d$",
4087 aopGet (AOP (left), offset, FALSE, FALSE),
4088 aopGet (AOP (right), offset, FALSE, FALSE),
4090 emitcode ("", "%05d$:", lbl->key + 100);
4094 if (AOP_TYPE (right) == AOP_LIT)
4096 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4097 /* optimize if(x < 0) or if(x >= 0) */
4106 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4107 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4109 genIfxJump (ifx, "acc.7");
4113 emitcode ("rlc", "a");
4121 rightInB = aopGetUsesAcc(AOP (right), offset);
4123 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4124 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4125 if (sign && size == 0)
4127 emitcode ("xrl", "a,#0x80");
4128 if (AOP_TYPE (right) == AOP_LIT)
4130 unsigned long lit = (unsigned long)
4131 floatFromVal (AOP (right)->aopu.aop_lit);
4132 emitcode ("subb", "a,#0x%02x",
4133 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4138 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4139 emitcode ("xrl", "b,#0x80");
4140 emitcode ("subb", "a,b");
4146 emitcode ("subb", "a,b");
4148 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4156 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4157 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4158 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4164 /* if the result is used in the next
4165 ifx conditional branch then generate
4166 code a little differently */
4168 genIfxJump (ifx, "c");
4171 /* leave the result in acc */
4175 /*-----------------------------------------------------------------*/
4176 /* genCmpGt :- greater than comparison */
4177 /*-----------------------------------------------------------------*/
4179 genCmpGt (iCode * ic, iCode * ifx)
4181 operand *left, *right, *result;
4182 sym_link *letype, *retype;
4185 D(emitcode ("; genCmpGt",""));
4187 left = IC_LEFT (ic);
4188 right = IC_RIGHT (ic);
4189 result = IC_RESULT (ic);
4191 letype = getSpec (operandType (left));
4192 retype = getSpec (operandType (right));
4193 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4194 /* assign the amsops */
4195 aopOp (left, ic, FALSE);
4196 aopOp (right, ic, FALSE);
4197 aopOp (result, ic, TRUE);
4199 genCmp (right, left, result, ifx, sign,ic);
4201 freeAsmop (result, NULL, ic, TRUE);
4204 /*-----------------------------------------------------------------*/
4205 /* genCmpLt - less than comparisons */
4206 /*-----------------------------------------------------------------*/
4208 genCmpLt (iCode * ic, iCode * ifx)
4210 operand *left, *right, *result;
4211 sym_link *letype, *retype;
4214 D(emitcode ("; genCmpLt",""));
4216 left = IC_LEFT (ic);
4217 right = IC_RIGHT (ic);
4218 result = IC_RESULT (ic);
4220 letype = getSpec (operandType (left));
4221 retype = getSpec (operandType (right));
4222 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4224 /* assign the amsops */
4225 aopOp (left, ic, FALSE);
4226 aopOp (right, ic, FALSE);
4227 aopOp (result, ic, TRUE);
4229 genCmp (left, right, result, ifx, sign,ic);
4231 freeAsmop (result, NULL, ic, TRUE);
4234 /*-----------------------------------------------------------------*/
4235 /* gencjneshort - compare and jump if not equal */
4236 /*-----------------------------------------------------------------*/
4238 gencjneshort (operand * left, operand * right, symbol * lbl)
4240 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4242 unsigned long lit = 0L;
4244 /* if the left side is a literal or
4245 if the right is in a pointer register and left
4247 if ((AOP_TYPE (left) == AOP_LIT) ||
4248 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4254 if (AOP_TYPE (right) == AOP_LIT)
4255 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4257 /* if the right side is a literal then anything goes */
4258 if (AOP_TYPE (right) == AOP_LIT &&
4259 AOP_TYPE (left) != AOP_DIR &&
4260 AOP_TYPE (left) != AOP_IMMD)
4264 emitcode ("cjne", "%s,%s,%05d$",
4265 aopGet (AOP (left), offset, FALSE, FALSE),
4266 aopGet (AOP (right), offset, FALSE, FALSE),
4272 /* if the right side is in a register or in direct space or
4273 if the left is a pointer register & right is not */
4274 else if (AOP_TYPE (right) == AOP_REG ||
4275 AOP_TYPE (right) == AOP_DIR ||
4276 AOP_TYPE (right) == AOP_LIT ||
4277 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4278 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4282 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4283 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4284 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4285 emitcode ("jnz", "%05d$", lbl->key + 100);
4287 emitcode ("cjne", "a,%s,%05d$",
4288 aopGet (AOP (right), offset, FALSE, TRUE),
4295 /* right is a pointer reg need both a & b */
4298 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4299 if (strcmp (l, "b"))
4300 emitcode ("mov", "b,%s", l);
4301 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4302 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4308 /*-----------------------------------------------------------------*/
4309 /* gencjne - compare and jump if not equal */
4310 /*-----------------------------------------------------------------*/
4312 gencjne (operand * left, operand * right, symbol * lbl)
4314 symbol *tlbl = newiTempLabel (NULL);
4316 gencjneshort (left, right, lbl);
4318 emitcode ("mov", "a,%s", one);
4319 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4320 emitcode ("", "%05d$:", lbl->key + 100);
4321 emitcode ("clr", "a");
4322 emitcode ("", "%05d$:", tlbl->key + 100);
4325 /*-----------------------------------------------------------------*/
4326 /* genCmpEq - generates code for equal to */
4327 /*-----------------------------------------------------------------*/
4329 genCmpEq (iCode * ic, iCode * ifx)
4331 operand *left, *right, *result;
4333 D(emitcode ("; genCmpEq",""));
4335 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4336 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4337 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4339 /* if literal, literal on the right or
4340 if the right is in a pointer register and left
4342 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4343 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4345 operand *t = IC_RIGHT (ic);
4346 IC_RIGHT (ic) = IC_LEFT (ic);
4350 if (ifx && !AOP_SIZE (result))
4353 /* if they are both bit variables */
4354 if (AOP_TYPE (left) == AOP_CRY &&
4355 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4357 if (AOP_TYPE (right) == AOP_LIT)
4359 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4362 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4363 emitcode ("cpl", "c");
4367 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4371 emitcode ("clr", "c");
4373 /* AOP_TYPE(right) == AOP_CRY */
4377 symbol *lbl = newiTempLabel (NULL);
4378 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4379 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4380 emitcode ("cpl", "c");
4381 emitcode ("", "%05d$:", (lbl->key + 100));
4383 /* if true label then we jump if condition
4385 tlbl = newiTempLabel (NULL);
4388 emitcode ("jnc", "%05d$", tlbl->key + 100);
4389 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4393 emitcode ("jc", "%05d$", tlbl->key + 100);
4394 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4396 emitcode ("", "%05d$:", tlbl->key + 100);
4400 tlbl = newiTempLabel (NULL);
4401 gencjneshort (left, right, tlbl);
4404 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4405 emitcode ("", "%05d$:", tlbl->key + 100);
4409 symbol *lbl = newiTempLabel (NULL);
4410 emitcode ("sjmp", "%05d$", lbl->key + 100);
4411 emitcode ("", "%05d$:", tlbl->key + 100);
4412 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4413 emitcode ("", "%05d$:", lbl->key + 100);
4416 /* mark the icode as generated */
4421 /* if they are both bit variables */
4422 if (AOP_TYPE (left) == AOP_CRY &&
4423 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4425 if (AOP_TYPE (right) == AOP_LIT)
4427 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4430 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4431 emitcode ("cpl", "c");
4435 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4439 emitcode ("clr", "c");
4441 /* AOP_TYPE(right) == AOP_CRY */
4445 symbol *lbl = newiTempLabel (NULL);
4446 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4447 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4448 emitcode ("cpl", "c");
4449 emitcode ("", "%05d$:", (lbl->key + 100));
4452 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4459 genIfxJump (ifx, "c");
4462 /* if the result is used in an arithmetic operation
4463 then put the result in place */
4468 gencjne (left, right, newiTempLabel (NULL));
4469 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4471 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4476 genIfxJump (ifx, "a");
4479 /* if the result is used in an arithmetic operation
4480 then put the result in place */
4481 if (AOP_TYPE (result) != AOP_CRY)
4483 /* leave the result in acc */
4487 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4488 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4489 freeAsmop (result, NULL, ic, TRUE);
4492 /*-----------------------------------------------------------------*/
4493 /* ifxForOp - returns the icode containing the ifx for operand */
4494 /*-----------------------------------------------------------------*/
4496 ifxForOp (operand * op, iCode * ic)
4498 /* if true symbol then needs to be assigned */
4499 if (IS_TRUE_SYMOP (op))
4502 /* if this has register type condition and
4503 the next instruction is ifx with the same operand
4504 and live to of the operand is upto the ifx only then */
4506 ic->next->op == IFX &&
4507 IC_COND (ic->next)->key == op->key &&
4508 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4514 /*-----------------------------------------------------------------*/
4515 /* hasInc - operand is incremented before any other use */
4516 /*-----------------------------------------------------------------*/
4518 hasInc (operand *op, iCode *ic,int osize)
4520 sym_link *type = operandType(op);
4521 sym_link *retype = getSpec (type);
4522 iCode *lic = ic->next;
4525 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4526 if (!IS_SYMOP(op)) return NULL;
4528 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4529 if (IS_AGGREGATE(type->next)) return NULL;
4530 if (osize != (isize = getSize(type->next))) return NULL;
4533 /* if operand of the form op = op + <sizeof *op> */
4534 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4535 isOperandEqual(IC_RESULT(lic),op) &&
4536 isOperandLiteral(IC_RIGHT(lic)) &&
4537 operandLitValue(IC_RIGHT(lic)) == isize) {
4540 /* if the operand used or deffed */
4541 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4544 /* if GOTO or IFX */
4545 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4551 /*-----------------------------------------------------------------*/
4552 /* genAndOp - for && operation */
4553 /*-----------------------------------------------------------------*/
4555 genAndOp (iCode * ic)
4557 operand *left, *right, *result;
4560 D(emitcode ("; genAndOp",""));
4562 /* note here that && operations that are in an
4563 if statement are taken away by backPatchLabels
4564 only those used in arthmetic operations remain */
4565 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4566 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4567 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4569 /* if both are bit variables */
4570 if (AOP_TYPE (left) == AOP_CRY &&
4571 AOP_TYPE (right) == AOP_CRY)
4573 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4574 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4579 tlbl = newiTempLabel (NULL);
4581 emitcode ("jz", "%05d$", tlbl->key + 100);
4583 emitcode ("", "%05d$:", tlbl->key + 100);
4587 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4588 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4589 freeAsmop (result, NULL, ic, TRUE);
4593 /*-----------------------------------------------------------------*/
4594 /* genOrOp - for || operation */
4595 /*-----------------------------------------------------------------*/
4597 genOrOp (iCode * ic)
4599 operand *left, *right, *result;
4602 D(emitcode ("; genOrOp",""));
4604 /* note here that || operations that are in an
4605 if statement are taken away by backPatchLabels
4606 only those used in arthmetic operations remain */
4607 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4608 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4609 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4611 /* if both are bit variables */
4612 if (AOP_TYPE (left) == AOP_CRY &&
4613 AOP_TYPE (right) == AOP_CRY)
4615 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4616 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4621 tlbl = newiTempLabel (NULL);
4623 emitcode ("jnz", "%05d$", tlbl->key + 100);
4625 emitcode ("", "%05d$:", tlbl->key + 100);
4629 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4630 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4631 freeAsmop (result, NULL, ic, TRUE);
4634 /*-----------------------------------------------------------------*/
4635 /* isLiteralBit - test if lit == 2^n */
4636 /*-----------------------------------------------------------------*/
4638 isLiteralBit (unsigned long lit)
4640 unsigned long pw[32] =
4641 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4642 0x100L, 0x200L, 0x400L, 0x800L,
4643 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4644 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4645 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4646 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4647 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4650 for (idx = 0; idx < 32; idx++)
4656 /*-----------------------------------------------------------------*/
4657 /* continueIfTrue - */
4658 /*-----------------------------------------------------------------*/
4660 continueIfTrue (iCode * ic)
4663 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4667 /*-----------------------------------------------------------------*/
4669 /*-----------------------------------------------------------------*/
4671 jumpIfTrue (iCode * ic)
4674 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4678 /*-----------------------------------------------------------------*/
4679 /* jmpTrueOrFalse - */
4680 /*-----------------------------------------------------------------*/
4682 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4684 // ugly but optimized by peephole
4687 symbol *nlbl = newiTempLabel (NULL);
4688 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4689 emitcode ("", "%05d$:", tlbl->key + 100);
4690 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4691 emitcode ("", "%05d$:", nlbl->key + 100);
4695 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4696 emitcode ("", "%05d$:", tlbl->key + 100);
4701 /*-----------------------------------------------------------------*/
4702 /* genAnd - code for and */
4703 /*-----------------------------------------------------------------*/
4705 genAnd (iCode * ic, iCode * ifx)
4707 operand *left, *right, *result;
4708 int size, offset = 0;
4709 unsigned long lit = 0L;
4713 D(emitcode ("; genAnd",""));
4715 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4716 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4717 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4720 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4722 AOP_TYPE (left), AOP_TYPE (right));
4723 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4725 AOP_SIZE (left), AOP_SIZE (right));
4728 /* if left is a literal & right is not then exchange them */
4729 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4730 AOP_NEEDSACC (left))
4732 operand *tmp = right;
4737 /* if result = right then exchange them */
4738 if (sameRegs (AOP (result), AOP (right)))
4740 operand *tmp = right;
4745 /* if right is bit then exchange them */
4746 if (AOP_TYPE (right) == AOP_CRY &&
4747 AOP_TYPE (left) != AOP_CRY)
4749 operand *tmp = right;
4753 if (AOP_TYPE (right) == AOP_LIT)
4754 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4756 size = AOP_SIZE (result);
4759 // result = bit & yy;
4760 if (AOP_TYPE (left) == AOP_CRY)
4762 // c = bit & literal;
4763 if (AOP_TYPE (right) == AOP_LIT)
4767 if (size && sameRegs (AOP (result), AOP (left)))
4770 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4775 if (size && (AOP_TYPE (result) == AOP_CRY))
4777 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4780 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4785 emitcode ("clr", "c");
4790 if (AOP_TYPE (right) == AOP_CRY)
4793 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4794 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4799 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4801 emitcode ("rrc", "a");
4802 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4810 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4811 genIfxJump (ifx, "c");
4815 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4816 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4817 if ((AOP_TYPE (right) == AOP_LIT) &&
4818 (AOP_TYPE (result) == AOP_CRY) &&
4819 (AOP_TYPE (left) != AOP_CRY))
4821 int posbit = isLiteralBit (lit);
4826 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4829 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4835 sprintf (buffer, "acc.%d", posbit & 0x07);
4836 genIfxJump (ifx, buffer);
4843 symbol *tlbl = newiTempLabel (NULL);
4844 int sizel = AOP_SIZE (left);
4846 emitcode ("setb", "c");
4849 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4851 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4853 if ((posbit = isLiteralBit (bytelit)) != 0)
4854 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4857 if (bytelit != 0x0FFL)
4858 emitcode ("anl", "a,%s",
4859 aopGet (AOP (right), offset, FALSE, TRUE));
4860 emitcode ("jnz", "%05d$", tlbl->key + 100);
4865 // bit = left & literal
4868 emitcode ("clr", "c");
4869 emitcode ("", "%05d$:", tlbl->key + 100);
4871 // if(left & literal)
4875 jmpTrueOrFalse (ifx, tlbl);
4883 /* if left is same as result */
4884 if (sameRegs (AOP (result), AOP (left)))
4886 for (; size--; offset++)
4888 if (AOP_TYPE (right) == AOP_LIT)
4890 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4892 else if (bytelit == 0)
4894 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4896 else if (IS_AOP_PREG (result))
4898 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4899 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4900 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4903 emitcode ("anl", "%s,%s",
4904 aopGet (AOP (left), offset, FALSE, TRUE),
4905 aopGet (AOP (right), offset, FALSE, FALSE));
4909 if (AOP_TYPE (left) == AOP_ACC)
4910 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4913 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4914 if (IS_AOP_PREG (result))
4916 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4917 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4921 emitcode ("anl", "%s,a",
4922 aopGet (AOP (left), offset, FALSE, TRUE));
4929 // left & result in different registers
4930 if (AOP_TYPE (result) == AOP_CRY)
4933 // if(size), result in bit
4934 // if(!size && ifx), conditional oper: if(left & right)
4935 symbol *tlbl = newiTempLabel (NULL);
4936 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4938 emitcode ("setb", "c");
4941 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4942 emitcode ("anl", "a,%s",
4943 aopGet (AOP (right), offset, FALSE, FALSE));
4945 if (AOP_TYPE(left)==AOP_ACC) {
4946 emitcode("mov", "b,a");
4947 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4948 emitcode("anl", "a,b");
4950 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4951 emitcode ("anl", "a,%s",
4952 aopGet (AOP (left), offset, FALSE, FALSE));
4955 emitcode ("jnz", "%05d$", tlbl->key + 100);
4961 emitcode ("", "%05d$:", tlbl->key + 100);
4965 jmpTrueOrFalse (ifx, tlbl);
4969 for (; (size--); offset++)
4972 // result = left & right
4973 if (AOP_TYPE (right) == AOP_LIT)
4975 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4977 aopPut (AOP (result),
4978 aopGet (AOP (left), offset, FALSE, FALSE),
4980 isOperandVolatile (result, FALSE));
4983 else if (bytelit == 0)
4985 /* dummy read of volatile operand */
4986 if (isOperandVolatile (left, FALSE))
4987 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4988 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4992 // faster than result <- left, anl result,right
4993 // and better if result is SFR
4994 if (AOP_TYPE (left) == AOP_ACC)
4995 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4998 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4999 emitcode ("anl", "a,%s",
5000 aopGet (AOP (left), offset, FALSE, FALSE));
5002 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5008 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5009 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5010 freeAsmop (result, NULL, ic, TRUE);
5013 /*-----------------------------------------------------------------*/
5014 /* genOr - code for or */
5015 /*-----------------------------------------------------------------*/
5017 genOr (iCode * ic, iCode * ifx)
5019 operand *left, *right, *result;
5020 int size, offset = 0;
5021 unsigned long lit = 0L;
5023 D(emitcode ("; genOr",""));
5025 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5026 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5027 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5030 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5032 AOP_TYPE (left), AOP_TYPE (right));
5033 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5035 AOP_SIZE (left), AOP_SIZE (right));
5038 /* if left is a literal & right is not then exchange them */
5039 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5040 AOP_NEEDSACC (left))
5042 operand *tmp = right;
5047 /* if result = right then exchange them */
5048 if (sameRegs (AOP (result), AOP (right)))
5050 operand *tmp = right;
5055 /* if right is bit then exchange them */
5056 if (AOP_TYPE (right) == AOP_CRY &&
5057 AOP_TYPE (left) != AOP_CRY)
5059 operand *tmp = right;
5063 if (AOP_TYPE (right) == AOP_LIT)
5064 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5066 size = AOP_SIZE (result);
5070 if (AOP_TYPE (left) == AOP_CRY)
5072 if (AOP_TYPE (right) == AOP_LIT)
5074 // c = bit | literal;
5077 // lit != 0 => result = 1
5078 if (AOP_TYPE (result) == AOP_CRY)
5081 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5083 continueIfTrue (ifx);
5086 emitcode ("setb", "c");
5090 // lit == 0 => result = left
5091 if (size && sameRegs (AOP (result), AOP (left)))
5093 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5098 if (AOP_TYPE (right) == AOP_CRY)
5101 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5102 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5107 symbol *tlbl = newiTempLabel (NULL);
5108 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5109 emitcode ("setb", "c");
5110 emitcode ("jb", "%s,%05d$",
5111 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5113 emitcode ("jnz", "%05d$", tlbl->key + 100);
5114 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5116 jmpTrueOrFalse (ifx, tlbl);
5122 emitcode ("", "%05d$:", tlbl->key + 100);
5131 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5132 genIfxJump (ifx, "c");
5136 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5137 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5138 if ((AOP_TYPE (right) == AOP_LIT) &&
5139 (AOP_TYPE (result) == AOP_CRY) &&
5140 (AOP_TYPE (left) != AOP_CRY))
5146 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5148 continueIfTrue (ifx);
5153 // lit = 0, result = boolean(left)
5155 emitcode ("setb", "c");
5159 symbol *tlbl = newiTempLabel (NULL);
5160 emitcode ("jnz", "%05d$", tlbl->key + 100);
5162 emitcode ("", "%05d$:", tlbl->key + 100);
5166 genIfxJump (ifx, "a");
5174 /* if left is same as result */
5175 if (sameRegs (AOP (result), AOP (left)))
5177 for (; size--; offset++)
5179 if (AOP_TYPE (right) == AOP_LIT)
5181 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5183 /* dummy read of volatile operand */
5184 if (isOperandVolatile (left, FALSE))
5185 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5189 else if (IS_AOP_PREG (left))
5191 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5192 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5193 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5196 emitcode ("orl", "%s,%s",
5197 aopGet (AOP (left), offset, FALSE, TRUE),
5198 aopGet (AOP (right), offset, FALSE, FALSE));
5202 if (AOP_TYPE (left) == AOP_ACC)
5203 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5206 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5207 if (IS_AOP_PREG (left))
5209 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5210 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5213 emitcode ("orl", "%s,a",
5214 aopGet (AOP (left), offset, FALSE, TRUE));
5221 // left & result in different registers
5222 if (AOP_TYPE (result) == AOP_CRY)
5225 // if(size), result in bit
5226 // if(!size && ifx), conditional oper: if(left | right)
5227 symbol *tlbl = newiTempLabel (NULL);
5228 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5230 emitcode ("setb", "c");
5233 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5234 emitcode ("orl", "a,%s",
5235 aopGet (AOP (right), offset, FALSE, FALSE));
5237 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5238 emitcode ("orl", "a,%s",
5239 aopGet (AOP (left), offset, FALSE, FALSE));
5241 emitcode ("jnz", "%05d$", tlbl->key + 100);
5247 emitcode ("", "%05d$:", tlbl->key + 100);
5251 jmpTrueOrFalse (ifx, tlbl);
5254 for (; (size--); offset++)
5257 // result = left & right
5258 if (AOP_TYPE (right) == AOP_LIT)
5260 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5262 aopPut (AOP (result),
5263 aopGet (AOP (left), offset, FALSE, FALSE),
5265 isOperandVolatile (result, FALSE));
5269 // faster than result <- left, anl result,right
5270 // and better if result is SFR
5271 if (AOP_TYPE (left) == AOP_ACC)
5272 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5275 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5276 emitcode ("orl", "a,%s",
5277 aopGet (AOP (left), offset, FALSE, FALSE));
5279 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5284 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5285 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5286 freeAsmop (result, NULL, ic, TRUE);
5289 /*-----------------------------------------------------------------*/
5290 /* genXor - code for xclusive or */
5291 /*-----------------------------------------------------------------*/
5293 genXor (iCode * ic, iCode * ifx)
5295 operand *left, *right, *result;
5296 int size, offset = 0;
5297 unsigned long lit = 0L;
5299 D(emitcode ("; genXor",""));
5301 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5302 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5303 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5306 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5308 AOP_TYPE (left), AOP_TYPE (right));
5309 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5311 AOP_SIZE (left), AOP_SIZE (right));
5314 /* if left is a literal & right is not ||
5315 if left needs acc & right does not */
5316 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5317 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5319 operand *tmp = right;
5324 /* if result = right then exchange them */
5325 if (sameRegs (AOP (result), AOP (right)))
5327 operand *tmp = right;
5332 /* if right is bit then exchange them */
5333 if (AOP_TYPE (right) == AOP_CRY &&
5334 AOP_TYPE (left) != AOP_CRY)
5336 operand *tmp = right;
5340 if (AOP_TYPE (right) == AOP_LIT)
5341 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5343 size = AOP_SIZE (result);
5347 if (AOP_TYPE (left) == AOP_CRY)
5349 if (AOP_TYPE (right) == AOP_LIT)
5351 // c = bit & literal;
5354 // lit>>1 != 0 => result = 1
5355 if (AOP_TYPE (result) == AOP_CRY)
5358 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5360 continueIfTrue (ifx);
5363 emitcode ("setb", "c");
5370 // lit == 0, result = left
5371 if (size && sameRegs (AOP (result), AOP (left)))
5373 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5377 // lit == 1, result = not(left)
5378 if (size && sameRegs (AOP (result), AOP (left)))
5380 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5385 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5386 emitcode ("cpl", "c");
5395 symbol *tlbl = newiTempLabel (NULL);
5396 if (AOP_TYPE (right) == AOP_CRY)
5399 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5403 int sizer = AOP_SIZE (right);
5405 // if val>>1 != 0, result = 1
5406 emitcode ("setb", "c");
5409 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5411 // test the msb of the lsb
5412 emitcode ("anl", "a,#0xfe");
5413 emitcode ("jnz", "%05d$", tlbl->key + 100);
5417 emitcode ("rrc", "a");
5419 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5420 emitcode ("cpl", "c");
5421 emitcode ("", "%05d$:", (tlbl->key + 100));
5428 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5429 genIfxJump (ifx, "c");
5433 if (sameRegs (AOP (result), AOP (left)))
5435 /* if left is same as result */
5436 for (; size--; offset++)
5438 if (AOP_TYPE (right) == AOP_LIT)
5440 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5442 else if (IS_AOP_PREG (left))
5444 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5445 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5446 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5449 emitcode ("xrl", "%s,%s",
5450 aopGet (AOP (left), offset, FALSE, TRUE),
5451 aopGet (AOP (right), offset, FALSE, FALSE));
5455 if (AOP_TYPE (left) == AOP_ACC)
5456 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5459 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5460 if (IS_AOP_PREG (left))
5462 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5463 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5466 emitcode ("xrl", "%s,a",
5467 aopGet (AOP (left), offset, FALSE, TRUE));
5474 // left & result in different registers
5475 if (AOP_TYPE (result) == AOP_CRY)
5478 // if(size), result in bit
5479 // if(!size && ifx), conditional oper: if(left ^ right)
5480 symbol *tlbl = newiTempLabel (NULL);
5481 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5483 emitcode ("setb", "c");
5486 if ((AOP_TYPE (right) == AOP_LIT) &&
5487 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5489 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5493 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5494 emitcode ("xrl", "a,%s",
5495 aopGet (AOP (right), offset, FALSE, FALSE));
5497 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5498 emitcode ("xrl", "a,%s",
5499 aopGet (AOP (left), offset, FALSE, FALSE));
5502 emitcode ("jnz", "%05d$", tlbl->key + 100);
5508 emitcode ("", "%05d$:", tlbl->key + 100);
5512 jmpTrueOrFalse (ifx, tlbl);
5515 for (; (size--); offset++)
5518 // result = left & right
5519 if (AOP_TYPE (right) == AOP_LIT)
5521 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5523 aopPut (AOP (result),
5524 aopGet (AOP (left), offset, FALSE, FALSE),
5526 isOperandVolatile (result, FALSE));
5530 // faster than result <- left, anl result,right
5531 // and better if result is SFR
5532 if (AOP_TYPE (left) == AOP_ACC)
5533 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5536 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5537 emitcode ("xrl", "a,%s",
5538 aopGet (AOP (left), offset, FALSE, TRUE));
5540 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5545 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5546 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5547 freeAsmop (result, NULL, ic, TRUE);
5550 /*-----------------------------------------------------------------*/
5551 /* genInline - write the inline code out */
5552 /*-----------------------------------------------------------------*/
5554 genInline (iCode * ic)
5556 char *buffer, *bp, *bp1;
5558 D(emitcode ("; genInline",""));
5560 _G.inLine += (!options.asmpeep);
5562 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5563 strcpy (buffer, IC_INLINE (ic));
5565 /* emit each line as a code */
5590 /* emitcode("",buffer); */
5591 _G.inLine -= (!options.asmpeep);
5594 /*-----------------------------------------------------------------*/
5595 /* genRRC - rotate right with carry */
5596 /*-----------------------------------------------------------------*/
5600 operand *left, *result;
5601 int size, offset = 0;
5604 D(emitcode ("; genRRC",""));
5606 /* rotate right with carry */
5607 left = IC_LEFT (ic);
5608 result = IC_RESULT (ic);
5609 aopOp (left, ic, FALSE);
5610 aopOp (result, ic, FALSE);
5612 /* move it to the result */
5613 size = AOP_SIZE (result);
5615 if (size == 1) { /* special case for 1 byte */
5616 l = aopGet (AOP (left), offset, FALSE, FALSE);
5618 emitcode ("rr", "a");
5624 l = aopGet (AOP (left), offset, FALSE, FALSE);
5626 emitcode ("rrc", "a");
5627 if (AOP_SIZE (result) > 1)
5628 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5630 /* now we need to put the carry into the
5631 highest order byte of the result */
5632 if (AOP_SIZE (result) > 1)
5634 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5637 emitcode ("mov", "acc.7,c");
5639 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5640 freeAsmop (left, NULL, ic, TRUE);
5641 freeAsmop (result, NULL, ic, TRUE);
5644 /*-----------------------------------------------------------------*/
5645 /* genRLC - generate code for rotate left with carry */
5646 /*-----------------------------------------------------------------*/
5650 operand *left, *result;
5651 int size, offset = 0;
5654 D(emitcode ("; genRLC",""));
5656 /* rotate right with carry */
5657 left = IC_LEFT (ic);
5658 result = IC_RESULT (ic);
5659 aopOp (left, ic, FALSE);
5660 aopOp (result, ic, FALSE);
5662 /* move it to the result */
5663 size = AOP_SIZE (result);
5667 l = aopGet (AOP (left), offset, FALSE, FALSE);
5669 if (size == 0) { /* special case for 1 byte */
5673 emitcode ("add", "a,acc");
5674 if (AOP_SIZE (result) > 1)
5675 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5678 l = aopGet (AOP (left), offset, FALSE, FALSE);
5680 emitcode ("rlc", "a");
5681 if (AOP_SIZE (result) > 1)
5682 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5685 /* now we need to put the carry into the
5686 highest order byte of the result */
5687 if (AOP_SIZE (result) > 1)
5689 l = aopGet (AOP (result), 0, FALSE, FALSE);
5692 emitcode ("mov", "acc.0,c");
5694 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5695 freeAsmop (left, NULL, ic, TRUE);
5696 freeAsmop (result, NULL, ic, TRUE);
5699 /*-----------------------------------------------------------------*/
5700 /* genGetHbit - generates code get highest order bit */
5701 /*-----------------------------------------------------------------*/
5703 genGetHbit (iCode * ic)
5705 operand *left, *result;
5707 D(emitcode ("; genGetHbit",""));
5709 left = IC_LEFT (ic);
5710 result = IC_RESULT (ic);
5711 aopOp (left, ic, FALSE);
5712 aopOp (result, ic, FALSE);
5714 /* get the highest order byte into a */
5715 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5716 if (AOP_TYPE (result) == AOP_CRY)
5718 emitcode ("rlc", "a");
5723 emitcode ("rl", "a");
5724 emitcode ("anl", "a,#0x01");
5729 freeAsmop (left, NULL, ic, TRUE);
5730 freeAsmop (result, NULL, ic, TRUE);
5733 /*-----------------------------------------------------------------*/
5734 /* AccRol - rotate left accumulator by known count */
5735 /*-----------------------------------------------------------------*/
5737 AccRol (int shCount)
5739 shCount &= 0x0007; // shCount : 0..7
5746 emitcode ("rl", "a");
5749 emitcode ("rl", "a");
5750 emitcode ("rl", "a");
5753 emitcode ("swap", "a");
5754 emitcode ("rr", "a");
5757 emitcode ("swap", "a");
5760 emitcode ("swap", "a");
5761 emitcode ("rl", "a");
5764 emitcode ("rr", "a");
5765 emitcode ("rr", "a");
5768 emitcode ("rr", "a");
5773 /*-----------------------------------------------------------------*/
5774 /* AccLsh - left shift accumulator by known count */
5775 /*-----------------------------------------------------------------*/
5777 AccLsh (int shCount)
5782 emitcode ("add", "a,acc");
5783 else if (shCount == 2)
5785 emitcode ("add", "a,acc");
5786 emitcode ("add", "a,acc");
5790 /* rotate left accumulator */
5792 /* and kill the lower order bits */
5793 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5798 /*-----------------------------------------------------------------*/
5799 /* AccRsh - right shift accumulator by known count */
5800 /*-----------------------------------------------------------------*/
5802 AccRsh (int shCount)
5809 emitcode ("rrc", "a");
5813 /* rotate right accumulator */
5814 AccRol (8 - shCount);
5815 /* and kill the higher order bits */
5816 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5821 /*-----------------------------------------------------------------*/
5822 /* AccSRsh - signed right shift accumulator by known count */
5823 /*-----------------------------------------------------------------*/
5825 AccSRsh (int shCount)
5832 emitcode ("mov", "c,acc.7");
5833 emitcode ("rrc", "a");
5835 else if (shCount == 2)
5837 emitcode ("mov", "c,acc.7");
5838 emitcode ("rrc", "a");
5839 emitcode ("mov", "c,acc.7");
5840 emitcode ("rrc", "a");
5844 tlbl = newiTempLabel (NULL);
5845 /* rotate right accumulator */
5846 AccRol (8 - shCount);
5847 /* and kill the higher order bits */
5848 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5849 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5850 emitcode ("orl", "a,#0x%02x",
5851 (unsigned char) ~SRMask[shCount]);
5852 emitcode ("", "%05d$:", tlbl->key + 100);
5857 /*-----------------------------------------------------------------*/
5858 /* shiftR1Left2Result - shift right one byte from left to result */
5859 /*-----------------------------------------------------------------*/
5861 shiftR1Left2Result (operand * left, int offl,
5862 operand * result, int offr,
5863 int shCount, int sign)
5865 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5866 /* shift right accumulator */
5871 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5874 /*-----------------------------------------------------------------*/
5875 /* shiftL1Left2Result - shift left one byte from left to result */
5876 /*-----------------------------------------------------------------*/
5878 shiftL1Left2Result (operand * left, int offl,
5879 operand * result, int offr, int shCount)
5882 l = aopGet (AOP (left), offl, FALSE, FALSE);
5884 /* shift left accumulator */
5886 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5889 /*-----------------------------------------------------------------*/
5890 /* movLeft2Result - move byte from left to result */
5891 /*-----------------------------------------------------------------*/
5893 movLeft2Result (operand * left, int offl,
5894 operand * result, int offr, int sign)
5897 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5899 l = aopGet (AOP (left), offl, FALSE, FALSE);
5901 if (*l == '@' && (IS_AOP_PREG (result)))
5903 emitcode ("mov", "a,%s", l);
5904 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5909 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
5912 /* MSB sign in acc.7 ! */
5913 if (getDataSize (left) == offl + 1)
5915 emitcode ("mov", "a,%s", l);
5916 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5923 /*-----------------------------------------------------------------*/
5924 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5925 /*-----------------------------------------------------------------*/
5929 emitcode ("rrc", "a");
5930 emitcode ("xch", "a,%s", x);
5931 emitcode ("rrc", "a");
5932 emitcode ("xch", "a,%s", x);
5935 /*-----------------------------------------------------------------*/
5936 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5937 /*-----------------------------------------------------------------*/
5941 emitcode ("xch", "a,%s", x);
5942 emitcode ("rlc", "a");
5943 emitcode ("xch", "a,%s", x);
5944 emitcode ("rlc", "a");
5947 /*-----------------------------------------------------------------*/
5948 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5949 /*-----------------------------------------------------------------*/
5953 emitcode ("xch", "a,%s", x);
5954 emitcode ("add", "a,acc");
5955 emitcode ("xch", "a,%s", x);
5956 emitcode ("rlc", "a");
5959 /*-----------------------------------------------------------------*/
5960 /* AccAXLsh - left shift a:x by known count (0..7) */
5961 /*-----------------------------------------------------------------*/
5963 AccAXLsh (char *x, int shCount)
5978 case 5: // AAAAABBB:CCCCCDDD
5980 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5982 emitcode ("anl", "a,#0x%02x",
5983 SLMask[shCount]); // BBB00000:CCCCCDDD
5985 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5987 AccRol (shCount); // DDDCCCCC:BBB00000
5989 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5991 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5993 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5995 emitcode ("anl", "a,#0x%02x",
5996 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5998 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6000 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6003 case 6: // AAAAAABB:CCCCCCDD
6004 emitcode ("anl", "a,#0x%02x",
6005 SRMask[shCount]); // 000000BB:CCCCCCDD
6006 emitcode ("mov", "c,acc.0"); // c = B
6007 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6009 AccAXRrl1 (x); // BCCCCCCD:D000000B
6010 AccAXRrl1 (x); // BBCCCCCC:DD000000
6012 emitcode("rrc","a");
6013 emitcode("xch","a,%s", x);
6014 emitcode("rrc","a");
6015 emitcode("mov","c,acc.0"); //<< get correct bit
6016 emitcode("xch","a,%s", x);
6018 emitcode("rrc","a");
6019 emitcode("xch","a,%s", x);
6020 emitcode("rrc","a");
6021 emitcode("xch","a,%s", x);
6024 case 7: // a:x <<= 7
6026 emitcode ("anl", "a,#0x%02x",
6027 SRMask[shCount]); // 0000000B:CCCCCCCD
6029 emitcode ("mov", "c,acc.0"); // c = B
6031 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6033 AccAXRrl1 (x); // BCCCCCCC:D0000000
6041 /*-----------------------------------------------------------------*/
6042 /* AccAXRsh - right shift a:x known count (0..7) */
6043 /*-----------------------------------------------------------------*/
6045 AccAXRsh (char *x, int shCount)
6053 AccAXRrl1 (x); // 0->a:x
6058 AccAXRrl1 (x); // 0->a:x
6061 AccAXRrl1 (x); // 0->a:x
6066 case 5: // AAAAABBB:CCCCCDDD = a:x
6068 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6070 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6072 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6074 emitcode ("anl", "a,#0x%02x",
6075 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6077 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6079 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6081 emitcode ("anl", "a,#0x%02x",
6082 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6084 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6086 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6088 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6091 case 6: // AABBBBBB:CCDDDDDD
6093 emitcode ("mov", "c,acc.7");
6094 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6096 emitcode ("mov", "c,acc.7");
6097 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6099 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6101 emitcode ("anl", "a,#0x%02x",
6102 SRMask[shCount]); // 000000AA:BBBBBBCC
6105 case 7: // ABBBBBBB:CDDDDDDD
6107 emitcode ("mov", "c,acc.7"); // c = A
6109 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6111 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6113 emitcode ("anl", "a,#0x%02x",
6114 SRMask[shCount]); // 0000000A:BBBBBBBC
6122 /*-----------------------------------------------------------------*/
6123 /* AccAXRshS - right shift signed a:x known count (0..7) */
6124 /*-----------------------------------------------------------------*/
6126 AccAXRshS (char *x, int shCount)
6134 emitcode ("mov", "c,acc.7");
6135 AccAXRrl1 (x); // s->a:x
6139 emitcode ("mov", "c,acc.7");
6140 AccAXRrl1 (x); // s->a:x
6142 emitcode ("mov", "c,acc.7");
6143 AccAXRrl1 (x); // s->a:x
6148 case 5: // AAAAABBB:CCCCCDDD = a:x
6150 tlbl = newiTempLabel (NULL);
6151 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6153 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6155 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6157 emitcode ("anl", "a,#0x%02x",
6158 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6160 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6162 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6164 emitcode ("anl", "a,#0x%02x",
6165 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6167 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6169 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6171 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6173 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6174 emitcode ("orl", "a,#0x%02x",
6175 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6177 emitcode ("", "%05d$:", tlbl->key + 100);
6178 break; // SSSSAAAA:BBBCCCCC
6180 case 6: // AABBBBBB:CCDDDDDD
6182 tlbl = newiTempLabel (NULL);
6183 emitcode ("mov", "c,acc.7");
6184 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6186 emitcode ("mov", "c,acc.7");
6187 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6189 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6191 emitcode ("anl", "a,#0x%02x",
6192 SRMask[shCount]); // 000000AA:BBBBBBCC
6194 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6195 emitcode ("orl", "a,#0x%02x",
6196 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6198 emitcode ("", "%05d$:", tlbl->key + 100);
6200 case 7: // ABBBBBBB:CDDDDDDD
6202 tlbl = newiTempLabel (NULL);
6203 emitcode ("mov", "c,acc.7"); // c = A
6205 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6207 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6209 emitcode ("anl", "a,#0x%02x",
6210 SRMask[shCount]); // 0000000A:BBBBBBBC
6212 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6213 emitcode ("orl", "a,#0x%02x",
6214 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6216 emitcode ("", "%05d$:", tlbl->key + 100);
6223 /*-----------------------------------------------------------------*/
6224 /* shiftL2Left2Result - shift left two bytes from left to result */
6225 /*-----------------------------------------------------------------*/
6227 shiftL2Left2Result (operand * left, int offl,
6228 operand * result, int offr, int shCount)
6230 if (sameRegs (AOP (result), AOP (left)) &&
6231 ((offl + MSB16) == offr))
6233 /* don't crash result[offr] */
6234 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6235 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6239 movLeft2Result (left, offl, result, offr, 0);
6240 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6242 /* ax << shCount (x = lsb(result)) */
6243 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6244 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6248 /*-----------------------------------------------------------------*/
6249 /* shiftR2Left2Result - shift right two bytes from left to result */
6250 /*-----------------------------------------------------------------*/
6252 shiftR2Left2Result (operand * left, int offl,
6253 operand * result, int offr,
6254 int shCount, int sign)
6256 if (sameRegs (AOP (result), AOP (left)) &&
6257 ((offl + MSB16) == offr))
6259 /* don't crash result[offr] */
6260 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6261 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6265 movLeft2Result (left, offl, result, offr, 0);
6266 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6268 /* a:x >> shCount (x = lsb(result)) */
6270 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6272 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6273 if (getDataSize (result) > 1)
6274 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6277 /*-----------------------------------------------------------------*/
6278 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6279 /*-----------------------------------------------------------------*/
6281 shiftLLeftOrResult (operand * left, int offl,
6282 operand * result, int offr, int shCount)
6284 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6285 /* shift left accumulator */
6287 /* or with result */
6288 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6289 /* back to result */
6290 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6293 /*-----------------------------------------------------------------*/
6294 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6295 /*-----------------------------------------------------------------*/
6297 shiftRLeftOrResult (operand * left, int offl,
6298 operand * result, int offr, int shCount)
6300 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6301 /* shift right accumulator */
6303 /* or with result */
6304 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6305 /* back to result */
6306 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6309 /*-----------------------------------------------------------------*/
6310 /* genlshOne - left shift a one byte quantity by known count */
6311 /*-----------------------------------------------------------------*/
6313 genlshOne (operand * result, operand * left, int shCount)
6315 D(emitcode ("; genlshOne",""));
6317 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6320 /*-----------------------------------------------------------------*/
6321 /* genlshTwo - left shift two bytes by known amount != 0 */
6322 /*-----------------------------------------------------------------*/
6324 genlshTwo (operand * result, operand * left, int shCount)
6328 D(emitcode ("; genlshTwo",""));
6330 size = getDataSize (result);
6332 /* if shCount >= 8 */
6340 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6342 movLeft2Result (left, LSB, result, MSB16, 0);
6344 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6347 /* 1 <= shCount <= 7 */
6351 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6353 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6357 /*-----------------------------------------------------------------*/
6358 /* shiftLLong - shift left one long from left to result */
6359 /* offl = LSB or MSB16 */
6360 /*-----------------------------------------------------------------*/
6362 shiftLLong (operand * left, operand * result, int offr)
6365 int size = AOP_SIZE (result);
6367 if (size >= LSB + offr)
6369 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6371 emitcode ("add", "a,acc");
6372 if (sameRegs (AOP (left), AOP (result)) &&
6373 size >= MSB16 + offr && offr != LSB)
6374 emitcode ("xch", "a,%s",
6375 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6377 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6380 if (size >= MSB16 + offr)
6382 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6384 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6387 emitcode ("rlc", "a");
6388 if (sameRegs (AOP (left), AOP (result)) &&
6389 size >= MSB24 + offr && offr != LSB)
6390 emitcode ("xch", "a,%s",
6391 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6393 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6396 if (size >= MSB24 + offr)
6398 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6400 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6403 emitcode ("rlc", "a");
6404 if (sameRegs (AOP (left), AOP (result)) &&
6405 size >= MSB32 + offr && offr != LSB)
6406 emitcode ("xch", "a,%s",
6407 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6409 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6412 if (size > MSB32 + offr)
6414 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6416 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6419 emitcode ("rlc", "a");
6420 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6423 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6426 /*-----------------------------------------------------------------*/
6427 /* genlshFour - shift four byte by a known amount != 0 */
6428 /*-----------------------------------------------------------------*/
6430 genlshFour (operand * result, operand * left, int shCount)
6434 D(emitcode ("; genlshFour",""));
6436 size = AOP_SIZE (result);
6438 /* if shifting more that 3 bytes */
6443 /* lowest order of left goes to the highest
6444 order of the destination */
6445 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6447 movLeft2Result (left, LSB, result, MSB32, 0);
6448 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6449 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6450 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6454 /* more than two bytes */
6455 else if (shCount >= 16)
6457 /* lower order two bytes goes to higher order two bytes */
6459 /* if some more remaining */
6461 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6464 movLeft2Result (left, MSB16, result, MSB32, 0);
6465 movLeft2Result (left, LSB, result, MSB24, 0);
6467 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6468 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6472 /* if more than 1 byte */
6473 else if (shCount >= 8)
6475 /* lower order three bytes goes to higher order three bytes */
6480 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6482 movLeft2Result (left, LSB, result, MSB16, 0);
6488 movLeft2Result (left, MSB24, result, MSB32, 0);
6489 movLeft2Result (left, MSB16, result, MSB24, 0);
6490 movLeft2Result (left, LSB, result, MSB16, 0);
6491 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6493 else if (shCount == 1)
6494 shiftLLong (left, result, MSB16);
6497 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6498 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6499 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6500 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6505 /* 1 <= shCount <= 7 */
6506 else if (shCount <= 2)
6508 shiftLLong (left, result, LSB);
6510 shiftLLong (result, result, LSB);
6512 /* 3 <= shCount <= 7, optimize */
6515 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6516 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6517 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6521 /*-----------------------------------------------------------------*/
6522 /* genLeftShiftLiteral - left shifting by known count */
6523 /*-----------------------------------------------------------------*/
6525 genLeftShiftLiteral (operand * left,
6530 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6533 D(emitcode ("; genLeftShiftLiteral",""));
6535 freeAsmop (right, NULL, ic, TRUE);
6537 aopOp (left, ic, FALSE);
6538 aopOp (result, ic, FALSE);
6540 size = getSize (operandType (result));
6543 emitcode ("; shift left ", "result %d, left %d", size,
6547 /* I suppose that the left size >= result size */
6552 movLeft2Result (left, size, result, size, 0);
6556 else if (shCount >= (size * 8))
6558 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6564 genlshOne (result, left, shCount);
6568 genlshTwo (result, left, shCount);
6572 genlshFour (result, left, shCount);
6575 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6576 "*** ack! mystery literal shift!\n");
6580 freeAsmop (left, NULL, ic, TRUE);
6581 freeAsmop (result, NULL, ic, TRUE);
6584 /*-----------------------------------------------------------------*/
6585 /* genLeftShift - generates code for left shifting */
6586 /*-----------------------------------------------------------------*/
6588 genLeftShift (iCode * ic)
6590 operand *left, *right, *result;
6593 symbol *tlbl, *tlbl1;
6595 D(emitcode ("; genLeftShift",""));
6597 right = IC_RIGHT (ic);
6598 left = IC_LEFT (ic);
6599 result = IC_RESULT (ic);
6601 aopOp (right, ic, FALSE);
6603 /* if the shift count is known then do it
6604 as efficiently as possible */
6605 if (AOP_TYPE (right) == AOP_LIT)
6607 genLeftShiftLiteral (left, right, result, ic);
6611 /* shift count is unknown then we have to form
6612 a loop get the loop count in B : Note: we take
6613 only the lower order byte since shifting
6614 more that 32 bits make no sense anyway, ( the
6615 largest size of an object can be only 32 bits ) */
6617 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6618 emitcode ("inc", "b");
6619 freeAsmop (right, NULL, ic, TRUE);
6620 aopOp (left, ic, FALSE);
6621 aopOp (result, ic, FALSE);
6623 /* now move the left to the result if they are not the
6625 if (!sameRegs (AOP (left), AOP (result)) &&
6626 AOP_SIZE (result) > 1)
6629 size = AOP_SIZE (result);
6633 l = aopGet (AOP (left), offset, FALSE, TRUE);
6634 if (*l == '@' && (IS_AOP_PREG (result)))
6637 emitcode ("mov", "a,%s", l);
6638 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6641 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6646 tlbl = newiTempLabel (NULL);
6647 size = AOP_SIZE (result);
6649 tlbl1 = newiTempLabel (NULL);
6651 /* if it is only one byte then */
6654 symbol *tlbl1 = newiTempLabel (NULL);
6656 l = aopGet (AOP (left), 0, FALSE, FALSE);
6658 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6659 emitcode ("", "%05d$:", tlbl->key + 100);
6660 emitcode ("add", "a,acc");
6661 emitcode ("", "%05d$:", tlbl1->key + 100);
6662 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6663 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6667 reAdjustPreg (AOP (result));
6669 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6670 emitcode ("", "%05d$:", tlbl->key + 100);
6671 l = aopGet (AOP (result), offset, FALSE, FALSE);
6673 emitcode ("add", "a,acc");
6674 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6677 l = aopGet (AOP (result), offset, FALSE, FALSE);
6679 emitcode ("rlc", "a");
6680 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6682 reAdjustPreg (AOP (result));
6684 emitcode ("", "%05d$:", tlbl1->key + 100);
6685 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6687 freeAsmop (left, NULL, ic, TRUE);
6688 freeAsmop (result, NULL, ic, TRUE);
6691 /*-----------------------------------------------------------------*/
6692 /* genrshOne - right shift a one byte quantity by known count */
6693 /*-----------------------------------------------------------------*/
6695 genrshOne (operand * result, operand * left,
6696 int shCount, int sign)
6698 D(emitcode ("; genrshOne",""));
6700 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6703 /*-----------------------------------------------------------------*/
6704 /* genrshTwo - right shift two bytes by known amount != 0 */
6705 /*-----------------------------------------------------------------*/
6707 genrshTwo (operand * result, operand * left,
6708 int shCount, int sign)
6710 D(emitcode ("; genrshTwo",""));
6712 /* if shCount >= 8 */
6717 shiftR1Left2Result (left, MSB16, result, LSB,
6720 movLeft2Result (left, MSB16, result, LSB, sign);
6721 addSign (result, MSB16, sign);
6724 /* 1 <= shCount <= 7 */
6726 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6729 /*-----------------------------------------------------------------*/
6730 /* shiftRLong - shift right one long from left to result */
6731 /* offl = LSB or MSB16 */
6732 /*-----------------------------------------------------------------*/
6734 shiftRLong (operand * left, int offl,
6735 operand * result, int sign)
6737 int isSameRegs=sameRegs(AOP(left),AOP(result));
6739 if (isSameRegs && offl>1) {
6740 // we are in big trouble, but this shouldn't happen
6741 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6744 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6749 emitcode ("rlc", "a");
6750 emitcode ("subb", "a,acc");
6752 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6754 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6755 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6758 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6763 emitcode ("clr", "c");
6765 emitcode ("mov", "c,acc.7");
6768 emitcode ("rrc", "a");
6770 if (isSameRegs && offl==MSB16) {
6771 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6773 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6774 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6777 emitcode ("rrc", "a");
6778 if (isSameRegs && offl==1) {
6779 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6781 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6782 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6784 emitcode ("rrc", "a");
6785 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6789 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6790 emitcode ("rrc", "a");
6791 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6795 /*-----------------------------------------------------------------*/
6796 /* genrshFour - shift four byte by a known amount != 0 */
6797 /*-----------------------------------------------------------------*/
6799 genrshFour (operand * result, operand * left,
6800 int shCount, int sign)
6802 D(emitcode ("; genrshFour",""));
6804 /* if shifting more that 3 bytes */
6809 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6811 movLeft2Result (left, MSB32, result, LSB, sign);
6812 addSign (result, MSB16, sign);
6814 else if (shCount >= 16)
6818 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6821 movLeft2Result (left, MSB24, result, LSB, 0);
6822 movLeft2Result (left, MSB32, result, MSB16, sign);
6824 addSign (result, MSB24, sign);
6826 else if (shCount >= 8)
6830 shiftRLong (left, MSB16, result, sign);
6831 else if (shCount == 0)
6833 movLeft2Result (left, MSB16, result, LSB, 0);
6834 movLeft2Result (left, MSB24, result, MSB16, 0);
6835 movLeft2Result (left, MSB32, result, MSB24, sign);
6836 addSign (result, MSB32, sign);
6840 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6841 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6842 /* the last shift is signed */
6843 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6844 addSign (result, MSB32, sign);
6848 { /* 1 <= shCount <= 7 */
6851 shiftRLong (left, LSB, result, sign);
6853 shiftRLong (result, LSB, result, sign);
6857 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6858 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6859 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6864 /*-----------------------------------------------------------------*/
6865 /* genRightShiftLiteral - right shifting by known count */
6866 /*-----------------------------------------------------------------*/
6868 genRightShiftLiteral (operand * left,
6874 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6877 D(emitcode ("; genRightShiftLiteral",""));
6879 freeAsmop (right, NULL, ic, TRUE);
6881 aopOp (left, ic, FALSE);
6882 aopOp (result, ic, FALSE);
6885 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6889 size = getDataSize (left);
6890 /* test the LEFT size !!! */
6892 /* I suppose that the left size >= result size */
6895 size = getDataSize (result);
6897 movLeft2Result (left, size, result, size, 0);
6900 else if (shCount >= (size * 8))
6903 /* get sign in acc.7 */
6904 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6906 addSign (result, LSB, sign);
6913 genrshOne (result, left, shCount, sign);
6917 genrshTwo (result, left, shCount, sign);
6921 genrshFour (result, left, shCount, sign);
6927 freeAsmop (left, NULL, ic, TRUE);
6928 freeAsmop (result, NULL, ic, TRUE);
6931 /*-----------------------------------------------------------------*/
6932 /* genSignedRightShift - right shift of signed number */
6933 /*-----------------------------------------------------------------*/
6935 genSignedRightShift (iCode * ic)
6937 operand *right, *left, *result;
6940 symbol *tlbl, *tlbl1;
6942 D(emitcode ("; genSignedRightShift",""));
6944 /* we do it the hard way put the shift count in b
6945 and loop thru preserving the sign */
6947 right = IC_RIGHT (ic);
6948 left = IC_LEFT (ic);
6949 result = IC_RESULT (ic);
6951 aopOp (right, ic, FALSE);
6954 if (AOP_TYPE (right) == AOP_LIT)
6956 genRightShiftLiteral (left, right, result, ic, 1);
6959 /* shift count is unknown then we have to form
6960 a loop get the loop count in B : Note: we take
6961 only the lower order byte since shifting
6962 more that 32 bits make no sense anyway, ( the
6963 largest size of an object can be only 32 bits ) */
6965 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6966 emitcode ("inc", "b");
6967 freeAsmop (right, NULL, ic, TRUE);
6968 aopOp (left, ic, FALSE);
6969 aopOp (result, ic, FALSE);
6971 /* now move the left to the result if they are not the
6973 if (!sameRegs (AOP (left), AOP (result)) &&
6974 AOP_SIZE (result) > 1)
6977 size = AOP_SIZE (result);
6981 l = aopGet (AOP (left), offset, FALSE, TRUE);
6982 if (*l == '@' && IS_AOP_PREG (result))
6985 emitcode ("mov", "a,%s", l);
6986 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6989 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6994 /* mov the highest order bit to OVR */
6995 tlbl = newiTempLabel (NULL);
6996 tlbl1 = newiTempLabel (NULL);
6998 size = AOP_SIZE (result);
7000 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7001 emitcode ("rlc", "a");
7002 emitcode ("mov", "ov,c");
7003 /* if it is only one byte then */
7006 l = aopGet (AOP (left), 0, FALSE, FALSE);
7008 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7009 emitcode ("", "%05d$:", tlbl->key + 100);
7010 emitcode ("mov", "c,ov");
7011 emitcode ("rrc", "a");
7012 emitcode ("", "%05d$:", tlbl1->key + 100);
7013 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7014 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7018 reAdjustPreg (AOP (result));
7019 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7020 emitcode ("", "%05d$:", tlbl->key + 100);
7021 emitcode ("mov", "c,ov");
7024 l = aopGet (AOP (result), offset, FALSE, FALSE);
7026 emitcode ("rrc", "a");
7027 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7029 reAdjustPreg (AOP (result));
7030 emitcode ("", "%05d$:", tlbl1->key + 100);
7031 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7034 freeAsmop (left, NULL, ic, TRUE);
7035 freeAsmop (result, NULL, ic, TRUE);
7038 /*-----------------------------------------------------------------*/
7039 /* genRightShift - generate code for right shifting */
7040 /*-----------------------------------------------------------------*/
7042 genRightShift (iCode * ic)
7044 operand *right, *left, *result;
7048 symbol *tlbl, *tlbl1;
7050 D(emitcode ("; genRightShift",""));
7052 /* if signed then we do it the hard way preserve the
7053 sign bit moving it inwards */
7054 retype = getSpec (operandType (IC_RESULT (ic)));
7056 if (!SPEC_USIGN (retype))
7058 genSignedRightShift (ic);
7062 /* signed & unsigned types are treated the same : i.e. the
7063 signed is NOT propagated inwards : quoting from the
7064 ANSI - standard : "for E1 >> E2, is equivalent to division
7065 by 2**E2 if unsigned or if it has a non-negative value,
7066 otherwise the result is implementation defined ", MY definition
7067 is that the sign does not get propagated */
7069 right = IC_RIGHT (ic);
7070 left = IC_LEFT (ic);
7071 result = IC_RESULT (ic);
7073 aopOp (right, ic, FALSE);
7075 /* if the shift count is known then do it
7076 as efficiently as possible */
7077 if (AOP_TYPE (right) == AOP_LIT)
7079 genRightShiftLiteral (left, right, result, ic, 0);
7083 /* shift count is unknown then we have to form
7084 a loop get the loop count in B : Note: we take
7085 only the lower order byte since shifting
7086 more that 32 bits make no sense anyway, ( the
7087 largest size of an object can be only 32 bits ) */
7089 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7090 emitcode ("inc", "b");
7091 freeAsmop (right, NULL, ic, TRUE);
7092 aopOp (left, ic, FALSE);
7093 aopOp (result, ic, FALSE);
7095 /* now move the left to the result if they are not the
7097 if (!sameRegs (AOP (left), AOP (result)) &&
7098 AOP_SIZE (result) > 1)
7101 size = AOP_SIZE (result);
7105 l = aopGet (AOP (left), offset, FALSE, TRUE);
7106 if (*l == '@' && IS_AOP_PREG (result))
7109 emitcode ("mov", "a,%s", l);
7110 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7113 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7118 tlbl = newiTempLabel (NULL);
7119 tlbl1 = newiTempLabel (NULL);
7120 size = AOP_SIZE (result);
7123 /* if it is only one byte then */
7126 l = aopGet (AOP (left), 0, FALSE, FALSE);
7128 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7129 emitcode ("", "%05d$:", tlbl->key + 100);
7131 emitcode ("rrc", "a");
7132 emitcode ("", "%05d$:", tlbl1->key + 100);
7133 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7134 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7138 reAdjustPreg (AOP (result));
7139 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7140 emitcode ("", "%05d$:", tlbl->key + 100);
7144 l = aopGet (AOP (result), offset, FALSE, FALSE);
7146 emitcode ("rrc", "a");
7147 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7149 reAdjustPreg (AOP (result));
7151 emitcode ("", "%05d$:", tlbl1->key + 100);
7152 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7155 freeAsmop (left, NULL, ic, TRUE);
7156 freeAsmop (result, NULL, ic, TRUE);
7159 /*-----------------------------------------------------------------*/
7160 /* emitPtrByteGet - emits code to get a byte into A through a */
7161 /* pointer register (R0, R1, or DPTR). The */
7162 /* original value of A can be preserved in B. */
7163 /*-----------------------------------------------------------------*/
7165 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7172 emitcode ("mov", "b,a");
7173 emitcode ("mov", "a,@%s", rname);
7178 emitcode ("mov", "b,a");
7179 emitcode ("movx", "a,@%s", rname);
7184 emitcode ("mov", "b,a");
7185 emitcode ("movx", "a,@dptr");
7190 emitcode ("mov", "b,a");
7191 emitcode ("clr", "a");
7192 emitcode ("movc", "a,@a+dptr");
7198 emitcode ("push", "b");
7199 emitcode ("push", "acc");
7201 emitcode ("lcall", "__gptrget");
7203 emitcode ("pop", "b");
7208 /*-----------------------------------------------------------------*/
7209 /* emitPtrByteSet - emits code to set a byte from src through a */
7210 /* pointer register (R0, R1, or DPTR). */
7211 /*-----------------------------------------------------------------*/
7213 emitPtrByteSet (char *rname, int p_type, char *src)
7222 emitcode ("mov", "@%s,a", rname);
7225 emitcode ("mov", "@%s,%s", rname, src);
7230 emitcode ("movx", "@%s,a", rname);
7235 emitcode ("movx", "@dptr,a");
7240 emitcode ("lcall", "__gptrput");
7245 /*-----------------------------------------------------------------*/
7246 /* genUnpackBits - generates code for unpacking bits */
7247 /*-----------------------------------------------------------------*/
7249 genUnpackBits (operand * result, char *rname, int ptype)
7251 int offset = 0; /* result byte offset */
7252 int rsize; /* result size */
7253 int rlen = 0; /* remaining bitfield length */
7254 sym_link *etype; /* bitfield type information */
7255 int blen; /* bitfield length */
7256 int bstr; /* bitfield starting bit within byte */
7258 D(emitcode ("; genUnpackBits",""));
7260 etype = getSpec (operandType (result));
7261 rsize = getSize (operandType (result));
7262 blen = SPEC_BLEN (etype);
7263 bstr = SPEC_BSTR (etype);
7265 /* If the bitfield length is less than a byte */
7268 emitPtrByteGet (rname, ptype, FALSE);
7270 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7271 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7275 /* Bit field did not fit in a byte. Copy all
7276 but the partial byte at the end. */
7277 for (rlen=blen;rlen>=8;rlen-=8)
7279 emitPtrByteGet (rname, ptype, FALSE);
7280 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7282 emitcode ("inc", "%s", rname);
7285 /* Handle the partial byte at the end */
7288 emitPtrByteGet (rname, ptype, FALSE);
7289 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7290 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7298 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7303 /*-----------------------------------------------------------------*/
7304 /* genDataPointerGet - generates code when ptr offset is known */
7305 /*-----------------------------------------------------------------*/
7307 genDataPointerGet (operand * left,
7313 int size, offset = 0;
7315 D(emitcode ("; genDataPointerGet",""));
7317 aopOp (result, ic, TRUE);
7319 /* get the string representation of the name */
7320 l = aopGet (AOP (left), 0, FALSE, TRUE);
7321 size = AOP_SIZE (result);
7325 sprintf (buffer, "(%s + %d)", l + 1, offset);
7327 sprintf (buffer, "%s", l + 1);
7328 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7331 freeAsmop (left, NULL, ic, TRUE);
7332 freeAsmop (result, NULL, ic, TRUE);
7335 /*-----------------------------------------------------------------*/
7336 /* genNearPointerGet - emitcode for near pointer fetch */
7337 /*-----------------------------------------------------------------*/
7339 genNearPointerGet (operand * left,
7347 sym_link *rtype, *retype;
7348 sym_link *ltype = operandType (left);
7351 D(emitcode ("; genNearPointerGet",""));
7353 rtype = operandType (result);
7354 retype = getSpec (rtype);
7356 aopOp (left, ic, FALSE);
7358 /* if left is rematerialisable and
7359 result is not bit variable type and
7360 the left is pointer to data space i.e
7361 lower 128 bytes of space */
7362 if (AOP_TYPE (left) == AOP_IMMD &&
7363 !IS_BITVAR (retype) &&
7364 DCL_TYPE (ltype) == POINTER)
7366 genDataPointerGet (left, result, ic);
7370 /* if the value is already in a pointer register
7371 then don't need anything more */
7372 if (!AOP_INPREG (AOP (left)))
7374 if (IS_AOP_PREG (left))
7376 // Aha, it is a pointer, just in disguise.
7377 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7380 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7381 __FILE__, __LINE__);
7386 emitcode ("mov", "a%s,%s", rname + 1, rname);
7387 rname++; // skip the '@'.
7392 /* otherwise get a free pointer register */
7394 preg = getFreePtr (ic, &aop, FALSE);
7395 emitcode ("mov", "%s,%s",
7397 aopGet (AOP (left), 0, FALSE, TRUE));
7402 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7404 //aopOp (result, ic, FALSE);
7405 aopOp (result, ic, result?TRUE:FALSE);
7407 /* if bitfield then unpack the bits */
7408 if (IS_BITVAR (retype))
7409 genUnpackBits (result, rname, POINTER);
7412 /* we have can just get the values */
7413 int size = AOP_SIZE (result);
7418 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7421 emitcode ("mov", "a,@%s", rname);
7422 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7426 sprintf (buffer, "@%s", rname);
7427 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7431 emitcode ("inc", "%s", rname);
7435 /* now some housekeeping stuff */
7436 if (aop) /* we had to allocate for this iCode */
7438 if (pi) { /* post increment present */
7439 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7441 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7445 /* we did not allocate which means left
7446 already in a pointer register, then
7447 if size > 0 && this could be used again
7448 we have to point it back to where it
7450 if ((AOP_SIZE (result) > 1 &&
7451 !OP_SYMBOL (left)->remat &&
7452 (OP_SYMBOL (left)->liveTo > ic->seq ||
7456 int size = AOP_SIZE (result) - 1;
7458 emitcode ("dec", "%s", rname);
7463 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7464 freeAsmop (left, NULL, ic, TRUE);
7465 if (pi) pi->generated = 1;
7468 /*-----------------------------------------------------------------*/
7469 /* genPagedPointerGet - emitcode for paged pointer fetch */
7470 /*-----------------------------------------------------------------*/
7472 genPagedPointerGet (operand * left,
7480 sym_link *rtype, *retype;
7482 D(emitcode ("; genPagedPointerGet",""));
7484 rtype = operandType (result);
7485 retype = getSpec (rtype);
7487 aopOp (left, ic, FALSE);
7489 /* if the value is already in a pointer register
7490 then don't need anything more */
7491 if (!AOP_INPREG (AOP (left)))
7493 /* otherwise get a free pointer register */
7495 preg = getFreePtr (ic, &aop, FALSE);
7496 emitcode ("mov", "%s,%s",
7498 aopGet (AOP (left), 0, FALSE, TRUE));
7502 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7504 aopOp (result, ic, FALSE);
7506 /* if bitfield then unpack the bits */
7507 if (IS_BITVAR (retype))
7508 genUnpackBits (result, rname, PPOINTER);
7511 /* we have can just get the values */
7512 int size = AOP_SIZE (result);
7518 emitcode ("movx", "a,@%s", rname);
7519 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7524 emitcode ("inc", "%s", rname);
7528 /* now some housekeeping stuff */
7529 if (aop) /* we had to allocate for this iCode */
7531 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7532 freeAsmop (NULL, aop, ic, TRUE);
7536 /* we did not allocate which means left
7537 already in a pointer register, then
7538 if size > 0 && this could be used again
7539 we have to point it back to where it
7541 if ((AOP_SIZE (result) > 1 &&
7542 !OP_SYMBOL (left)->remat &&
7543 (OP_SYMBOL (left)->liveTo > ic->seq ||
7547 int size = AOP_SIZE (result) - 1;
7549 emitcode ("dec", "%s", rname);
7554 freeAsmop (left, NULL, ic, TRUE);
7555 freeAsmop (result, NULL, ic, TRUE);
7556 if (pi) pi->generated = 1;
7560 /*--------------------------------------------------------------------*/
7561 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7562 /*--------------------------------------------------------------------*/
7564 loadDptrFromOperand (operand *op, bool loadBToo)
7566 if (AOP_TYPE (op) != AOP_STR)
7568 /* if this is remateriazable */
7569 if (AOP_TYPE (op) == AOP_IMMD)
7571 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7574 if (AOP(op)->aopu.aop_immd.from_cast_remat)
7575 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7578 wassertl(FALSE, "need pointerCode");
7579 emitcode ("", "; mov b,???");
7580 /* genPointerGet and genPointerSet originally did different
7581 ** things for this case. Both seem wrong.
7582 ** from genPointerGet:
7583 ** emitcode ("mov", "b,#%d", pointerCode (retype));
7584 ** from genPointerSet:
7585 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7590 else if (AOP_TYPE (op) == AOP_DPTR)
7594 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7595 emitcode ("push", "acc");
7596 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7597 emitcode ("push", "acc");
7598 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7599 emitcode ("pop", "dph");
7600 emitcode ("pop", "dpl");
7604 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7605 emitcode ("push", "acc");
7606 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7607 emitcode ("pop", "dpl");
7611 { /* we need to get it byte by byte */
7612 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7613 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7615 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7620 /*-----------------------------------------------------------------*/
7621 /* genFarPointerGet - gget value from far space */
7622 /*-----------------------------------------------------------------*/
7624 genFarPointerGet (operand * left,
7625 operand * result, iCode * ic, iCode * pi)
7628 sym_link *retype = getSpec (operandType (result));
7630 D(emitcode ("; genFarPointerGet",""));
7632 aopOp (left, ic, FALSE);
7633 loadDptrFromOperand (left, FALSE);
7635 /* so dptr now contains the address */
7636 aopOp (result, ic, FALSE);
7638 /* if bit then unpack */
7639 if (IS_BITVAR (retype))
7640 genUnpackBits (result, "dptr", FPOINTER);
7643 size = AOP_SIZE (result);
7648 emitcode ("movx", "a,@dptr");
7649 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7651 emitcode ("inc", "dptr");
7655 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7656 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7657 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7660 freeAsmop (left, NULL, ic, TRUE);
7661 freeAsmop (result, NULL, ic, TRUE);
7664 /*-----------------------------------------------------------------*/
7665 /* genCodePointerGet - gget value from code space */
7666 /*-----------------------------------------------------------------*/
7668 genCodePointerGet (operand * left,
7669 operand * result, iCode * ic, iCode *pi)
7672 sym_link *retype = getSpec (operandType (result));
7674 D(emitcode ("; genCodePointerGet",""));
7676 aopOp (left, ic, FALSE);
7677 loadDptrFromOperand (left, FALSE);
7679 /* so dptr now contains the address */
7680 aopOp (result, ic, FALSE);
7682 /* if bit then unpack */
7683 if (IS_BITVAR (retype))
7684 genUnpackBits (result, "dptr", CPOINTER);
7687 size = AOP_SIZE (result);
7694 emitcode ("clr", "a");
7695 emitcode ("movc", "a,@a+dptr");
7696 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7697 emitcode ("inc", "dptr");
7701 emitcode ("mov", "a,#0x%02x", offset);
7702 emitcode ("movc", "a,@a+dptr");
7703 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7708 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7709 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7710 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7713 freeAsmop (left, NULL, ic, TRUE);
7714 freeAsmop (result, NULL, ic, TRUE);
7717 /*-----------------------------------------------------------------*/
7718 /* genGenPointerGet - gget value from generic pointer space */
7719 /*-----------------------------------------------------------------*/
7721 genGenPointerGet (operand * left,
7722 operand * result, iCode * ic, iCode *pi)
7725 sym_link *retype = getSpec (operandType (result));
7727 D(emitcode ("; genGenPointerGet",""));
7729 aopOp (left, ic, FALSE);
7730 loadDptrFromOperand (left, TRUE);
7732 /* so dptr know contains the address */
7733 aopOp (result, ic, FALSE);
7735 /* if bit then unpack */
7736 if (IS_BITVAR (retype))
7737 genUnpackBits (result, "dptr", GPOINTER);
7740 size = AOP_SIZE (result);
7745 emitcode ("lcall", "__gptrget");
7746 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7748 emitcode ("inc", "dptr");
7752 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7753 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7754 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7757 freeAsmop (left, NULL, ic, TRUE);
7758 freeAsmop (result, NULL, ic, TRUE);
7761 /*-----------------------------------------------------------------*/
7762 /* genPointerGet - generate code for pointer get */
7763 /*-----------------------------------------------------------------*/
7765 genPointerGet (iCode * ic, iCode *pi)
7767 operand *left, *result;
7768 sym_link *type, *etype;
7771 D(emitcode ("; genPointerGet",""));
7773 left = IC_LEFT (ic);
7774 result = IC_RESULT (ic);
7776 /* depending on the type of pointer we need to
7777 move it to the correct pointer register */
7778 type = operandType (left);
7779 etype = getSpec (type);
7780 /* if left is of type of pointer then it is simple */
7781 if (IS_PTR (type) && !IS_FUNC (type->next))
7782 p_type = DCL_TYPE (type);
7785 /* we have to go by the storage class */
7786 p_type = PTR_TYPE (SPEC_OCLS (etype));
7789 /* special case when cast remat */
7790 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7791 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7792 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7793 type = operandType (left);
7794 p_type = DCL_TYPE (type);
7796 /* now that we have the pointer type we assign
7797 the pointer values */
7803 genNearPointerGet (left, result, ic, pi);
7807 genPagedPointerGet (left, result, ic, pi);
7811 genFarPointerGet (left, result, ic, pi);
7815 genCodePointerGet (left, result, ic, pi);
7819 genGenPointerGet (left, result, ic, pi);
7827 /*-----------------------------------------------------------------*/
7828 /* genPackBits - generates code for packed bit storage */
7829 /*-----------------------------------------------------------------*/
7831 genPackBits (sym_link * etype,
7833 char *rname, int p_type)
7835 int offset = 0; /* source byte offset */
7836 int rlen = 0; /* remaining bitfield length */
7837 int blen; /* bitfield length */
7838 int bstr; /* bitfield starting bit within byte */
7839 int litval; /* source literal value (if AOP_LIT) */
7840 unsigned char mask; /* bitmask within current byte */
7842 D(emitcode ("; genPackBits",""));
7844 blen = SPEC_BLEN (etype);
7845 bstr = SPEC_BSTR (etype);
7847 /* If the bitfield length is less than a byte */
7850 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7851 (unsigned char) (0xFF >> (8 - bstr)));
7853 if (AOP_TYPE (right) == AOP_LIT)
7855 /* Case with a bitfield length <8 and literal source
7857 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7859 litval &= (~mask) & 0xff;
7860 emitPtrByteGet (rname, p_type, FALSE);
7861 if ((mask|litval)!=0xff)
7862 emitcode ("anl","a,#0x%02x", mask);
7864 emitcode ("orl","a,#0x%02x", litval);
7868 if ((blen==1) && (p_type!=GPOINTER))
7870 /* Case with a bitfield length == 1 and no generic pointer
7872 if (AOP_TYPE (right) == AOP_CRY)
7873 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7876 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7877 emitcode ("rrc","a");
7879 emitPtrByteGet (rname, p_type, FALSE);
7880 emitcode ("mov","acc.%d,c",bstr);
7884 /* Case with a bitfield length < 8 and arbitrary source
7886 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7887 /* shift and mask source value */
7889 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7891 /* transfer A to B and get next byte */
7892 emitPtrByteGet (rname, p_type, TRUE);
7894 emitcode ("anl", "a,#0x%02x", mask);
7895 emitcode ("orl", "a,b");
7896 if (p_type == GPOINTER)
7897 emitcode ("pop", "b");
7901 emitPtrByteSet (rname, p_type, "a");
7905 /* Bit length is greater than 7 bits. In this case, copy */
7906 /* all except the partial byte at the end */
7907 for (rlen=blen;rlen>=8;rlen-=8)
7909 emitPtrByteSet (rname, p_type,
7910 aopGet (AOP (right), offset++, FALSE, TRUE) );
7912 emitcode ("inc", "%s", rname);
7915 /* If there was a partial byte at the end */
7918 mask = (((unsigned char) -1 << rlen) & 0xff);
7920 if (AOP_TYPE (right) == AOP_LIT)
7922 /* Case with partial byte and literal source
7924 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7925 litval >>= (blen-rlen);
7926 litval &= (~mask) & 0xff;
7927 emitPtrByteGet (rname, p_type, FALSE);
7928 if ((mask|litval)!=0xff)
7929 emitcode ("anl","a,#0x%02x", mask);
7931 emitcode ("orl","a,#0x%02x", litval);
7935 /* Case with partial byte and arbitrary source
7937 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
7938 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7940 /* transfer A to B and get next byte */
7941 emitPtrByteGet (rname, p_type, TRUE);
7943 emitcode ("anl", "a,#0x%02x", mask);
7944 emitcode ("orl", "a,b");
7945 if (p_type == GPOINTER)
7946 emitcode ("pop", "b");
7948 emitPtrByteSet (rname, p_type, "a");
7954 /*-----------------------------------------------------------------*/
7955 /* genDataPointerSet - remat pointer to data space */
7956 /*-----------------------------------------------------------------*/
7958 genDataPointerSet (operand * right,
7962 int size, offset = 0;
7963 char *l, buffer[256];
7965 D(emitcode ("; genDataPointerSet",""));
7967 aopOp (right, ic, FALSE);
7969 l = aopGet (AOP (result), 0, FALSE, TRUE);
7970 size = AOP_SIZE (right);
7974 sprintf (buffer, "(%s + %d)", l + 1, offset);
7976 sprintf (buffer, "%s", l + 1);
7977 emitcode ("mov", "%s,%s", buffer,
7978 aopGet (AOP (right), offset++, FALSE, FALSE));
7981 freeAsmop (right, NULL, ic, TRUE);
7982 freeAsmop (result, NULL, ic, TRUE);
7985 /*-----------------------------------------------------------------*/
7986 /* genNearPointerSet - emitcode for near pointer put */
7987 /*-----------------------------------------------------------------*/
7989 genNearPointerSet (operand * right,
7997 sym_link *retype, *letype;
7998 sym_link *ptype = operandType (result);
8000 D(emitcode ("; genNearPointerSet",""));
8002 retype = getSpec (operandType (right));
8003 letype = getSpec (ptype);
8004 aopOp (result, ic, FALSE);
8006 /* if the result is rematerializable &
8007 in data space & not a bit variable */
8008 if (AOP_TYPE (result) == AOP_IMMD &&
8009 DCL_TYPE (ptype) == POINTER &&
8010 !IS_BITVAR (retype) &&
8011 !IS_BITVAR (letype))
8013 genDataPointerSet (right, result, ic);
8017 /* if the value is already in a pointer register
8018 then don't need anything more */
8019 if (!AOP_INPREG (AOP (result)))
8022 //AOP_TYPE (result) == AOP_STK
8026 // Aha, it is a pointer, just in disguise.
8027 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8030 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8031 __FILE__, __LINE__);
8036 emitcode ("mov", "a%s,%s", rname + 1, rname);
8037 rname++; // skip the '@'.
8042 /* otherwise get a free pointer register */
8044 preg = getFreePtr (ic, &aop, FALSE);
8045 emitcode ("mov", "%s,%s",
8047 aopGet (AOP (result), 0, FALSE, TRUE));
8053 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8056 aopOp (right, ic, FALSE);
8058 /* if bitfield then unpack the bits */
8059 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8060 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8063 /* we have can just get the values */
8064 int size = AOP_SIZE (right);
8069 l = aopGet (AOP (right), offset, FALSE, TRUE);
8073 emitcode ("mov", "@%s,a", rname);
8076 emitcode ("mov", "@%s,%s", rname, l);
8078 emitcode ("inc", "%s", rname);
8083 /* now some housekeeping stuff */
8084 if (aop) /* we had to allocate for this iCode */
8087 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8088 freeAsmop (NULL, aop, ic, TRUE);
8092 /* we did not allocate which means left
8093 already in a pointer register, then
8094 if size > 0 && this could be used again
8095 we have to point it back to where it
8097 if ((AOP_SIZE (right) > 1 &&
8098 !OP_SYMBOL (result)->remat &&
8099 (OP_SYMBOL (result)->liveTo > ic->seq ||
8103 int size = AOP_SIZE (right) - 1;
8105 emitcode ("dec", "%s", rname);
8110 if (pi) pi->generated = 1;
8111 freeAsmop (result, NULL, ic, TRUE);
8112 freeAsmop (right, NULL, ic, TRUE);
8115 /*-----------------------------------------------------------------*/
8116 /* genPagedPointerSet - emitcode for Paged pointer put */
8117 /*-----------------------------------------------------------------*/
8119 genPagedPointerSet (operand * right,
8127 sym_link *retype, *letype;
8129 D(emitcode ("; genPagedPointerSet",""));
8131 retype = getSpec (operandType (right));
8132 letype = getSpec (operandType (result));
8134 aopOp (result, ic, FALSE);
8136 /* if the value is already in a pointer register
8137 then don't need anything more */
8138 if (!AOP_INPREG (AOP (result)))
8140 /* otherwise get a free pointer register */
8142 preg = getFreePtr (ic, &aop, FALSE);
8143 emitcode ("mov", "%s,%s",
8145 aopGet (AOP (result), 0, FALSE, TRUE));
8149 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8151 aopOp (right, ic, FALSE);
8153 /* if bitfield then unpack the bits */
8154 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8155 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8158 /* we have can just get the values */
8159 int size = AOP_SIZE (right);
8164 l = aopGet (AOP (right), offset, FALSE, TRUE);
8167 emitcode ("movx", "@%s,a", rname);
8170 emitcode ("inc", "%s", rname);
8176 /* now some housekeeping stuff */
8177 if (aop) /* we had to allocate for this iCode */
8180 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8181 freeAsmop (NULL, aop, ic, TRUE);
8185 /* we did not allocate which means left
8186 already in a pointer register, then
8187 if size > 0 && this could be used again
8188 we have to point it back to where it
8190 if (AOP_SIZE (right) > 1 &&
8191 !OP_SYMBOL (result)->remat &&
8192 (OP_SYMBOL (result)->liveTo > ic->seq ||
8195 int size = AOP_SIZE (right) - 1;
8197 emitcode ("dec", "%s", rname);
8202 if (pi) pi->generated = 1;
8203 freeAsmop (result, NULL, ic, TRUE);
8204 freeAsmop (right, NULL, ic, TRUE);
8209 /*-----------------------------------------------------------------*/
8210 /* genFarPointerSet - set value from far space */
8211 /*-----------------------------------------------------------------*/
8213 genFarPointerSet (operand * right,
8214 operand * result, iCode * ic, iCode * pi)
8217 sym_link *retype = getSpec (operandType (right));
8218 sym_link *letype = getSpec (operandType (result));
8220 D(emitcode ("; genFarPointerSet",""));
8222 aopOp (result, ic, FALSE);
8223 loadDptrFromOperand (result, FALSE);
8225 /* so dptr know contains the address */
8226 aopOp (right, ic, FALSE);
8228 /* if bit then unpack */
8229 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8230 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8233 size = AOP_SIZE (right);
8238 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8240 emitcode ("movx", "@dptr,a");
8242 emitcode ("inc", "dptr");
8245 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8246 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8247 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8250 freeAsmop (result, NULL, ic, TRUE);
8251 freeAsmop (right, NULL, ic, TRUE);
8254 /*-----------------------------------------------------------------*/
8255 /* genGenPointerSet - set value from generic pointer space */
8256 /*-----------------------------------------------------------------*/
8258 genGenPointerSet (operand * right,
8259 operand * result, iCode * ic, iCode * pi)
8262 sym_link *retype = getSpec (operandType (right));
8263 sym_link *letype = getSpec (operandType (result));
8265 D(emitcode ("; genGenPointerSet",""));
8267 aopOp (result, ic, FALSE);
8268 loadDptrFromOperand (result, TRUE);
8270 /* so dptr know contains the address */
8271 aopOp (right, ic, FALSE);
8273 /* if bit then unpack */
8274 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8275 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8278 size = AOP_SIZE (right);
8283 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8285 emitcode ("lcall", "__gptrput");
8287 emitcode ("inc", "dptr");
8291 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8292 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8293 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8296 freeAsmop (result, NULL, ic, TRUE);
8297 freeAsmop (right, NULL, ic, TRUE);
8300 /*-----------------------------------------------------------------*/
8301 /* genPointerSet - stores the value into a pointer location */
8302 /*-----------------------------------------------------------------*/
8304 genPointerSet (iCode * ic, iCode *pi)
8306 operand *right, *result;
8307 sym_link *type, *etype;
8310 D(emitcode ("; genPointerSet",""));
8312 right = IC_RIGHT (ic);
8313 result = IC_RESULT (ic);
8315 /* depending on the type of pointer we need to
8316 move it to the correct pointer register */
8317 type = operandType (result);
8318 etype = getSpec (type);
8319 /* if left is of type of pointer then it is simple */
8320 if (IS_PTR (type) && !IS_FUNC (type->next))
8322 p_type = DCL_TYPE (type);
8326 /* we have to go by the storage class */
8327 p_type = PTR_TYPE (SPEC_OCLS (etype));
8330 /* special case when cast remat */
8331 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8332 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8333 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8334 type = operandType (result);
8335 p_type = DCL_TYPE (type);
8337 /* now that we have the pointer type we assign
8338 the pointer values */
8344 genNearPointerSet (right, result, ic, pi);
8348 genPagedPointerSet (right, result, ic, pi);
8352 genFarPointerSet (right, result, ic, pi);
8356 genGenPointerSet (right, result, ic, pi);
8360 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8361 "genPointerSet: illegal pointer type");
8366 /*-----------------------------------------------------------------*/
8367 /* genIfx - generate code for Ifx statement */
8368 /*-----------------------------------------------------------------*/
8370 genIfx (iCode * ic, iCode * popIc)
8372 operand *cond = IC_COND (ic);
8375 D(emitcode ("; genIfx",""));
8377 aopOp (cond, ic, FALSE);
8379 /* get the value into acc */
8380 if (AOP_TYPE (cond) != AOP_CRY)
8384 /* the result is now in the accumulator */
8385 freeAsmop (cond, NULL, ic, TRUE);
8387 /* if there was something to be popped then do it */
8391 /* if the condition is a bit variable */
8392 if (isbit && IS_ITEMP (cond) &&
8394 genIfxJump (ic, SPIL_LOC (cond)->rname);
8395 else if (isbit && !IS_ITEMP (cond))
8396 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8398 genIfxJump (ic, "a");
8403 /*-----------------------------------------------------------------*/
8404 /* genAddrOf - generates code for address of */
8405 /*-----------------------------------------------------------------*/
8407 genAddrOf (iCode * ic)
8409 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8412 D(emitcode ("; genAddrOf",""));
8414 aopOp (IC_RESULT (ic), ic, FALSE);
8416 /* if the operand is on the stack then we
8417 need to get the stack offset of this
8421 /* if it has an offset then we need to compute
8425 emitcode ("mov", "a,_bp");
8426 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8427 ((char) (sym->stack - _G.nRegsSaved)) :
8428 ((char) sym->stack)) & 0xff);
8429 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8433 /* we can just move _bp */
8434 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8436 /* fill the result with zero */
8437 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8442 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8448 /* object not on stack then we need the name */
8449 size = AOP_SIZE (IC_RESULT (ic));
8454 char s[SDCC_NAME_MAX];
8456 sprintf (s, "#(%s >> %d)",
8460 sprintf (s, "#%s", sym->rname);
8461 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8465 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8469 /*-----------------------------------------------------------------*/
8470 /* genFarFarAssign - assignment when both are in far space */
8471 /*-----------------------------------------------------------------*/
8473 genFarFarAssign (operand * result, operand * right, iCode * ic)
8475 int size = AOP_SIZE (right);
8479 D(emitcode ("; genFarFarAssign",""));
8481 /* first push the right side on to the stack */
8484 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8486 emitcode ("push", "acc");
8489 freeAsmop (right, NULL, ic, FALSE);
8490 /* now assign DPTR to result */
8491 aopOp (result, ic, FALSE);
8492 size = AOP_SIZE (result);
8495 emitcode ("pop", "acc");
8496 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8498 freeAsmop (result, NULL, ic, FALSE);
8502 /*-----------------------------------------------------------------*/
8503 /* genAssign - generate code for assignment */
8504 /*-----------------------------------------------------------------*/
8506 genAssign (iCode * ic)
8508 operand *result, *right;
8510 unsigned long lit = 0L;
8512 D(emitcode("; genAssign",""));
8514 result = IC_RESULT (ic);
8515 right = IC_RIGHT (ic);
8517 /* if they are the same */
8518 if (operandsEqu (result, right) &&
8519 !isOperandVolatile (result, FALSE) &&
8520 !isOperandVolatile (right, FALSE))
8523 aopOp (right, ic, FALSE);
8525 /* special case both in far space */
8526 if (AOP_TYPE (right) == AOP_DPTR &&
8527 IS_TRUE_SYMOP (result) &&
8528 isOperandInFarSpace (result))
8531 genFarFarAssign (result, right, ic);
8535 aopOp (result, ic, TRUE);
8537 /* if they are the same registers */
8538 if (sameRegs (AOP (right), AOP (result)) &&
8539 !isOperandVolatile (result, FALSE) &&
8540 !isOperandVolatile (right, FALSE))
8543 /* if the result is a bit */
8544 if (AOP_TYPE (result) == AOP_CRY)
8547 /* if the right size is a literal then
8548 we know what the value is */
8549 if (AOP_TYPE (right) == AOP_LIT)
8551 if (((int) operandLitValue (right)))
8552 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8554 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8558 /* the right is also a bit variable */
8559 if (AOP_TYPE (right) == AOP_CRY)
8561 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8562 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8568 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8572 /* bit variables done */
8574 size = AOP_SIZE (result);
8576 if (AOP_TYPE (right) == AOP_LIT)
8577 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8579 (AOP_TYPE (result) != AOP_REG) &&
8580 (AOP_TYPE (right) == AOP_LIT) &&
8581 !IS_FLOAT (operandType (right)) &&
8584 emitcode ("clr", "a");
8587 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8588 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8590 aopPut (AOP (result),
8591 aopGet (AOP (right), size, FALSE, FALSE),
8593 isOperandVolatile (result, FALSE));
8600 aopPut (AOP (result),
8601 aopGet (AOP (right), offset, FALSE, FALSE),
8603 isOperandVolatile (result, FALSE));
8609 freeAsmop (right, NULL, ic, TRUE);
8610 freeAsmop (result, NULL, ic, TRUE);
8613 /*-----------------------------------------------------------------*/
8614 /* genJumpTab - genrates code for jump table */
8615 /*-----------------------------------------------------------------*/
8617 genJumpTab (iCode * ic)
8622 D(emitcode ("; genJumpTab",""));
8624 aopOp (IC_JTCOND (ic), ic, FALSE);
8625 /* get the condition into accumulator */
8626 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8628 /* multiply by three */
8629 emitcode ("add", "a,acc");
8630 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8631 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8633 jtab = newiTempLabel (NULL);
8634 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8635 emitcode ("jmp", "@a+dptr");
8636 emitcode ("", "%05d$:", jtab->key + 100);
8637 /* now generate the jump labels */
8638 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8639 jtab = setNextItem (IC_JTLABELS (ic)))
8640 emitcode ("ljmp", "%05d$", jtab->key + 100);
8644 /*-----------------------------------------------------------------*/
8645 /* genCast - gen code for casting */
8646 /*-----------------------------------------------------------------*/
8648 genCast (iCode * ic)
8650 operand *result = IC_RESULT (ic);
8651 sym_link *ctype = operandType (IC_LEFT (ic));
8652 sym_link *rtype = operandType (IC_RIGHT (ic));
8653 operand *right = IC_RIGHT (ic);
8656 D(emitcode("; genCast",""));
8658 /* if they are equivalent then do nothing */
8659 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8662 aopOp (right, ic, FALSE);
8663 aopOp (result, ic, FALSE);
8665 /* if the result is a bit (and not a bitfield) */
8666 // if (AOP_TYPE (result) == AOP_CRY)
8667 if (IS_BITVAR (OP_SYMBOL (result)->type)
8668 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8670 /* if the right size is a literal then
8671 we know what the value is */
8672 if (AOP_TYPE (right) == AOP_LIT)
8674 if (((int) operandLitValue (right)))
8675 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8677 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8682 /* the right is also a bit variable */
8683 if (AOP_TYPE (right) == AOP_CRY)
8685 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8686 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8692 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8697 /* if they are the same size : or less */
8698 if (AOP_SIZE (result) <= AOP_SIZE (right))
8701 /* if they are in the same place */
8702 if (sameRegs (AOP (right), AOP (result)))
8705 /* if they in different places then copy */
8706 size = AOP_SIZE (result);
8710 aopPut (AOP (result),
8711 aopGet (AOP (right), offset, FALSE, FALSE),
8713 isOperandVolatile (result, FALSE));
8720 /* if the result is of type pointer */
8725 sym_link *type = operandType (right);
8726 sym_link *etype = getSpec (type);
8728 /* pointer to generic pointer */
8729 if (IS_GENPTR (ctype))
8732 p_type = DCL_TYPE (type);
8735 if (SPEC_SCLS(etype)==S_REGISTER) {
8736 // let's assume it is a generic pointer
8739 /* we have to go by the storage class */
8740 p_type = PTR_TYPE (SPEC_OCLS (etype));
8744 /* the first two bytes are known */
8745 size = GPTRSIZE - 1;
8749 aopPut (AOP (result),
8750 aopGet (AOP (right), offset, FALSE, FALSE),
8752 isOperandVolatile (result, FALSE));
8755 /* the last byte depending on type */
8757 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8762 // pointerTypeToGPByte will have bitched.
8766 sprintf(gpValStr, "#0x%d", gpVal);
8767 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8772 /* just copy the pointers */
8773 size = AOP_SIZE (result);
8777 aopPut (AOP (result),
8778 aopGet (AOP (right), offset, FALSE, FALSE),
8780 isOperandVolatile (result, FALSE));
8786 /* so we now know that the size of destination is greater
8787 than the size of the source */
8788 /* we move to result for the size of source */
8789 size = AOP_SIZE (right);
8793 aopPut (AOP (result),
8794 aopGet (AOP (right), offset, FALSE, FALSE),
8796 isOperandVolatile (result, FALSE));
8800 /* now depending on the sign of the source && destination */
8801 size = AOP_SIZE (result) - AOP_SIZE (right);
8802 /* if unsigned or not an integral type */
8803 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8806 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8810 /* we need to extend the sign :{ */
8811 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8814 emitcode ("rlc", "a");
8815 emitcode ("subb", "a,acc");
8817 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8820 /* we are done hurray !!!! */
8823 freeAsmop (right, NULL, ic, TRUE);
8824 freeAsmop (result, NULL, ic, TRUE);
8828 /*-----------------------------------------------------------------*/
8829 /* genDjnz - generate decrement & jump if not zero instrucion */
8830 /*-----------------------------------------------------------------*/
8832 genDjnz (iCode * ic, iCode * ifx)
8838 D(emitcode ("; genDjnz",""));
8840 /* if the if condition has a false label
8841 then we cannot save */
8845 /* if the minus is not of the form
8847 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8848 !IS_OP_LITERAL (IC_RIGHT (ic)))
8851 if (operandLitValue (IC_RIGHT (ic)) != 1)
8854 /* if the size of this greater than one then no
8856 if (getSize (operandType (IC_RESULT (ic))) > 1)
8859 /* otherwise we can save BIG */
8860 lbl = newiTempLabel (NULL);
8861 lbl1 = newiTempLabel (NULL);
8863 aopOp (IC_RESULT (ic), ic, FALSE);
8865 if (AOP_NEEDSACC(IC_RESULT(ic)))
8867 /* If the result is accessed indirectly via
8868 * the accumulator, we must explicitly write
8869 * it back after the decrement.
8871 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8873 if (strcmp(rByte, "a"))
8875 /* Something is hopelessly wrong */
8876 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8877 __FILE__, __LINE__);
8878 /* We can just give up; the generated code will be inefficient,
8881 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8884 emitcode ("dec", "%s", rByte);
8885 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8886 emitcode ("jnz", "%05d$", lbl->key + 100);
8888 else if (IS_AOP_PREG (IC_RESULT (ic)))
8890 emitcode ("dec", "%s",
8891 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8892 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8893 emitcode ("jnz", "%05d$", lbl->key + 100);
8897 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8900 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8901 emitcode ("", "%05d$:", lbl->key + 100);
8902 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8903 emitcode ("", "%05d$:", lbl1->key + 100);
8905 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8910 /*-----------------------------------------------------------------*/
8911 /* genReceive - generate code for a receive iCode */
8912 /*-----------------------------------------------------------------*/
8914 genReceive (iCode * ic)
8916 int size = getSize (operandType (IC_RESULT (ic)));
8918 D(emitcode ("; genReceive",""));
8920 if (ic->argreg == 1) { /* first parameter */
8921 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8922 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8923 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8925 offset = fReturnSizeMCS51 - size;
8927 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8928 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8931 aopOp (IC_RESULT (ic), ic, FALSE);
8932 size = AOP_SIZE (IC_RESULT (ic));
8935 emitcode ("pop", "acc");
8936 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8941 aopOp (IC_RESULT (ic), ic, FALSE);
8943 assignResultValue (IC_RESULT (ic));
8945 } else { /* second receive onwards */
8947 aopOp (IC_RESULT (ic), ic, FALSE);
8948 rb1off = ic->argreg;
8950 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8953 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8956 /*-----------------------------------------------------------------*/
8957 /* genDummyRead - generate code for dummy read of volatiles */
8958 /*-----------------------------------------------------------------*/
8960 genDummyRead (iCode * ic)
8965 D(emitcode("; genDummyRead",""));
8967 right = IC_RIGHT (ic);
8969 aopOp (right, ic, FALSE);
8971 /* if the result is a bit */
8972 if (AOP_TYPE (right) == AOP_CRY)
8974 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8978 /* bit variables done */
8980 size = AOP_SIZE (right);
8984 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
8989 freeAsmop (right, NULL, ic, TRUE);
8992 /*-----------------------------------------------------------------*/
8993 /* gen51Code - generate code for 8051 based controllers */
8994 /*-----------------------------------------------------------------*/
8996 gen51Code (iCode * lic)
9001 lineHead = lineCurr = NULL;
9003 /* print the allocation information */
9004 if (allocInfo && currFunc)
9005 printAllocInfo (currFunc, codeOutFile);
9006 /* if debug information required */
9007 if (options.debug && currFunc)
9009 debugFile->writeFunction(currFunc);
9011 if (IS_STATIC (currFunc->etype))
9012 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9014 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9017 /* stack pointer name */
9018 if (options.useXstack)
9024 for (ic = lic; ic; ic = ic->next)
9026 _G.current_iCode = ic;
9028 if (ic->lineno && cln != ic->lineno)
9033 emitcode ("", "C$%s$%d$%d$%d ==.",
9034 FileBaseName (ic->filename), ic->lineno,
9035 ic->level, ic->block);
9038 if (!options.noCcodeInAsm) {
9039 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9040 printCLine(ic->filename, ic->lineno));
9044 if (options.iCodeInAsm) {
9048 for (i=0; i<8; i++) {
9049 sprintf (®sInUse[i],
9050 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9053 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9055 /* if the result is marked as
9056 spilt and rematerializable or code for
9057 this has already been generated then
9059 if (resultRemat (ic) || ic->generated)
9062 /* depending on the operation */
9082 /* IPOP happens only when trying to restore a
9083 spilt live range, if there is an ifx statement
9084 following this pop then the if statement might
9085 be using some of the registers being popped which
9086 would destory the contents of the register so
9087 we need to check for this condition and handle it */
9089 ic->next->op == IFX &&
9090 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9091 genIfx (ic->next, ic);
9109 genEndFunction (ic);
9129 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9146 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9150 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9157 /* note these two are xlated by algebraic equivalence
9158 during parsing SDCC.y */
9159 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9160 "got '>=' or '<=' shouldn't have come here");
9164 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9176 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9180 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9184 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9211 case GET_VALUE_AT_ADDRESS:
9212 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9216 if (POINTER_SET (ic))
9217 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9243 addSet (&_G.sendSet, ic);
9246 case DUMMY_READ_VOLATILE:
9255 _G.current_iCode = NULL;
9257 /* now we are ready to call the
9258 peep hole optimizer */
9259 if (!options.nopeep)
9260 peepHole (&lineHead);
9262 /* now do the actual printing */
9263 printLine (lineHead, codeOutFile);