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 /* else spill location */
712 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
713 /* force a new aop if sizes differ */
714 sym->usl.spillLoc->aop = NULL;
716 sym->aop = op->aop = aop =
717 aopForSym (ic, sym->usl.spillLoc, result);
718 aop->size = getSize (sym->type);
722 /* must be in a register */
723 sym->aop = op->aop = aop = newAsmop (AOP_REG);
724 aop->size = sym->nRegs;
725 for (i = 0; i < sym->nRegs; i++)
726 aop->aopu.aop_reg[i] = sym->regs[i];
729 /*-----------------------------------------------------------------*/
730 /* freeAsmop - free up the asmop given to an operand */
731 /*----------------------------------------------------------------*/
733 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
750 /* depending on the asmop type only three cases need work AOP_RO
751 , AOP_R1 && AOP_STK */
759 emitcode ("pop", "ar0");
763 bitVectUnSetBit (ic->rUsed, R0_IDX);
771 emitcode ("pop", "ar1");
775 bitVectUnSetBit (ic->rUsed, R1_IDX);
781 int stk = aop->aopu.aop_stk + aop->size - 1;
782 bitVectUnSetBit (ic->rUsed, R0_IDX);
783 bitVectUnSetBit (ic->rUsed, R1_IDX);
785 getFreePtr (ic, &aop, FALSE);
789 emitcode ("mov", "a,_bp");
790 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
791 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
795 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
800 emitcode ("pop", "acc");
801 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
804 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
807 freeAsmop (op, NULL, ic, TRUE);
810 emitcode ("pop", "ar1");
816 emitcode ("pop", "ar0");
823 /* all other cases just dealloc */
829 OP_SYMBOL (op)->aop = NULL;
830 /* if the symbol has a spill */
832 SPIL_LOC (op)->aop = NULL;
837 /*-----------------------------------------------------------------*/
838 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
839 /* clobber the accumulator */
840 /*-----------------------------------------------------------------*/
842 aopGetUsesAcc (asmop *aop, int offset)
844 if (offset > (aop->size - 1))
862 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
871 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
875 /* Error case --- will have been caught already */
881 /*-----------------------------------------------------------------*/
882 /* aopGet - for fetching value of the aop */
883 /*-----------------------------------------------------------------*/
885 aopGet (asmop * aop, int offset, bool bit16, bool dname)
890 /* offset is greater than
892 if (offset > (aop->size - 1) &&
893 aop->type != AOP_LIT)
896 /* depending on type */
902 /* if we need to increment it */
903 while (offset > aop->coff)
905 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
909 while (offset < aop->coff)
911 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
918 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
919 return (dname ? "acc" : "a");
921 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
922 rs = Safe_calloc (1, strlen (s) + 1);
927 if (aop->code && aop->coff==0 && offset>=1) {
928 emitcode ("mov", "a,#0x%02x", offset);
929 emitcode ("movc", "a,@a+dptr");
930 return (dname ? "acc" : "a");
933 while (offset > aop->coff)
935 emitcode ("inc", "dptr");
939 while (offset < aop->coff)
941 emitcode ("lcall", "__decdptr");
948 emitcode ("clr", "a");
949 emitcode ("movc", "a,@a+dptr");
953 emitcode ("movx", "a,@dptr");
955 return (dname ? "acc" : "a");
959 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
960 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
962 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
964 sprintf (s, "#(%s >> %d)",
965 aop->aopu.aop_immd.aop_immd1,
969 aop->aopu.aop_immd.aop_immd1);
970 rs = Safe_calloc (1, strlen (s) + 1);
976 sprintf (s, "(%s + %d)",
980 sprintf (s, "%s", aop->aopu.aop_dir);
981 rs = Safe_calloc (1, strlen (s) + 1);
987 return aop->aopu.aop_reg[offset]->dname;
989 return aop->aopu.aop_reg[offset]->name;
992 emitcode ("clr", "a");
993 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
994 emitcode ("rlc", "a");
995 return (dname ? "acc" : "a");
998 if (!offset && dname)
1000 return aop->aopu.aop_str[offset];
1003 return aopLiteral (aop->aopu.aop_lit, offset);
1007 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1011 return aop->aopu.aop_str[offset];
1015 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1016 "aopget got unsupported aop->type");
1019 /*-----------------------------------------------------------------*/
1020 /* aopPut - puts a string for a aop */
1021 /*-----------------------------------------------------------------*/
1023 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1027 if (aop->size && offset > (aop->size - 1))
1029 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1030 "aopPut got offset > aop->size");
1034 /* will assign value to value */
1035 /* depending on where it is ofcourse */
1040 sprintf (d, "(%s + %d)",
1041 aop->aopu.aop_dir, offset);
1043 sprintf (d, "%s", aop->aopu.aop_dir);
1045 if (strcmp (d, s) ||
1047 emitcode ("mov", "%s,%s", d, s);
1052 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1053 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1056 strcmp (s, "r0") == 0 ||
1057 strcmp (s, "r1") == 0 ||
1058 strcmp (s, "r2") == 0 ||
1059 strcmp (s, "r3") == 0 ||
1060 strcmp (s, "r4") == 0 ||
1061 strcmp (s, "r5") == 0 ||
1062 strcmp (s, "r6") == 0 ||
1063 strcmp (s, "r7") == 0)
1064 emitcode ("mov", "%s,%s",
1065 aop->aopu.aop_reg[offset]->dname, s);
1067 emitcode ("mov", "%s,%s",
1068 aop->aopu.aop_reg[offset]->name, s);
1075 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1076 "aopPut writing to code space");
1080 while (offset > aop->coff)
1083 emitcode ("inc", "dptr");
1086 while (offset < aop->coff)
1089 emitcode ("lcall", "__decdptr");
1094 /* if not in accumulater */
1097 emitcode ("movx", "@dptr,a");
1102 while (offset > aop->coff)
1105 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1107 while (offset < aop->coff)
1110 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1117 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1123 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1125 else if (strcmp (s, "r0") == 0 ||
1126 strcmp (s, "r1") == 0 ||
1127 strcmp (s, "r2") == 0 ||
1128 strcmp (s, "r3") == 0 ||
1129 strcmp (s, "r4") == 0 ||
1130 strcmp (s, "r5") == 0 ||
1131 strcmp (s, "r6") == 0 ||
1132 strcmp (s, "r7") == 0)
1135 sprintf (buffer, "a%s", s);
1136 emitcode ("mov", "@%s,%s",
1137 aop->aopu.aop_ptr->name, buffer);
1140 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1145 if (strcmp (s, "a") == 0)
1146 emitcode ("push", "acc");
1150 emitcode ("push", "acc");
1152 emitcode ("push", s);
1158 /* if bit variable */
1159 if (!aop->aopu.aop_dir)
1161 emitcode ("clr", "a");
1162 emitcode ("rlc", "a");
1167 emitcode ("clr", "%s", aop->aopu.aop_dir);
1169 emitcode ("setb", "%s", aop->aopu.aop_dir);
1170 else if (!strcmp (s, "c"))
1171 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1174 if (strcmp (s, "a"))
1179 /* set C, if a >= 1 */
1180 emitcode ("add", "a,#0xff");
1181 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1189 if (strcmp (aop->aopu.aop_str[offset], s) ||
1191 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1196 if (!offset && (strcmp (s, "acc") == 0) &&
1200 if (strcmp (aop->aopu.aop_str[offset], s) &&
1202 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1206 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1207 "aopPut got unsupported aop->type");
1215 /*-----------------------------------------------------------------*/
1216 /* pointToEnd :- points to the last byte of the operand */
1217 /*-----------------------------------------------------------------*/
1219 pointToEnd (asmop * aop)
1225 aop->coff = count = (aop->size - 1);
1231 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1235 emitcode ("inc", "dptr");
1242 /*-----------------------------------------------------------------*/
1243 /* reAdjustPreg - points a register back to where it should */
1244 /*-----------------------------------------------------------------*/
1246 reAdjustPreg (asmop * aop)
1248 if ((aop->coff==0) || aop->size <= 1)
1256 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1261 emitcode ("lcall", "__decdptr");
1268 #define AOP(op) op->aop
1269 #define AOP_TYPE(op) AOP(op)->type
1270 #define AOP_SIZE(op) AOP(op)->size
1271 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1272 AOP_TYPE(x) == AOP_R0))
1274 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1275 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1277 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1278 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1279 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1282 /*-----------------------------------------------------------------*/
1283 /* opIsGptr: returns non-zero if the passed operand is */
1284 /* a generic pointer type. */
1285 /*-----------------------------------------------------------------*/
1287 opIsGptr (operand * op)
1289 sym_link *type = operandType (op);
1291 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1298 /*-----------------------------------------------------------------*/
1299 /* getDataSize - get the operand data size */
1300 /*-----------------------------------------------------------------*/
1302 getDataSize (operand * op)
1305 size = AOP_SIZE (op);
1306 if (size == GPTRSIZE)
1308 sym_link *type = operandType (op);
1309 if (IS_GENPTR (type))
1311 /* generic pointer; arithmetic operations
1312 * should ignore the high byte (pointer type).
1320 /*-----------------------------------------------------------------*/
1321 /* outAcc - output Acc */
1322 /*-----------------------------------------------------------------*/
1324 outAcc (operand * result)
1327 size = getDataSize (result);
1330 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1333 /* unsigned or positive */
1336 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1341 /*-----------------------------------------------------------------*/
1342 /* outBitC - output a bit C */
1343 /*-----------------------------------------------------------------*/
1345 outBitC (operand * result)
1347 /* if the result is bit */
1348 if (AOP_TYPE (result) == AOP_CRY)
1349 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1352 emitcode ("clr", "a");
1353 emitcode ("rlc", "a");
1358 /*-----------------------------------------------------------------*/
1359 /* toBoolean - emit code for orl a,operator(sizeop) */
1360 /*-----------------------------------------------------------------*/
1362 toBoolean (operand * oper)
1364 int size = AOP_SIZE (oper) - 1;
1366 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1368 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1372 /*-----------------------------------------------------------------*/
1373 /* genNot - generate code for ! operation */
1374 /*-----------------------------------------------------------------*/
1380 D(emitcode ("; genNot",""));
1382 /* assign asmOps to operand & result */
1383 aopOp (IC_LEFT (ic), ic, FALSE);
1384 aopOp (IC_RESULT (ic), ic, TRUE);
1386 /* if in bit space then a special case */
1387 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1389 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1390 emitcode ("cpl", "c");
1391 outBitC (IC_RESULT (ic));
1395 toBoolean (IC_LEFT (ic));
1397 tlbl = newiTempLabel (NULL);
1398 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1399 emitcode ("", "%05d$:", tlbl->key + 100);
1400 outBitC (IC_RESULT (ic));
1403 /* release the aops */
1404 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1405 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1409 /*-----------------------------------------------------------------*/
1410 /* genCpl - generate code for complement */
1411 /*-----------------------------------------------------------------*/
1419 D(emitcode ("; genCpl",""));
1421 /* assign asmOps to operand & result */
1422 aopOp (IC_LEFT (ic), ic, FALSE);
1423 aopOp (IC_RESULT (ic), ic, TRUE);
1425 /* special case if in bit space */
1426 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1427 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1428 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1429 emitcode ("cpl", "c");
1430 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1433 tlbl=newiTempLabel(NULL);
1434 emitcode ("cjne", "%s,#0x01,%05d$",
1435 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE), tlbl->key+100);
1436 emitcode ("", "%05d$:", tlbl->key+100);
1437 outBitC (IC_RESULT(ic));
1441 size = AOP_SIZE (IC_RESULT (ic));
1444 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1446 emitcode ("cpl", "a");
1447 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1452 /* release the aops */
1453 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1454 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1457 /*-----------------------------------------------------------------*/
1458 /* genUminusFloat - unary minus for floating points */
1459 /*-----------------------------------------------------------------*/
1461 genUminusFloat (operand * op, operand * result)
1463 int size, offset = 0;
1466 D(emitcode ("; genUminusFloat",""));
1468 /* for this we just copy and then flip the bit */
1470 size = AOP_SIZE (op) - 1;
1474 aopPut (AOP (result),
1475 aopGet (AOP (op), offset, FALSE, FALSE),
1477 isOperandVolatile (result, FALSE));
1481 l = aopGet (AOP (op), offset, FALSE, FALSE);
1485 emitcode ("cpl", "acc.7");
1486 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1489 /*-----------------------------------------------------------------*/
1490 /* genUminus - unary minus code generation */
1491 /*-----------------------------------------------------------------*/
1493 genUminus (iCode * ic)
1496 sym_link *optype, *rtype;
1499 D(emitcode ("; genUminus",""));
1502 aopOp (IC_LEFT (ic), ic, FALSE);
1503 aopOp (IC_RESULT (ic), ic, TRUE);
1505 /* if both in bit space then special
1507 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1508 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1511 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1512 emitcode ("cpl", "c");
1513 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1517 optype = operandType (IC_LEFT (ic));
1518 rtype = operandType (IC_RESULT (ic));
1520 /* if float then do float stuff */
1521 if (IS_FLOAT (optype))
1523 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1527 /* otherwise subtract from zero */
1528 size = AOP_SIZE (IC_LEFT (ic));
1533 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1534 if (!strcmp (l, "a"))
1538 emitcode ("cpl", "a");
1539 emitcode ("addc", "a,#0");
1545 emitcode ("clr", "a");
1546 emitcode ("subb", "a,%s", l);
1548 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1551 /* if any remaining bytes in the result */
1552 /* we just need to propagate the sign */
1553 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1555 emitcode ("rlc", "a");
1556 emitcode ("subb", "a,acc");
1558 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1562 /* release the aops */
1563 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1564 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1567 /*-----------------------------------------------------------------*/
1568 /* saveRegisters - will look for a call and save the registers */
1569 /*-----------------------------------------------------------------*/
1571 saveRegisters (iCode * lic)
1578 for (ic = lic; ic; ic = ic->next)
1579 if (ic->op == CALL || ic->op == PCALL)
1584 fprintf (stderr, "found parameter push with no function call\n");
1588 /* if the registers have been saved already or don't need to be then
1592 if (IS_SYMOP(IC_LEFT(ic)) &&
1593 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1594 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1597 /* safe the registers in use at this time but skip the
1598 ones for the result */
1599 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1600 mcs51_rUmaskForOp (IC_RESULT(ic)));
1603 if (options.useXstack)
1605 if (bitVectBitValue (rsave, R0_IDX))
1606 emitcode ("mov", "b,r0");
1607 emitcode ("mov", "r0,%s", spname);
1608 for (i = 0; i < mcs51_nRegs; i++)
1610 if (bitVectBitValue (rsave, i))
1613 emitcode ("mov", "a,b");
1615 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1616 emitcode ("movx", "@r0,a");
1617 emitcode ("inc", "r0");
1620 emitcode ("mov", "%s,r0", spname);
1621 if (bitVectBitValue (rsave, R0_IDX))
1622 emitcode ("mov", "r0,b");
1625 for (i = 0; i < mcs51_nRegs; i++)
1627 if (bitVectBitValue (rsave, i))
1628 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1632 /*-----------------------------------------------------------------*/
1633 /* unsaveRegisters - pop the pushed registers */
1634 /*-----------------------------------------------------------------*/
1636 unsaveRegisters (iCode * ic)
1641 /* restore the registers in use at this time but skip the
1642 ones for the result */
1643 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1644 mcs51_rUmaskForOp (IC_RESULT(ic)));
1646 if (options.useXstack)
1648 emitcode ("mov", "r0,%s", spname);
1649 for (i = mcs51_nRegs; i >= 0; i--)
1651 if (bitVectBitValue (rsave, i))
1653 emitcode ("dec", "r0");
1654 emitcode ("movx", "a,@r0");
1656 emitcode ("mov", "b,a");
1658 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1662 emitcode ("mov", "%s,r0", spname);
1663 if (bitVectBitValue (rsave, R0_IDX))
1664 emitcode ("mov", "r0,b");
1667 for (i = mcs51_nRegs; i >= 0; i--)
1669 if (bitVectBitValue (rsave, i))
1670 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1676 /*-----------------------------------------------------------------*/
1678 /*-----------------------------------------------------------------*/
1680 pushSide (operand * oper, int size)
1685 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1686 if (AOP_TYPE (oper) != AOP_REG &&
1687 AOP_TYPE (oper) != AOP_DIR &&
1690 emitcode ("mov", "a,%s", l);
1691 emitcode ("push", "acc");
1694 emitcode ("push", "%s", l);
1698 /*-----------------------------------------------------------------*/
1699 /* assignResultValue - */
1700 /*-----------------------------------------------------------------*/
1702 assignResultValue (operand * oper)
1705 int size = AOP_SIZE (oper);
1708 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1714 /*-----------------------------------------------------------------*/
1715 /* genXpush - pushes onto the external stack */
1716 /*-----------------------------------------------------------------*/
1718 genXpush (iCode * ic)
1720 asmop *aop = newAsmop (0);
1722 int size, offset = 0;
1724 D(emitcode ("; genXpush",""));
1726 aopOp (IC_LEFT (ic), ic, FALSE);
1727 r = getFreePtr (ic, &aop, FALSE);
1730 emitcode ("mov", "%s,_spx", r->name);
1732 size = AOP_SIZE (IC_LEFT (ic));
1736 char *l = aopGet (AOP (IC_LEFT (ic)),
1737 offset++, FALSE, FALSE);
1739 emitcode ("movx", "@%s,a", r->name);
1740 emitcode ("inc", "%s", r->name);
1745 emitcode ("mov", "_spx,%s", r->name);
1747 freeAsmop (NULL, aop, ic, TRUE);
1748 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1751 /*-----------------------------------------------------------------*/
1752 /* genIpush - genrate code for pushing this gets a little complex */
1753 /*-----------------------------------------------------------------*/
1755 genIpush (iCode * ic)
1757 int size, offset = 0;
1760 D(emitcode ("; genIpush",""));
1762 /* if this is not a parm push : ie. it is spill push
1763 and spill push is always done on the local stack */
1767 /* and the item is spilt then do nothing */
1768 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1771 aopOp (IC_LEFT (ic), ic, FALSE);
1772 size = AOP_SIZE (IC_LEFT (ic));
1773 /* push it on the stack */
1776 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1782 emitcode ("push", "%s", l);
1787 /* this is a paramter push: in this case we call
1788 the routine to find the call and save those
1789 registers that need to be saved */
1792 /* if use external stack then call the external
1793 stack pushing routine */
1794 if (options.useXstack)
1800 /* then do the push */
1801 aopOp (IC_LEFT (ic), ic, FALSE);
1804 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1805 size = AOP_SIZE (IC_LEFT (ic));
1809 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1810 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1811 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1814 emitcode ("mov", "a,%s", l);
1815 emitcode ("push", "acc");
1818 emitcode ("push", "%s", l);
1821 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1824 /*-----------------------------------------------------------------*/
1825 /* genIpop - recover the registers: can happen only for spilling */
1826 /*-----------------------------------------------------------------*/
1828 genIpop (iCode * ic)
1832 D(emitcode ("; genIpop",""));
1834 /* if the temp was not pushed then */
1835 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1838 aopOp (IC_LEFT (ic), ic, FALSE);
1839 size = AOP_SIZE (IC_LEFT (ic));
1840 offset = (size - 1);
1842 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1845 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1848 /*-----------------------------------------------------------------*/
1849 /* unsaveRBank - restores the resgister bank from stack */
1850 /*-----------------------------------------------------------------*/
1852 unsaveRBank (int bank, iCode * ic, bool popPsw)
1858 if (options.useXstack)
1862 /* Assume r0 is available for use. */
1863 r = mcs51_regWithIdx (R0_IDX);;
1868 r = getFreePtr (ic, &aop, FALSE);
1870 emitcode ("mov", "%s,_spx", r->name);
1875 if (options.useXstack)
1877 emitcode ("movx", "a,@%s", r->name);
1878 emitcode ("mov", "psw,a");
1879 emitcode ("dec", "%s", r->name);
1883 emitcode ("pop", "psw");
1887 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1889 if (options.useXstack)
1891 emitcode ("movx", "a,@%s", r->name);
1892 emitcode ("mov", "(%s+%d),a",
1893 regs8051[i].base, 8 * bank + regs8051[i].offset);
1894 emitcode ("dec", "%s", r->name);
1898 emitcode ("pop", "(%s+%d)",
1899 regs8051[i].base, 8 * bank + regs8051[i].offset);
1902 if (options.useXstack)
1904 emitcode ("mov", "_spx,%s", r->name);
1909 freeAsmop (NULL, aop, ic, TRUE);
1913 /*-----------------------------------------------------------------*/
1914 /* saveRBank - saves an entire register bank on the stack */
1915 /*-----------------------------------------------------------------*/
1917 saveRBank (int bank, iCode * ic, bool pushPsw)
1923 if (options.useXstack)
1927 /* Assume r0 is available for use. */
1928 r = mcs51_regWithIdx (R0_IDX);;
1933 r = getFreePtr (ic, &aop, FALSE);
1935 emitcode ("mov", "%s,_spx", r->name);
1938 for (i = 0; i < mcs51_nRegs; i++)
1940 if (options.useXstack)
1942 emitcode ("inc", "%s", r->name);
1943 emitcode ("mov", "a,(%s+%d)",
1944 regs8051[i].base, 8 * bank + regs8051[i].offset);
1945 emitcode ("movx", "@%s,a", r->name);
1948 emitcode ("push", "(%s+%d)",
1949 regs8051[i].base, 8 * bank + regs8051[i].offset);
1954 if (options.useXstack)
1956 emitcode ("mov", "a,psw");
1957 emitcode ("movx", "@%s,a", r->name);
1958 emitcode ("inc", "%s", r->name);
1959 emitcode ("mov", "_spx,%s", r->name);
1964 emitcode ("push", "psw");
1967 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1972 freeAsmop (NULL, aop, ic, TRUE);
1981 /*-----------------------------------------------------------------*/
1982 /* genSend - gen code for SEND */
1983 /*-----------------------------------------------------------------*/
1984 static void genSend(set *sendSet)
1989 for (sic = setFirstItem (_G.sendSet); sic;
1990 sic = setNextItem (_G.sendSet)) {
1991 int size, offset = 0;
1992 aopOp (IC_LEFT (sic), sic, FALSE);
1993 size = AOP_SIZE (IC_LEFT (sic));
1995 if (sic->argreg == 1) {
1997 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1999 if (strcmp (l, fReturn[offset]))
2000 emitcode ("mov", "%s,%s", fReturn[offset], l);
2006 emitcode ("mov","b1_%d,%s",rb1_count++,
2007 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2010 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2014 /*-----------------------------------------------------------------*/
2015 /* genCall - generates a call statement */
2016 /*-----------------------------------------------------------------*/
2018 genCall (iCode * ic)
2021 // bool restoreBank = FALSE;
2022 bool swapBanks = FALSE;
2024 D(emitcode("; genCall",""));
2026 dtype = operandType (IC_LEFT (ic));
2027 /* if send set is not empty the assign */
2030 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2031 genSend(reverseSet(_G.sendSet));
2033 genSend(_G.sendSet);
2039 /* if we are calling a not _naked function that is not using
2040 the same register bank then we need to save the
2041 destination registers on the stack */
2042 dtype = operandType (IC_LEFT (ic));
2043 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2044 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2045 !IFFUNC_ISISR (dtype))
2050 /* if caller saves & we have not saved then */
2056 emitcode ("mov", "psw,#0x%02x",
2057 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2061 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2062 OP_SYMBOL (IC_LEFT (ic))->rname :
2063 OP_SYMBOL (IC_LEFT (ic))->name));
2067 emitcode ("mov", "psw,#0x%02x",
2068 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2071 /* if we need assign a result value */
2072 if ((IS_ITEMP (IC_RESULT (ic)) &&
2073 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2074 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2075 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2076 IS_TRUE_SYMOP (IC_RESULT (ic)))
2080 aopOp (IC_RESULT (ic), ic, FALSE);
2083 assignResultValue (IC_RESULT (ic));
2085 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2088 /* adjust the stack for parameters if
2093 if (ic->parmBytes > 3)
2095 emitcode ("mov", "a,%s", spname);
2096 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2097 emitcode ("mov", "%s,a", spname);
2100 for (i = 0; i < ic->parmBytes; i++)
2101 emitcode ("dec", "%s", spname);
2104 /* if we hade saved some registers then unsave them */
2105 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2106 unsaveRegisters (ic);
2108 // /* if register bank was saved then pop them */
2110 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2113 /*-----------------------------------------------------------------*/
2114 /* -10l - generates a call by pointer statement */
2115 /*-----------------------------------------------------------------*/
2117 genPcall (iCode * ic)
2120 symbol *rlbl = newiTempLabel (NULL);
2121 // bool restoreBank=FALSE;
2122 bool swapBanks = FALSE;
2124 D(emitcode("; genPCall",""));
2126 /* if caller saves & we have not saved then */
2130 /* if we are calling a not _naked function that is not using
2131 the same register bank then we need to save the
2132 destination registers on the stack */
2133 dtype = operandType (IC_LEFT (ic))->next;
2134 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2135 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2136 !IFFUNC_ISISR (dtype))
2138 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2139 // restoreBank=TRUE;
2141 // need caution message to user here
2144 /* push the return address on to the stack */
2145 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2146 emitcode ("push", "acc");
2147 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2148 emitcode ("push", "acc");
2150 /* now push the calling address */
2151 aopOp (IC_LEFT (ic), ic, FALSE);
2153 pushSide (IC_LEFT (ic), FPTRSIZE);
2155 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2157 /* if send set is not empty the assign */
2160 genSend(reverseSet(_G.sendSet));
2166 emitcode ("mov", "psw,#0x%02x",
2167 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2171 emitcode ("ret", "");
2172 emitcode ("", "%05d$:", (rlbl->key + 100));
2177 emitcode ("mov", "psw,#0x%02x",
2178 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2181 /* if we need assign a result value */
2182 if ((IS_ITEMP (IC_RESULT (ic)) &&
2183 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2184 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2185 IS_TRUE_SYMOP (IC_RESULT (ic)))
2189 aopOp (IC_RESULT (ic), ic, FALSE);
2192 assignResultValue (IC_RESULT (ic));
2194 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2197 /* adjust the stack for parameters if
2202 if (ic->parmBytes > 3)
2204 emitcode ("mov", "a,%s", spname);
2205 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2206 emitcode ("mov", "%s,a", spname);
2209 for (i = 0; i < ic->parmBytes; i++)
2210 emitcode ("dec", "%s", spname);
2214 // /* if register bank was saved then unsave them */
2216 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2218 /* if we hade saved some registers then
2220 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2221 unsaveRegisters (ic);
2224 /*-----------------------------------------------------------------*/
2225 /* resultRemat - result is rematerializable */
2226 /*-----------------------------------------------------------------*/
2228 resultRemat (iCode * ic)
2230 if (SKIP_IC (ic) || ic->op == IFX)
2233 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2235 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2236 if (sym->remat && !POINTER_SET (ic))
2243 #if defined(__BORLANDC__) || defined(_MSC_VER)
2244 #define STRCASECMP stricmp
2246 #define STRCASECMP strcasecmp
2249 /*-----------------------------------------------------------------*/
2250 /* inExcludeList - return 1 if the string is in exclude Reg list */
2251 /*-----------------------------------------------------------------*/
2253 regsCmp(void *p1, void *p2)
2255 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2259 inExcludeList (char *s)
2261 const char *p = setFirstItem(options.excludeRegsSet);
2263 if (p == NULL || STRCASECMP(p, "none") == 0)
2267 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2270 /*-----------------------------------------------------------------*/
2271 /* genFunction - generated code for function entry */
2272 /*-----------------------------------------------------------------*/
2274 genFunction (iCode * ic)
2278 bool switchedPSW = FALSE;
2279 int calleesaves_saved_register = -1;
2282 /* create the function header */
2283 emitcode (";", "-----------------------------------------");
2284 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2285 emitcode (";", "-----------------------------------------");
2287 emitcode ("", "%s:", sym->rname);
2288 ftype = operandType (IC_LEFT (ic));
2290 if (IFFUNC_ISNAKED(ftype))
2292 emitcode(";", "naked function: no prologue.");
2296 /* here we need to generate the equates for the
2297 register bank if required */
2298 if (FUNC_REGBANK (ftype) != rbank)
2302 rbank = FUNC_REGBANK (ftype);
2303 for (i = 0; i < mcs51_nRegs; i++)
2305 if (strcmp (regs8051[i].base, "0") == 0)
2306 emitcode ("", "%s = 0x%02x",
2308 8 * rbank + regs8051[i].offset);
2310 emitcode ("", "%s = %s + 0x%02x",
2313 8 * rbank + regs8051[i].offset);
2317 /* if this is an interrupt service routine then
2318 save acc, b, dpl, dph */
2319 if (IFFUNC_ISISR (sym->type))
2322 if (!inExcludeList ("acc"))
2323 emitcode ("push", "acc");
2324 if (!inExcludeList ("b"))
2325 emitcode ("push", "b");
2326 if (!inExcludeList ("dpl"))
2327 emitcode ("push", "dpl");
2328 if (!inExcludeList ("dph"))
2329 emitcode ("push", "dph");
2330 /* if this isr has no bank i.e. is going to
2331 run with bank 0 , then we need to save more
2333 if (!FUNC_REGBANK (sym->type))
2336 /* if this function does not call any other
2337 function then we can be economical and
2338 save only those registers that are used */
2339 if (!IFFUNC_HASFCALL(sym->type))
2343 /* if any registers used */
2346 /* save the registers used */
2347 for (i = 0; i < sym->regsUsed->size; i++)
2349 if (bitVectBitValue (sym->regsUsed, i) ||
2350 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2351 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2359 /* this function has a function call cannot
2360 determines register usage so we will have to push the
2362 saveRBank (0, ic, FALSE);
2363 if (options.parms_in_bank1) {
2365 for (i=0; i < 8 ; i++ ) {
2366 emitcode ("push","%s",rb1regs[i]);
2373 /* This ISR uses a non-zero bank.
2375 * We assume that the bank is available for our
2378 * However, if this ISR calls a function which uses some
2379 * other bank, we must save that bank entirely.
2381 unsigned long banksToSave = 0;
2383 if (IFFUNC_HASFCALL(sym->type))
2386 #define MAX_REGISTER_BANKS 4
2391 for (i = ic; i; i = i->next)
2393 if (i->op == ENDFUNCTION)
2395 /* we got to the end OK. */
2403 dtype = operandType (IC_LEFT(i));
2405 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2407 /* Mark this bank for saving. */
2408 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2410 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2414 banksToSave |= (1 << FUNC_REGBANK(dtype));
2417 /* And note that we don't need to do it in
2425 /* This is a mess; we have no idea what
2426 * register bank the called function might
2429 * The only thing I can think of to do is
2430 * throw a warning and hope.
2432 werror(W_FUNCPTR_IN_USING_ISR);
2436 if (banksToSave && options.useXstack)
2438 /* Since we aren't passing it an ic,
2439 * saveRBank will assume r0 is available to abuse.
2441 * So switch to our (trashable) bank now, so
2442 * the caller's R0 isn't trashed.
2444 emitcode ("push", "psw");
2445 emitcode ("mov", "psw,#0x%02x",
2446 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2450 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2452 if (banksToSave & (1 << ix))
2454 saveRBank(ix, NULL, FALSE);
2458 // TODO: this needs a closer look
2459 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2464 /* if callee-save to be used for this function
2465 then save the registers being used in this function */
2466 if (IFFUNC_CALLEESAVES(sym->type))
2470 /* if any registers used */
2473 /* save the registers used */
2474 for (i = 0; i < sym->regsUsed->size; i++)
2476 if (bitVectBitValue (sym->regsUsed, i) ||
2477 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2479 /* remember one saved register for later usage */
2480 if (calleesaves_saved_register < 0)
2481 calleesaves_saved_register = i;
2482 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2490 /* set the register bank to the desired value */
2491 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2494 emitcode ("push", "psw");
2495 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2498 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2501 if (options.useXstack)
2503 emitcode ("mov", "r0,%s", spname);
2504 emitcode ("mov", "a,_bp");
2505 emitcode ("movx", "@r0,a");
2506 emitcode ("inc", "%s", spname);
2510 /* set up the stack */
2511 emitcode ("push", "_bp"); /* save the callers stack */
2513 emitcode ("mov", "_bp,%s", spname);
2516 /* adjust the stack for the function */
2522 werror (W_STACK_OVERFLOW, sym->name);
2524 if (i > 3 && sym->recvSize < 4)
2527 emitcode ("mov", "a,sp");
2528 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2529 emitcode ("mov", "sp,a");
2534 if (IFFUNC_CALLEESAVES(sym->type))
2536 /* if it's a callee-saves function we need a saved register */
2537 if (calleesaves_saved_register >= 0)
2539 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2540 emitcode ("mov", "a,sp");
2541 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2542 emitcode ("mov", "sp,a");
2543 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2546 /* do it the hard way */
2548 emitcode ("inc", "sp");
2552 /* not callee-saves, we can clobber r0 */
2553 emitcode ("mov", "r0,a");
2554 emitcode ("mov", "a,sp");
2555 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2556 emitcode ("mov", "sp,a");
2557 emitcode ("mov", "a,r0");
2562 emitcode ("inc", "sp");
2568 emitcode ("mov", "a,_spx");
2569 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2570 emitcode ("mov", "_spx,a");
2573 /* if critical function then turn interrupts off */
2574 if (IFFUNC_ISCRITICAL (ftype))
2576 emitcode ("mov", "c,ea");
2577 emitcode ("push", "psw"); /* save old ea via c in psw */
2578 emitcode ("clr", "ea");
2582 /*-----------------------------------------------------------------*/
2583 /* genEndFunction - generates epilogue for functions */
2584 /*-----------------------------------------------------------------*/
2586 genEndFunction (iCode * ic)
2588 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2590 if (IFFUNC_ISNAKED(sym->type))
2592 emitcode(";", "naked function: no epilogue.");
2596 if (IFFUNC_ISCRITICAL (sym->type))
2598 emitcode ("pop", "psw"); /* restore ea via c in psw */
2599 emitcode ("mov", "ea,c");
2602 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2604 emitcode ("mov", "%s,_bp", spname);
2607 /* if use external stack but some variables were
2608 added to the local stack then decrement the
2610 if (options.useXstack && sym->stack)
2612 emitcode ("mov", "a,sp");
2613 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2614 emitcode ("mov", "sp,a");
2618 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2620 if (options.useXstack)
2622 emitcode ("mov", "r0,%s", spname);
2623 emitcode ("movx", "a,@r0");
2624 emitcode ("mov", "_bp,a");
2625 emitcode ("dec", "%s", spname);
2629 emitcode ("pop", "_bp");
2633 /* restore the register bank */
2634 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2636 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2637 || !options.useXstack)
2639 /* Special case of ISR using non-zero bank with useXstack
2642 emitcode ("pop", "psw");
2646 if (IFFUNC_ISISR (sym->type))
2649 /* now we need to restore the registers */
2650 /* if this isr has no bank i.e. is going to
2651 run with bank 0 , then we need to save more
2653 if (!FUNC_REGBANK (sym->type))
2655 /* if this function does not call any other
2656 function then we can be economical and
2657 save only those registers that are used */
2658 if (!IFFUNC_HASFCALL(sym->type))
2662 /* if any registers used */
2665 /* save the registers used */
2666 for (i = sym->regsUsed->size; i >= 0; i--)
2668 if (bitVectBitValue (sym->regsUsed, i) ||
2669 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2670 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2677 if (options.parms_in_bank1) {
2679 for (i = 7 ; i >= 0 ; i-- ) {
2680 emitcode ("pop","%s",rb1regs[i]);
2683 /* this function has a function call cannot
2684 determines register usage so we will have to pop the
2686 unsaveRBank (0, ic, FALSE);
2691 /* This ISR uses a non-zero bank.
2693 * Restore any register banks saved by genFunction
2696 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2699 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2701 if (savedBanks & (1 << ix))
2703 unsaveRBank(ix, NULL, FALSE);
2707 if (options.useXstack)
2709 /* Restore bank AFTER calling unsaveRBank,
2710 * since it can trash r0.
2712 emitcode ("pop", "psw");
2716 if (!inExcludeList ("dph"))
2717 emitcode ("pop", "dph");
2718 if (!inExcludeList ("dpl"))
2719 emitcode ("pop", "dpl");
2720 if (!inExcludeList ("b"))
2721 emitcode ("pop", "b");
2722 if (!inExcludeList ("acc"))
2723 emitcode ("pop", "acc");
2725 /* if debug then send end of function */
2726 if (options.debug && currFunc)
2729 emitcode ("", "C$%s$%d$%d$%d ==.",
2730 FileBaseName (ic->filename), currFunc->lastLine,
2731 ic->level, ic->block);
2732 if (IS_STATIC (currFunc->etype))
2733 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2735 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2739 emitcode ("reti", "");
2743 if (IFFUNC_CALLEESAVES(sym->type))
2747 /* if any registers used */
2750 /* save the registers used */
2751 for (i = sym->regsUsed->size; i >= 0; i--)
2753 if (bitVectBitValue (sym->regsUsed, i) ||
2754 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2755 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2761 /* if debug then send end of function */
2762 if (options.debug && currFunc)
2765 emitcode ("", "C$%s$%d$%d$%d ==.",
2766 FileBaseName (ic->filename), currFunc->lastLine,
2767 ic->level, ic->block);
2768 if (IS_STATIC (currFunc->etype))
2769 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2771 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2775 emitcode ("ret", "");
2780 /*-----------------------------------------------------------------*/
2781 /* genRet - generate code for return statement */
2782 /*-----------------------------------------------------------------*/
2786 int size, offset = 0, pushed = 0;
2788 D(emitcode ("; genRet",""));
2790 /* if we have no return value then
2791 just generate the "ret" */
2795 /* we have something to return then
2796 move the return value into place */
2797 aopOp (IC_LEFT (ic), ic, FALSE);
2798 size = AOP_SIZE (IC_LEFT (ic));
2803 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2806 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2808 emitcode ("push", "%s", l);
2813 l = aopGet (AOP (IC_LEFT (ic)), offset,
2815 if (strcmp (fReturn[offset], l))
2816 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2825 if (strcmp (fReturn[pushed], "a"))
2826 emitcode ("pop", fReturn[pushed]);
2828 emitcode ("pop", "acc");
2831 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2834 /* generate a jump to the return label
2835 if the next is not the return statement */
2836 if (!(ic->next && ic->next->op == LABEL &&
2837 IC_LABEL (ic->next) == returnLabel))
2839 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2843 /*-----------------------------------------------------------------*/
2844 /* genLabel - generates a label */
2845 /*-----------------------------------------------------------------*/
2847 genLabel (iCode * ic)
2849 /* special case never generate */
2850 if (IC_LABEL (ic) == entryLabel)
2853 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2856 /*-----------------------------------------------------------------*/
2857 /* genGoto - generates a ljmp */
2858 /*-----------------------------------------------------------------*/
2860 genGoto (iCode * ic)
2862 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2865 /*-----------------------------------------------------------------*/
2866 /* findLabelBackwards: walks back through the iCode chain looking */
2867 /* for the given label. Returns number of iCode instructions */
2868 /* between that label and given ic. */
2869 /* Returns zero if label not found. */
2870 /*-----------------------------------------------------------------*/
2872 findLabelBackwards (iCode * ic, int key)
2881 /* If we have any pushes or pops, we cannot predict the distance.
2882 I don't like this at all, this should be dealt with in the
2884 if (ic->op == IPUSH || ic->op == IPOP) {
2888 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2897 /*-----------------------------------------------------------------*/
2898 /* genPlusIncr :- does addition with increment if possible */
2899 /*-----------------------------------------------------------------*/
2901 genPlusIncr (iCode * ic)
2903 unsigned int icount;
2904 unsigned int size = getDataSize (IC_RESULT (ic));
2906 /* will try to generate an increment */
2907 /* if the right side is not a literal
2909 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2912 /* if the literal value of the right hand side
2913 is greater than 4 then it is not worth it */
2914 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2917 D(emitcode ("; genPlusIncr",""));
2919 /* if increment >=16 bits in register or direct space */
2920 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2921 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2929 /* If the next instruction is a goto and the goto target
2930 * is < 10 instructions previous to this, we can generate
2931 * jumps straight to that target.
2933 if (ic->next && ic->next->op == GOTO
2934 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2935 && labelRange <= 10)
2937 emitcode (";", "tail increment optimized");
2938 tlbl = IC_LABEL (ic->next);
2943 tlbl = newiTempLabel (NULL);
2946 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2947 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2948 IS_AOP_PREG (IC_RESULT (ic)))
2949 emitcode ("cjne", "%s,#0x00,%05d$",
2950 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2954 emitcode ("clr", "a");
2955 emitcode ("cjne", "a,%s,%05d$",
2956 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2960 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, 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)), MSB16, FALSE, FALSE),
2969 emitcode ("cjne", "a,%s,%05d$",
2970 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
2973 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2977 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2978 IS_AOP_PREG (IC_RESULT (ic)))
2979 emitcode ("cjne", "%s,#0x00,%05d$",
2980 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2984 emitcode ("cjne", "a,%s,%05d$",
2985 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
2988 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2993 emitcode ("", "%05d$:", tlbl->key + 100);
2998 /* if the sizes are greater than 1 then we cannot */
2999 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3000 AOP_SIZE (IC_LEFT (ic)) > 1)
3003 /* we can if the aops of the left & result match or
3004 if they are in registers and the registers are the
3006 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3011 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3012 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3013 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3019 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3028 /*-----------------------------------------------------------------*/
3029 /* outBitAcc - output a bit in acc */
3030 /*-----------------------------------------------------------------*/
3032 outBitAcc (operand * result)
3034 symbol *tlbl = newiTempLabel (NULL);
3035 /* if the result is a bit */
3036 if (AOP_TYPE (result) == AOP_CRY)
3038 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3042 emitcode ("jz", "%05d$", tlbl->key + 100);
3043 emitcode ("mov", "a,%s", one);
3044 emitcode ("", "%05d$:", tlbl->key + 100);
3049 /*-----------------------------------------------------------------*/
3050 /* genPlusBits - generates code for addition of two bits */
3051 /*-----------------------------------------------------------------*/
3053 genPlusBits (iCode * ic)
3055 D(emitcode ("; genPlusBits",""));
3057 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3059 symbol *lbl = newiTempLabel (NULL);
3060 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3061 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3062 emitcode ("cpl", "c");
3063 emitcode ("", "%05d$:", (lbl->key + 100));
3064 outBitC (IC_RESULT (ic));
3068 emitcode ("clr", "a");
3069 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3070 emitcode ("rlc", "a");
3071 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3072 emitcode ("addc", "a,#0x00");
3073 outAcc (IC_RESULT (ic));
3078 /* This is the original version of this code.
3080 * This is being kept around for reference,
3081 * because I am not entirely sure I got it right...
3084 adjustArithmeticResult (iCode * ic)
3086 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3087 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3088 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3089 aopPut (AOP (IC_RESULT (ic)),
3090 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3092 isOperandVolatile (IC_RESULT (ic), FALSE));
3094 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3095 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3096 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3097 aopPut (AOP (IC_RESULT (ic)),
3098 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3100 isOperandVolatile (IC_RESULT (ic), FALSE));
3102 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3103 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3104 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3105 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3106 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3109 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3110 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3114 /* This is the pure and virtuous version of this code.
3115 * I'm pretty certain it's right, but not enough to toss the old
3119 adjustArithmeticResult (iCode * ic)
3121 if (opIsGptr (IC_RESULT (ic)) &&
3122 opIsGptr (IC_LEFT (ic)) &&
3123 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3125 aopPut (AOP (IC_RESULT (ic)),
3126 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3128 isOperandVolatile (IC_RESULT (ic), FALSE));
3131 if (opIsGptr (IC_RESULT (ic)) &&
3132 opIsGptr (IC_RIGHT (ic)) &&
3133 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3135 aopPut (AOP (IC_RESULT (ic)),
3136 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3138 isOperandVolatile (IC_RESULT (ic), FALSE));
3141 if (opIsGptr (IC_RESULT (ic)) &&
3142 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3143 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3144 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3145 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3148 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3149 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3154 /*-----------------------------------------------------------------*/
3155 /* genPlus - generates code for addition */
3156 /*-----------------------------------------------------------------*/
3158 genPlus (iCode * ic)
3160 int size, offset = 0;
3162 asmop *leftOp, *rightOp;
3164 /* special cases :- */
3166 D(emitcode ("; genPlus",""));
3168 aopOp (IC_LEFT (ic), ic, FALSE);
3169 aopOp (IC_RIGHT (ic), ic, FALSE);
3170 aopOp (IC_RESULT (ic), ic, TRUE);
3172 /* if literal, literal on the right or
3173 if left requires ACC or right is already
3175 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3176 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3177 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3179 operand *t = IC_RIGHT (ic);
3180 IC_RIGHT (ic) = IC_LEFT (ic);
3184 /* if both left & right are in bit
3186 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3187 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3193 /* if left in bit space & right literal */
3194 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3195 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3197 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3198 /* if result in bit space */
3199 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3201 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3202 emitcode ("cpl", "c");
3203 outBitC (IC_RESULT (ic));
3207 size = getDataSize (IC_RESULT (ic));
3210 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3211 emitcode ("addc", "a,#00");
3212 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3218 /* if I can do an increment instead
3219 of add then GOOD for ME */
3220 if (genPlusIncr (ic) == TRUE)
3223 size = getDataSize (IC_RESULT (ic));
3225 leftOp = AOP(IC_LEFT(ic));
3226 rightOp = AOP(IC_RIGHT(ic));
3231 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3233 emitcode("mov", "b,a");
3234 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3235 emitcode("xch", "a,b");
3236 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3237 emitcode (add, "a,b");
3239 else if (aopGetUsesAcc (leftOp, offset))
3241 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3242 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3246 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3247 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3249 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3250 add = "addc"; /* further adds must propagate carry */
3253 adjustArithmeticResult (ic);
3256 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3257 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3258 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3261 /*-----------------------------------------------------------------*/
3262 /* genMinusDec :- does subtraction with deccrement if possible */
3263 /*-----------------------------------------------------------------*/
3265 genMinusDec (iCode * ic)
3267 unsigned int icount;
3268 unsigned int size = getDataSize (IC_RESULT (ic));
3270 /* will try to generate an increment */
3271 /* if the right side is not a literal
3273 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3276 /* if the literal value of the right hand side
3277 is greater than 4 then it is not worth it */
3278 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3281 D(emitcode ("; genMinusDec",""));
3283 /* if decrement >=16 bits in register or direct space */
3284 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3285 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3293 /* If the next instruction is a goto and the goto target
3294 * is <= 10 instructions previous to this, we can generate
3295 * jumps straight to that target.
3297 if (ic->next && ic->next->op == GOTO
3298 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3299 && labelRange <= 10)
3301 emitcode (";", "tail decrement optimized");
3302 tlbl = IC_LABEL (ic->next);
3307 tlbl = newiTempLabel (NULL);
3311 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3312 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3313 IS_AOP_PREG (IC_RESULT (ic)))
3314 emitcode ("cjne", "%s,#0xff,%05d$"
3315 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3319 emitcode ("mov", "a,#0xff");
3320 emitcode ("cjne", "a,%s,%05d$"
3321 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3324 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3327 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3328 IS_AOP_PREG (IC_RESULT (ic)))
3329 emitcode ("cjne", "%s,#0xff,%05d$"
3330 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3334 emitcode ("cjne", "a,%s,%05d$"
3335 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3338 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3342 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3343 IS_AOP_PREG (IC_RESULT (ic)))
3344 emitcode ("cjne", "%s,#0xff,%05d$"
3345 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3349 emitcode ("cjne", "a,%s,%05d$"
3350 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3353 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3357 emitcode ("", "%05d$:", tlbl->key + 100);
3362 /* if the sizes are greater than 1 then we cannot */
3363 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3364 AOP_SIZE (IC_LEFT (ic)) > 1)
3367 /* we can if the aops of the left & result match or
3368 if they are in registers and the registers are the
3370 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3374 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3382 /*-----------------------------------------------------------------*/
3383 /* addSign - complete with sign */
3384 /*-----------------------------------------------------------------*/
3386 addSign (operand * result, int offset, int sign)
3388 int size = (getDataSize (result) - offset);
3393 emitcode ("rlc", "a");
3394 emitcode ("subb", "a,acc");
3396 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3400 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3404 /*-----------------------------------------------------------------*/
3405 /* genMinusBits - generates code for subtraction of two bits */
3406 /*-----------------------------------------------------------------*/
3408 genMinusBits (iCode * ic)
3410 symbol *lbl = newiTempLabel (NULL);
3412 D(emitcode ("; genMinusBits",""));
3414 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3416 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3417 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3418 emitcode ("cpl", "c");
3419 emitcode ("", "%05d$:", (lbl->key + 100));
3420 outBitC (IC_RESULT (ic));
3424 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3425 emitcode ("subb", "a,acc");
3426 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3427 emitcode ("inc", "a");
3428 emitcode ("", "%05d$:", (lbl->key + 100));
3429 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3430 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3434 /*-----------------------------------------------------------------*/
3435 /* genMinus - generates code for subtraction */
3436 /*-----------------------------------------------------------------*/
3438 genMinus (iCode * ic)
3440 int size, offset = 0;
3442 D(emitcode ("; genMinus",""));
3444 aopOp (IC_LEFT (ic), ic, FALSE);
3445 aopOp (IC_RIGHT (ic), ic, FALSE);
3446 aopOp (IC_RESULT (ic), ic, TRUE);
3448 /* special cases :- */
3449 /* if both left & right are in bit space */
3450 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3451 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3457 /* if I can do an decrement instead
3458 of subtract then GOOD for ME */
3459 if (genMinusDec (ic) == TRUE)
3462 size = getDataSize (IC_RESULT (ic));
3464 /* if literal, add a,#-lit, else normal subb */
3465 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3467 unsigned long lit = 0L;
3469 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3474 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3475 /* first add without previous c */
3477 if (!size && lit== (unsigned long) -1) {
3478 emitcode ("dec", "a");
3480 emitcode ("add", "a,#0x%02x",
3481 (unsigned int) (lit & 0x0FFL));
3484 emitcode ("addc", "a,#0x%02x",
3485 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3487 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3492 asmop *leftOp, *rightOp;
3494 leftOp = AOP(IC_LEFT(ic));
3495 rightOp = AOP(IC_RIGHT(ic));
3499 if (aopGetUsesAcc(rightOp, offset)) {
3500 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3501 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3503 emitcode( "setb", "c");
3505 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3506 emitcode("cpl", "a");
3508 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3511 emitcode ("subb", "a,%s",
3512 aopGet(rightOp, offset, FALSE, TRUE));
3515 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3520 adjustArithmeticResult (ic);
3523 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3524 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3525 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3529 /*-----------------------------------------------------------------*/
3530 /* genMultbits :- multiplication of bits */
3531 /*-----------------------------------------------------------------*/
3533 genMultbits (operand * left,
3537 D(emitcode ("; genMultbits",""));
3539 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3540 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3545 /*-----------------------------------------------------------------*/
3546 /* genMultOneByte : 8*8=8/16 bit multiplication */
3547 /*-----------------------------------------------------------------*/
3549 genMultOneByte (operand * left,
3553 sym_link *opetype = operandType (result);
3555 int size=AOP_SIZE(result);
3557 D(emitcode ("; genMultOneByte",""));
3559 if (size<1 || size>2) {
3560 // this should never happen
3561 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3562 AOP_SIZE(result), __FILE__, lineno);
3566 /* (if two literals: the value is computed before) */
3567 /* if one literal, literal on the right */
3568 if (AOP_TYPE (left) == AOP_LIT)
3573 //emitcode (";", "swapped left and right");
3576 if (SPEC_USIGN(opetype)
3577 // ignore the sign of left and right, what else can we do?
3578 || (SPEC_USIGN(operandType(left)) &&
3579 SPEC_USIGN(operandType(right)))) {
3580 // just an unsigned 8*8=8/16 multiply
3581 //emitcode (";","unsigned");
3582 // TODO: check for accumulator clash between left & right aops?
3583 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3584 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3585 emitcode ("mul", "ab");
3586 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3588 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3593 // we have to do a signed multiply
3595 //emitcode (";", "signed");
3596 emitcode ("clr", "F0"); // reset sign flag
3597 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3599 lbl=newiTempLabel(NULL);
3600 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3601 // left side is negative, 8-bit two's complement, this fails for -128
3602 emitcode ("setb", "F0"); // set sign flag
3603 emitcode ("cpl", "a");
3604 emitcode ("inc", "a");
3606 emitcode ("", "%05d$:", lbl->key+100);
3609 if (AOP_TYPE(right)==AOP_LIT) {
3610 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3611 /* AND literal negative */
3613 emitcode ("cpl", "F0"); // complement sign flag
3614 emitcode ("mov", "b,#0x%02x", -val);
3616 emitcode ("mov", "b,#0x%02x", val);
3619 lbl=newiTempLabel(NULL);
3620 emitcode ("mov", "b,a");
3621 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3622 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3623 // right side is negative, 8-bit two's complement
3624 emitcode ("cpl", "F0"); // complement sign flag
3625 emitcode ("cpl", "a");
3626 emitcode ("inc", "a");
3627 emitcode ("", "%05d$:", lbl->key+100);
3629 emitcode ("mul", "ab");
3631 lbl=newiTempLabel(NULL);
3632 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3633 // only ONE op was negative, we have to do a 8/16-bit two's complement
3634 emitcode ("cpl", "a"); // lsb
3636 emitcode ("inc", "a");
3638 emitcode ("add", "a,#1");
3639 emitcode ("xch", "a,b");
3640 emitcode ("cpl", "a"); // msb
3641 emitcode ("addc", "a,#0");
3642 emitcode ("xch", "a,b");
3645 emitcode ("", "%05d$:", lbl->key+100);
3646 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3648 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3652 /*-----------------------------------------------------------------*/
3653 /* genMult - generates code for multiplication */
3654 /*-----------------------------------------------------------------*/
3656 genMult (iCode * ic)
3658 operand *left = IC_LEFT (ic);
3659 operand *right = IC_RIGHT (ic);
3660 operand *result = IC_RESULT (ic);
3662 D(emitcode ("; genMult",""));
3664 /* assign the amsops */
3665 aopOp (left, ic, FALSE);
3666 aopOp (right, ic, FALSE);
3667 aopOp (result, ic, TRUE);
3669 /* special cases first */
3671 if (AOP_TYPE (left) == AOP_CRY &&
3672 AOP_TYPE (right) == AOP_CRY)
3674 genMultbits (left, right, result);
3678 /* if both are of size == 1 */
3679 #if 0 // one of them can be a sloc shared with the result
3680 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3682 if (getSize(operandType(left)) == 1 &&
3683 getSize(operandType(right)) == 1)
3686 genMultOneByte (left, right, result);
3690 /* should have been converted to function call */
3691 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3692 getSize(OP_SYMBOL(right)->type));
3696 freeAsmop (result, NULL, ic, TRUE);
3697 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3698 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3701 /*-----------------------------------------------------------------*/
3702 /* genDivbits :- division of bits */
3703 /*-----------------------------------------------------------------*/
3705 genDivbits (operand * left,
3712 D(emitcode ("; genDivbits",""));
3714 /* the result must be bit */
3715 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3716 l = aopGet (AOP (left), 0, FALSE, FALSE);
3720 emitcode ("div", "ab");
3721 emitcode ("rrc", "a");
3722 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3725 /*-----------------------------------------------------------------*/
3726 /* genDivOneByte : 8 bit division */
3727 /*-----------------------------------------------------------------*/
3729 genDivOneByte (operand * left,
3733 sym_link *opetype = operandType (result);
3738 D(emitcode ("; genDivOneByte",""));
3740 size = AOP_SIZE (result) - 1;
3742 /* signed or unsigned */
3743 if (SPEC_USIGN (opetype))
3745 /* unsigned is easy */
3746 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3747 l = aopGet (AOP (left), 0, FALSE, FALSE);
3749 emitcode ("div", "ab");
3750 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3752 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3756 /* signed is a little bit more difficult */
3758 /* save the signs of the operands */
3759 l = aopGet (AOP (left), 0, FALSE, FALSE);
3761 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3762 emitcode ("push", "acc"); /* save it on the stack */
3764 /* now sign adjust for both left & right */
3765 l = aopGet (AOP (right), 0, FALSE, FALSE);
3767 lbl = newiTempLabel (NULL);
3768 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3769 emitcode ("cpl", "a");
3770 emitcode ("inc", "a");
3771 emitcode ("", "%05d$:", (lbl->key + 100));
3772 emitcode ("mov", "b,a");
3774 /* sign adjust left side */
3775 l = aopGet (AOP (left), 0, FALSE, FALSE);
3778 lbl = newiTempLabel (NULL);
3779 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3780 emitcode ("cpl", "a");
3781 emitcode ("inc", "a");
3782 emitcode ("", "%05d$:", (lbl->key + 100));
3784 /* now the division */
3785 emitcode ("div", "ab");
3786 /* we are interested in the lower order
3788 emitcode ("mov", "b,a");
3789 lbl = newiTempLabel (NULL);
3790 emitcode ("pop", "acc");
3791 /* if there was an over flow we don't
3792 adjust the sign of the result */
3793 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3794 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3796 emitcode ("clr", "a");
3797 emitcode ("subb", "a,b");
3798 emitcode ("mov", "b,a");
3799 emitcode ("", "%05d$:", (lbl->key + 100));
3801 /* now we are done */
3802 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3805 emitcode ("mov", "c,b.7");
3806 emitcode ("subb", "a,acc");
3809 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3813 /*-----------------------------------------------------------------*/
3814 /* genDiv - generates code for division */
3815 /*-----------------------------------------------------------------*/
3819 operand *left = IC_LEFT (ic);
3820 operand *right = IC_RIGHT (ic);
3821 operand *result = IC_RESULT (ic);
3823 D(emitcode ("; genDiv",""));
3825 /* assign the amsops */
3826 aopOp (left, ic, FALSE);
3827 aopOp (right, ic, FALSE);
3828 aopOp (result, ic, TRUE);
3830 /* special cases first */
3832 if (AOP_TYPE (left) == AOP_CRY &&
3833 AOP_TYPE (right) == AOP_CRY)
3835 genDivbits (left, right, result);
3839 /* if both are of size == 1 */
3840 if (AOP_SIZE (left) == 1 &&
3841 AOP_SIZE (right) == 1)
3843 genDivOneByte (left, right, result);
3847 /* should have been converted to function call */
3850 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3851 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3852 freeAsmop (result, NULL, ic, TRUE);
3855 /*-----------------------------------------------------------------*/
3856 /* genModbits :- modulus of bits */
3857 /*-----------------------------------------------------------------*/
3859 genModbits (operand * left,
3866 D(emitcode ("; genModbits",""));
3868 /* the result must be bit */
3869 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3870 l = aopGet (AOP (left), 0, FALSE, FALSE);
3874 emitcode ("div", "ab");
3875 emitcode ("mov", "a,b");
3876 emitcode ("rrc", "a");
3877 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3880 /*-----------------------------------------------------------------*/
3881 /* genModOneByte : 8 bit modulus */
3882 /*-----------------------------------------------------------------*/
3884 genModOneByte (operand * left,
3888 sym_link *opetype = operandType (result);
3892 D(emitcode ("; genModOneByte",""));
3894 /* signed or unsigned */
3895 if (SPEC_USIGN (opetype))
3897 /* unsigned is easy */
3898 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3899 l = aopGet (AOP (left), 0, FALSE, FALSE);
3901 emitcode ("div", "ab");
3902 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3906 /* signed is a little bit more difficult */
3908 /* save the signs of the operands */
3909 l = aopGet (AOP (left), 0, FALSE, FALSE);
3912 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3913 emitcode ("push", "acc"); /* save it on the stack */
3915 /* now sign adjust for both left & right */
3916 l = aopGet (AOP (right), 0, FALSE, FALSE);
3919 lbl = newiTempLabel (NULL);
3920 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3921 emitcode ("cpl", "a");
3922 emitcode ("inc", "a");
3923 emitcode ("", "%05d$:", (lbl->key + 100));
3924 emitcode ("mov", "b,a");
3926 /* sign adjust left side */
3927 l = aopGet (AOP (left), 0, FALSE, FALSE);
3930 lbl = newiTempLabel (NULL);
3931 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3932 emitcode ("cpl", "a");
3933 emitcode ("inc", "a");
3934 emitcode ("", "%05d$:", (lbl->key + 100));
3936 /* now the multiplication */
3937 emitcode ("div", "ab");
3938 /* we are interested in the lower order
3940 lbl = newiTempLabel (NULL);
3941 emitcode ("pop", "acc");
3942 /* if there was an over flow we don't
3943 adjust the sign of the result */
3944 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3945 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3947 emitcode ("clr", "a");
3948 emitcode ("subb", "a,b");
3949 emitcode ("mov", "b,a");
3950 emitcode ("", "%05d$:", (lbl->key + 100));
3952 /* now we are done */
3953 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3957 /*-----------------------------------------------------------------*/
3958 /* genMod - generates code for division */
3959 /*-----------------------------------------------------------------*/
3963 operand *left = IC_LEFT (ic);
3964 operand *right = IC_RIGHT (ic);
3965 operand *result = IC_RESULT (ic);
3967 D(emitcode ("; genMod",""));
3969 /* assign the amsops */
3970 aopOp (left, ic, FALSE);
3971 aopOp (right, ic, FALSE);
3972 aopOp (result, ic, TRUE);
3974 /* special cases first */
3976 if (AOP_TYPE (left) == AOP_CRY &&
3977 AOP_TYPE (right) == AOP_CRY)
3979 genModbits (left, right, result);
3983 /* if both are of size == 1 */
3984 if (AOP_SIZE (left) == 1 &&
3985 AOP_SIZE (right) == 1)
3987 genModOneByte (left, right, result);
3991 /* should have been converted to function call */
3995 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3996 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3997 freeAsmop (result, NULL, ic, TRUE);
4000 /*-----------------------------------------------------------------*/
4001 /* genIfxJump :- will create a jump depending on the ifx */
4002 /*-----------------------------------------------------------------*/
4004 genIfxJump (iCode * ic, char *jval)
4007 symbol *tlbl = newiTempLabel (NULL);
4010 D(emitcode ("; genIfxJump",""));
4012 /* if true label then we jump if condition
4016 jlbl = IC_TRUE (ic);
4017 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4018 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4022 /* false label is present */
4023 jlbl = IC_FALSE (ic);
4024 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4025 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4027 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4028 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4030 emitcode (inst, "%05d$", tlbl->key + 100);
4031 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4032 emitcode ("", "%05d$:", tlbl->key + 100);
4034 /* mark the icode as generated */
4038 /*-----------------------------------------------------------------*/
4039 /* genCmp :- greater or less than comparison */
4040 /*-----------------------------------------------------------------*/
4042 genCmp (operand * left, operand * right,
4043 operand * result, iCode * ifx, int sign, iCode *ic)
4045 int size, offset = 0;
4046 unsigned long lit = 0L;
4049 D(emitcode ("; genCmp",""));
4051 /* if left & right are bit variables */
4052 if (AOP_TYPE (left) == AOP_CRY &&
4053 AOP_TYPE (right) == AOP_CRY)
4055 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4056 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4060 /* subtract right from left if at the
4061 end the carry flag is set then we know that
4062 left is greater than right */
4063 size = max (AOP_SIZE (left), AOP_SIZE (right));
4065 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4066 if ((size == 1) && !sign &&
4067 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4069 symbol *lbl = newiTempLabel (NULL);
4070 emitcode ("cjne", "%s,%s,%05d$",
4071 aopGet (AOP (left), offset, FALSE, FALSE),
4072 aopGet (AOP (right), offset, FALSE, FALSE),
4074 emitcode ("", "%05d$:", lbl->key + 100);
4078 if (AOP_TYPE (right) == AOP_LIT)
4080 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4081 /* optimize if(x < 0) or if(x >= 0) */
4090 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4091 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4093 genIfxJump (ifx, "acc.7");
4097 emitcode ("rlc", "a");
4105 rightInB = aopGetUsesAcc(AOP (right), offset);
4107 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4108 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4109 if (sign && size == 0)
4111 emitcode ("xrl", "a,#0x80");
4112 if (AOP_TYPE (right) == AOP_LIT)
4114 unsigned long lit = (unsigned long)
4115 floatFromVal (AOP (right)->aopu.aop_lit);
4116 emitcode ("subb", "a,#0x%02x",
4117 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4122 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4123 emitcode ("xrl", "b,#0x80");
4124 emitcode ("subb", "a,b");
4130 emitcode ("subb", "a,b");
4132 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4140 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4141 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4142 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4148 /* if the result is used in the next
4149 ifx conditional branch then generate
4150 code a little differently */
4152 genIfxJump (ifx, "c");
4155 /* leave the result in acc */
4159 /*-----------------------------------------------------------------*/
4160 /* genCmpGt :- greater than comparison */
4161 /*-----------------------------------------------------------------*/
4163 genCmpGt (iCode * ic, iCode * ifx)
4165 operand *left, *right, *result;
4166 sym_link *letype, *retype;
4169 D(emitcode ("; genCmpGt",""));
4171 left = IC_LEFT (ic);
4172 right = IC_RIGHT (ic);
4173 result = IC_RESULT (ic);
4175 letype = getSpec (operandType (left));
4176 retype = getSpec (operandType (right));
4177 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4178 /* assign the amsops */
4179 aopOp (left, ic, FALSE);
4180 aopOp (right, ic, FALSE);
4181 aopOp (result, ic, TRUE);
4183 genCmp (right, left, result, ifx, sign,ic);
4185 freeAsmop (result, NULL, ic, TRUE);
4188 /*-----------------------------------------------------------------*/
4189 /* genCmpLt - less than comparisons */
4190 /*-----------------------------------------------------------------*/
4192 genCmpLt (iCode * ic, iCode * ifx)
4194 operand *left, *right, *result;
4195 sym_link *letype, *retype;
4198 D(emitcode ("; genCmpLt",""));
4200 left = IC_LEFT (ic);
4201 right = IC_RIGHT (ic);
4202 result = IC_RESULT (ic);
4204 letype = getSpec (operandType (left));
4205 retype = getSpec (operandType (right));
4206 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4208 /* assign the amsops */
4209 aopOp (left, ic, FALSE);
4210 aopOp (right, ic, FALSE);
4211 aopOp (result, ic, TRUE);
4213 genCmp (left, right, result, ifx, sign,ic);
4215 freeAsmop (result, NULL, ic, TRUE);
4218 /*-----------------------------------------------------------------*/
4219 /* gencjneshort - compare and jump if not equal */
4220 /*-----------------------------------------------------------------*/
4222 gencjneshort (operand * left, operand * right, symbol * lbl)
4224 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4226 unsigned long lit = 0L;
4228 /* if the left side is a literal or
4229 if the right is in a pointer register and left
4231 if ((AOP_TYPE (left) == AOP_LIT) ||
4232 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4238 if (AOP_TYPE (right) == AOP_LIT)
4239 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4241 /* if the right side is a literal then anything goes */
4242 if (AOP_TYPE (right) == AOP_LIT &&
4243 AOP_TYPE (left) != AOP_DIR &&
4244 AOP_TYPE (left) != AOP_IMMD)
4248 emitcode ("cjne", "%s,%s,%05d$",
4249 aopGet (AOP (left), offset, FALSE, FALSE),
4250 aopGet (AOP (right), offset, FALSE, FALSE),
4256 /* if the right side is in a register or in direct space or
4257 if the left is a pointer register & right is not */
4258 else if (AOP_TYPE (right) == AOP_REG ||
4259 AOP_TYPE (right) == AOP_DIR ||
4260 AOP_TYPE (right) == AOP_LIT ||
4261 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4262 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4266 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4267 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4268 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4269 emitcode ("jnz", "%05d$", lbl->key + 100);
4271 emitcode ("cjne", "a,%s,%05d$",
4272 aopGet (AOP (right), offset, FALSE, TRUE),
4279 /* right is a pointer reg need both a & b */
4282 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4283 if (strcmp (l, "b"))
4284 emitcode ("mov", "b,%s", l);
4285 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4286 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4292 /*-----------------------------------------------------------------*/
4293 /* gencjne - compare and jump if not equal */
4294 /*-----------------------------------------------------------------*/
4296 gencjne (operand * left, operand * right, symbol * lbl)
4298 symbol *tlbl = newiTempLabel (NULL);
4300 gencjneshort (left, right, lbl);
4302 emitcode ("mov", "a,%s", one);
4303 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4304 emitcode ("", "%05d$:", lbl->key + 100);
4305 emitcode ("clr", "a");
4306 emitcode ("", "%05d$:", tlbl->key + 100);
4309 /*-----------------------------------------------------------------*/
4310 /* genCmpEq - generates code for equal to */
4311 /*-----------------------------------------------------------------*/
4313 genCmpEq (iCode * ic, iCode * ifx)
4315 operand *left, *right, *result;
4317 D(emitcode ("; genCmpEq",""));
4319 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4320 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4321 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4323 /* if literal, literal on the right or
4324 if the right is in a pointer register and left
4326 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4327 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4329 operand *t = IC_RIGHT (ic);
4330 IC_RIGHT (ic) = IC_LEFT (ic);
4334 if (ifx && !AOP_SIZE (result))
4337 /* if they are both bit variables */
4338 if (AOP_TYPE (left) == AOP_CRY &&
4339 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4341 if (AOP_TYPE (right) == AOP_LIT)
4343 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4346 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4347 emitcode ("cpl", "c");
4351 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4355 emitcode ("clr", "c");
4357 /* AOP_TYPE(right) == AOP_CRY */
4361 symbol *lbl = newiTempLabel (NULL);
4362 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4363 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4364 emitcode ("cpl", "c");
4365 emitcode ("", "%05d$:", (lbl->key + 100));
4367 /* if true label then we jump if condition
4369 tlbl = newiTempLabel (NULL);
4372 emitcode ("jnc", "%05d$", tlbl->key + 100);
4373 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4377 emitcode ("jc", "%05d$", tlbl->key + 100);
4378 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4380 emitcode ("", "%05d$:", tlbl->key + 100);
4384 tlbl = newiTempLabel (NULL);
4385 gencjneshort (left, right, tlbl);
4388 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4389 emitcode ("", "%05d$:", tlbl->key + 100);
4393 symbol *lbl = newiTempLabel (NULL);
4394 emitcode ("sjmp", "%05d$", lbl->key + 100);
4395 emitcode ("", "%05d$:", tlbl->key + 100);
4396 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4397 emitcode ("", "%05d$:", lbl->key + 100);
4400 /* mark the icode as generated */
4405 /* if they are both bit variables */
4406 if (AOP_TYPE (left) == AOP_CRY &&
4407 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4409 if (AOP_TYPE (right) == AOP_LIT)
4411 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4414 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4415 emitcode ("cpl", "c");
4419 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4423 emitcode ("clr", "c");
4425 /* AOP_TYPE(right) == AOP_CRY */
4429 symbol *lbl = newiTempLabel (NULL);
4430 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4431 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4432 emitcode ("cpl", "c");
4433 emitcode ("", "%05d$:", (lbl->key + 100));
4436 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4443 genIfxJump (ifx, "c");
4446 /* if the result is used in an arithmetic operation
4447 then put the result in place */
4452 gencjne (left, right, newiTempLabel (NULL));
4453 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4455 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4460 genIfxJump (ifx, "a");
4463 /* if the result is used in an arithmetic operation
4464 then put the result in place */
4465 if (AOP_TYPE (result) != AOP_CRY)
4467 /* leave the result in acc */
4471 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4472 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4473 freeAsmop (result, NULL, ic, TRUE);
4476 /*-----------------------------------------------------------------*/
4477 /* ifxForOp - returns the icode containing the ifx for operand */
4478 /*-----------------------------------------------------------------*/
4480 ifxForOp (operand * op, iCode * ic)
4482 /* if true symbol then needs to be assigned */
4483 if (IS_TRUE_SYMOP (op))
4486 /* if this has register type condition and
4487 the next instruction is ifx with the same operand
4488 and live to of the operand is upto the ifx only then */
4490 ic->next->op == IFX &&
4491 IC_COND (ic->next)->key == op->key &&
4492 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4498 /*-----------------------------------------------------------------*/
4499 /* hasInc - operand is incremented before any other use */
4500 /*-----------------------------------------------------------------*/
4502 hasInc (operand *op, iCode *ic,int osize)
4504 sym_link *type = operandType(op);
4505 sym_link *retype = getSpec (type);
4506 iCode *lic = ic->next;
4509 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4510 if (!IS_SYMOP(op)) return NULL;
4512 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4513 if (IS_AGGREGATE(type->next)) return NULL;
4514 if (osize != (isize = getSize(type->next))) return NULL;
4517 /* if operand of the form op = op + <sizeof *op> */
4518 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4519 isOperandEqual(IC_RESULT(lic),op) &&
4520 isOperandLiteral(IC_RIGHT(lic)) &&
4521 operandLitValue(IC_RIGHT(lic)) == isize) {
4524 /* if the operand used or deffed */
4525 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4528 /* if GOTO or IFX */
4529 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4535 /*-----------------------------------------------------------------*/
4536 /* genAndOp - for && operation */
4537 /*-----------------------------------------------------------------*/
4539 genAndOp (iCode * ic)
4541 operand *left, *right, *result;
4544 D(emitcode ("; genAndOp",""));
4546 /* note here that && operations that are in an
4547 if statement are taken away by backPatchLabels
4548 only those used in arthmetic operations remain */
4549 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4550 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4551 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4553 /* if both are bit variables */
4554 if (AOP_TYPE (left) == AOP_CRY &&
4555 AOP_TYPE (right) == AOP_CRY)
4557 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4558 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4563 tlbl = newiTempLabel (NULL);
4565 emitcode ("jz", "%05d$", tlbl->key + 100);
4567 emitcode ("", "%05d$:", tlbl->key + 100);
4571 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4572 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4573 freeAsmop (result, NULL, ic, TRUE);
4577 /*-----------------------------------------------------------------*/
4578 /* genOrOp - for || operation */
4579 /*-----------------------------------------------------------------*/
4581 genOrOp (iCode * ic)
4583 operand *left, *right, *result;
4586 D(emitcode ("; genOrOp",""));
4588 /* note here that || operations that are in an
4589 if statement are taken away by backPatchLabels
4590 only those used in arthmetic operations remain */
4591 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4592 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4593 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4595 /* if both are bit variables */
4596 if (AOP_TYPE (left) == AOP_CRY &&
4597 AOP_TYPE (right) == AOP_CRY)
4599 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4600 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4605 tlbl = newiTempLabel (NULL);
4607 emitcode ("jnz", "%05d$", tlbl->key + 100);
4609 emitcode ("", "%05d$:", tlbl->key + 100);
4613 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4614 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4615 freeAsmop (result, NULL, ic, TRUE);
4618 /*-----------------------------------------------------------------*/
4619 /* isLiteralBit - test if lit == 2^n */
4620 /*-----------------------------------------------------------------*/
4622 isLiteralBit (unsigned long lit)
4624 unsigned long pw[32] =
4625 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4626 0x100L, 0x200L, 0x400L, 0x800L,
4627 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4628 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4629 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4630 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4631 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4634 for (idx = 0; idx < 32; idx++)
4640 /*-----------------------------------------------------------------*/
4641 /* continueIfTrue - */
4642 /*-----------------------------------------------------------------*/
4644 continueIfTrue (iCode * ic)
4647 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4651 /*-----------------------------------------------------------------*/
4653 /*-----------------------------------------------------------------*/
4655 jumpIfTrue (iCode * ic)
4658 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4662 /*-----------------------------------------------------------------*/
4663 /* jmpTrueOrFalse - */
4664 /*-----------------------------------------------------------------*/
4666 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4668 // ugly but optimized by peephole
4671 symbol *nlbl = newiTempLabel (NULL);
4672 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4673 emitcode ("", "%05d$:", tlbl->key + 100);
4674 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4675 emitcode ("", "%05d$:", nlbl->key + 100);
4679 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4680 emitcode ("", "%05d$:", tlbl->key + 100);
4685 /*-----------------------------------------------------------------*/
4686 /* genAnd - code for and */
4687 /*-----------------------------------------------------------------*/
4689 genAnd (iCode * ic, iCode * ifx)
4691 operand *left, *right, *result;
4692 int size, offset = 0;
4693 unsigned long lit = 0L;
4697 D(emitcode ("; genAnd",""));
4699 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4700 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4701 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4704 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4706 AOP_TYPE (left), AOP_TYPE (right));
4707 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4709 AOP_SIZE (left), AOP_SIZE (right));
4712 /* if left is a literal & right is not then exchange them */
4713 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4714 AOP_NEEDSACC (left))
4716 operand *tmp = right;
4721 /* if result = right then exchange them */
4722 if (sameRegs (AOP (result), AOP (right)))
4724 operand *tmp = right;
4729 /* if right is bit then exchange them */
4730 if (AOP_TYPE (right) == AOP_CRY &&
4731 AOP_TYPE (left) != AOP_CRY)
4733 operand *tmp = right;
4737 if (AOP_TYPE (right) == AOP_LIT)
4738 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4740 size = AOP_SIZE (result);
4743 // result = bit & yy;
4744 if (AOP_TYPE (left) == AOP_CRY)
4746 // c = bit & literal;
4747 if (AOP_TYPE (right) == AOP_LIT)
4751 if (size && sameRegs (AOP (result), AOP (left)))
4754 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4759 if (size && (AOP_TYPE (result) == AOP_CRY))
4761 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4764 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4769 emitcode ("clr", "c");
4774 if (AOP_TYPE (right) == AOP_CRY)
4777 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4778 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4783 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4785 emitcode ("rrc", "a");
4786 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4794 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4795 genIfxJump (ifx, "c");
4799 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4800 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4801 if ((AOP_TYPE (right) == AOP_LIT) &&
4802 (AOP_TYPE (result) == AOP_CRY) &&
4803 (AOP_TYPE (left) != AOP_CRY))
4805 int posbit = isLiteralBit (lit);
4810 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4813 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4819 sprintf (buffer, "acc.%d", posbit & 0x07);
4820 genIfxJump (ifx, buffer);
4827 symbol *tlbl = newiTempLabel (NULL);
4828 int sizel = AOP_SIZE (left);
4830 emitcode ("setb", "c");
4833 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4835 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4837 if ((posbit = isLiteralBit (bytelit)) != 0)
4838 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4841 if (bytelit != 0x0FFL)
4842 emitcode ("anl", "a,%s",
4843 aopGet (AOP (right), offset, FALSE, TRUE));
4844 emitcode ("jnz", "%05d$", tlbl->key + 100);
4849 // bit = left & literal
4852 emitcode ("clr", "c");
4853 emitcode ("", "%05d$:", tlbl->key + 100);
4855 // if(left & literal)
4859 jmpTrueOrFalse (ifx, tlbl);
4867 /* if left is same as result */
4868 if (sameRegs (AOP (result), AOP (left)))
4870 for (; size--; offset++)
4872 if (AOP_TYPE (right) == AOP_LIT)
4874 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4876 else if (bytelit == 0)
4878 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4880 else if (IS_AOP_PREG (result))
4882 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4883 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4884 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4887 emitcode ("anl", "%s,%s",
4888 aopGet (AOP (left), offset, FALSE, TRUE),
4889 aopGet (AOP (right), offset, FALSE, FALSE));
4893 if (AOP_TYPE (left) == AOP_ACC)
4894 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4897 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4898 if (IS_AOP_PREG (result))
4900 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4901 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4905 emitcode ("anl", "%s,a",
4906 aopGet (AOP (left), offset, FALSE, TRUE));
4913 // left & result in different registers
4914 if (AOP_TYPE (result) == AOP_CRY)
4917 // if(size), result in bit
4918 // if(!size && ifx), conditional oper: if(left & right)
4919 symbol *tlbl = newiTempLabel (NULL);
4920 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4922 emitcode ("setb", "c");
4925 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4926 emitcode ("anl", "a,%s",
4927 aopGet (AOP (right), offset, FALSE, FALSE));
4929 if (AOP_TYPE(left)==AOP_ACC) {
4930 emitcode("mov", "b,a");
4931 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4932 emitcode("anl", "a,b");
4934 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4935 emitcode ("anl", "a,%s",
4936 aopGet (AOP (left), offset, FALSE, FALSE));
4939 emitcode ("jnz", "%05d$", tlbl->key + 100);
4945 emitcode ("", "%05d$:", tlbl->key + 100);
4949 jmpTrueOrFalse (ifx, tlbl);
4953 for (; (size--); offset++)
4956 // result = left & right
4957 if (AOP_TYPE (right) == AOP_LIT)
4959 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4961 aopPut (AOP (result),
4962 aopGet (AOP (left), offset, FALSE, FALSE),
4964 isOperandVolatile (result, FALSE));
4967 else if (bytelit == 0)
4969 /* dummy read of volatile operand */
4970 if (isOperandVolatile (left, FALSE))
4971 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4972 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4976 // faster than result <- left, anl result,right
4977 // and better if result is SFR
4978 if (AOP_TYPE (left) == AOP_ACC)
4979 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4982 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4983 emitcode ("anl", "a,%s",
4984 aopGet (AOP (left), offset, FALSE, FALSE));
4986 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4992 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4993 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4994 freeAsmop (result, NULL, ic, TRUE);
4997 /*-----------------------------------------------------------------*/
4998 /* genOr - code for or */
4999 /*-----------------------------------------------------------------*/
5001 genOr (iCode * ic, iCode * ifx)
5003 operand *left, *right, *result;
5004 int size, offset = 0;
5005 unsigned long lit = 0L;
5007 D(emitcode ("; genOr",""));
5009 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5010 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5011 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5014 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5016 AOP_TYPE (left), AOP_TYPE (right));
5017 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5019 AOP_SIZE (left), AOP_SIZE (right));
5022 /* if left is a literal & right is not then exchange them */
5023 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5024 AOP_NEEDSACC (left))
5026 operand *tmp = right;
5031 /* if result = right then exchange them */
5032 if (sameRegs (AOP (result), AOP (right)))
5034 operand *tmp = right;
5039 /* if right is bit then exchange them */
5040 if (AOP_TYPE (right) == AOP_CRY &&
5041 AOP_TYPE (left) != AOP_CRY)
5043 operand *tmp = right;
5047 if (AOP_TYPE (right) == AOP_LIT)
5048 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5050 size = AOP_SIZE (result);
5054 if (AOP_TYPE (left) == AOP_CRY)
5056 if (AOP_TYPE (right) == AOP_LIT)
5058 // c = bit | literal;
5061 // lit != 0 => result = 1
5062 if (AOP_TYPE (result) == AOP_CRY)
5065 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5067 continueIfTrue (ifx);
5070 emitcode ("setb", "c");
5074 // lit == 0 => result = left
5075 if (size && sameRegs (AOP (result), AOP (left)))
5077 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5082 if (AOP_TYPE (right) == AOP_CRY)
5085 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5086 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5091 symbol *tlbl = newiTempLabel (NULL);
5092 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5093 emitcode ("setb", "c");
5094 emitcode ("jb", "%s,%05d$",
5095 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5097 emitcode ("jnz", "%05d$", tlbl->key + 100);
5098 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5100 jmpTrueOrFalse (ifx, tlbl);
5106 emitcode ("", "%05d$:", tlbl->key + 100);
5115 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5116 genIfxJump (ifx, "c");
5120 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5121 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5122 if ((AOP_TYPE (right) == AOP_LIT) &&
5123 (AOP_TYPE (result) == AOP_CRY) &&
5124 (AOP_TYPE (left) != AOP_CRY))
5130 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5132 continueIfTrue (ifx);
5137 // lit = 0, result = boolean(left)
5139 emitcode ("setb", "c");
5143 symbol *tlbl = newiTempLabel (NULL);
5144 emitcode ("jnz", "%05d$", tlbl->key + 100);
5146 emitcode ("", "%05d$:", tlbl->key + 100);
5150 genIfxJump (ifx, "a");
5158 /* if left is same as result */
5159 if (sameRegs (AOP (result), AOP (left)))
5161 for (; size--; offset++)
5163 if (AOP_TYPE (right) == AOP_LIT)
5165 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5167 /* dummy read of volatile operand */
5168 if (isOperandVolatile (left, FALSE))
5169 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5173 else if (IS_AOP_PREG (left))
5175 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5176 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5177 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5180 emitcode ("orl", "%s,%s",
5181 aopGet (AOP (left), offset, FALSE, TRUE),
5182 aopGet (AOP (right), offset, FALSE, FALSE));
5186 if (AOP_TYPE (left) == AOP_ACC)
5187 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5190 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5191 if (IS_AOP_PREG (left))
5193 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5194 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5197 emitcode ("orl", "%s,a",
5198 aopGet (AOP (left), offset, FALSE, TRUE));
5205 // left & result in different registers
5206 if (AOP_TYPE (result) == AOP_CRY)
5209 // if(size), result in bit
5210 // if(!size && ifx), conditional oper: if(left | right)
5211 symbol *tlbl = newiTempLabel (NULL);
5212 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5214 emitcode ("setb", "c");
5217 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5218 emitcode ("orl", "a,%s",
5219 aopGet (AOP (right), offset, FALSE, FALSE));
5221 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5222 emitcode ("orl", "a,%s",
5223 aopGet (AOP (left), offset, FALSE, FALSE));
5225 emitcode ("jnz", "%05d$", tlbl->key + 100);
5231 emitcode ("", "%05d$:", tlbl->key + 100);
5235 jmpTrueOrFalse (ifx, tlbl);
5238 for (; (size--); offset++)
5241 // result = left & right
5242 if (AOP_TYPE (right) == AOP_LIT)
5244 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5246 aopPut (AOP (result),
5247 aopGet (AOP (left), offset, FALSE, FALSE),
5249 isOperandVolatile (result, FALSE));
5253 // faster than result <- left, anl result,right
5254 // and better if result is SFR
5255 if (AOP_TYPE (left) == AOP_ACC)
5256 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5259 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5260 emitcode ("orl", "a,%s",
5261 aopGet (AOP (left), offset, FALSE, FALSE));
5263 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5268 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5269 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5270 freeAsmop (result, NULL, ic, TRUE);
5273 /*-----------------------------------------------------------------*/
5274 /* genXor - code for xclusive or */
5275 /*-----------------------------------------------------------------*/
5277 genXor (iCode * ic, iCode * ifx)
5279 operand *left, *right, *result;
5280 int size, offset = 0;
5281 unsigned long lit = 0L;
5283 D(emitcode ("; genXor",""));
5285 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5286 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5287 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5290 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5292 AOP_TYPE (left), AOP_TYPE (right));
5293 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5295 AOP_SIZE (left), AOP_SIZE (right));
5298 /* if left is a literal & right is not ||
5299 if left needs acc & right does not */
5300 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5301 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5303 operand *tmp = right;
5308 /* if result = right then exchange them */
5309 if (sameRegs (AOP (result), AOP (right)))
5311 operand *tmp = right;
5316 /* if right is bit then exchange them */
5317 if (AOP_TYPE (right) == AOP_CRY &&
5318 AOP_TYPE (left) != AOP_CRY)
5320 operand *tmp = right;
5324 if (AOP_TYPE (right) == AOP_LIT)
5325 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5327 size = AOP_SIZE (result);
5331 if (AOP_TYPE (left) == AOP_CRY)
5333 if (AOP_TYPE (right) == AOP_LIT)
5335 // c = bit & literal;
5338 // lit>>1 != 0 => result = 1
5339 if (AOP_TYPE (result) == AOP_CRY)
5342 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5344 continueIfTrue (ifx);
5347 emitcode ("setb", "c");
5354 // lit == 0, result = left
5355 if (size && sameRegs (AOP (result), AOP (left)))
5357 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5361 // lit == 1, result = not(left)
5362 if (size && sameRegs (AOP (result), AOP (left)))
5364 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5369 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5370 emitcode ("cpl", "c");
5379 symbol *tlbl = newiTempLabel (NULL);
5380 if (AOP_TYPE (right) == AOP_CRY)
5383 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5387 int sizer = AOP_SIZE (right);
5389 // if val>>1 != 0, result = 1
5390 emitcode ("setb", "c");
5393 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5395 // test the msb of the lsb
5396 emitcode ("anl", "a,#0xfe");
5397 emitcode ("jnz", "%05d$", tlbl->key + 100);
5401 emitcode ("rrc", "a");
5403 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5404 emitcode ("cpl", "c");
5405 emitcode ("", "%05d$:", (tlbl->key + 100));
5412 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5413 genIfxJump (ifx, "c");
5417 if (sameRegs (AOP (result), AOP (left)))
5419 /* if left is same as result */
5420 for (; size--; offset++)
5422 if (AOP_TYPE (right) == AOP_LIT)
5424 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5426 else if (IS_AOP_PREG (left))
5428 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5429 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5430 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5433 emitcode ("xrl", "%s,%s",
5434 aopGet (AOP (left), offset, FALSE, TRUE),
5435 aopGet (AOP (right), offset, FALSE, FALSE));
5439 if (AOP_TYPE (left) == AOP_ACC)
5440 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5443 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5444 if (IS_AOP_PREG (left))
5446 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5447 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5450 emitcode ("xrl", "%s,a",
5451 aopGet (AOP (left), offset, FALSE, TRUE));
5458 // left & result in different registers
5459 if (AOP_TYPE (result) == AOP_CRY)
5462 // if(size), result in bit
5463 // if(!size && ifx), conditional oper: if(left ^ right)
5464 symbol *tlbl = newiTempLabel (NULL);
5465 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5467 emitcode ("setb", "c");
5470 if ((AOP_TYPE (right) == AOP_LIT) &&
5471 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5473 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5477 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5478 emitcode ("xrl", "a,%s",
5479 aopGet (AOP (right), offset, FALSE, FALSE));
5481 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5482 emitcode ("xrl", "a,%s",
5483 aopGet (AOP (left), offset, FALSE, FALSE));
5486 emitcode ("jnz", "%05d$", tlbl->key + 100);
5492 emitcode ("", "%05d$:", tlbl->key + 100);
5496 jmpTrueOrFalse (ifx, tlbl);
5499 for (; (size--); offset++)
5502 // result = left & right
5503 if (AOP_TYPE (right) == AOP_LIT)
5505 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5507 aopPut (AOP (result),
5508 aopGet (AOP (left), offset, FALSE, FALSE),
5510 isOperandVolatile (result, FALSE));
5514 // faster than result <- left, anl result,right
5515 // and better if result is SFR
5516 if (AOP_TYPE (left) == AOP_ACC)
5517 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5520 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5521 emitcode ("xrl", "a,%s",
5522 aopGet (AOP (left), offset, FALSE, TRUE));
5524 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5529 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5530 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5531 freeAsmop (result, NULL, ic, TRUE);
5534 /*-----------------------------------------------------------------*/
5535 /* genInline - write the inline code out */
5536 /*-----------------------------------------------------------------*/
5538 genInline (iCode * ic)
5540 char *buffer, *bp, *bp1;
5542 D(emitcode ("; genInline",""));
5544 _G.inLine += (!options.asmpeep);
5546 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5547 strcpy (buffer, IC_INLINE (ic));
5549 /* emit each line as a code */
5574 /* emitcode("",buffer); */
5575 _G.inLine -= (!options.asmpeep);
5578 /*-----------------------------------------------------------------*/
5579 /* genRRC - rotate right with carry */
5580 /*-----------------------------------------------------------------*/
5584 operand *left, *result;
5585 int size, offset = 0;
5588 D(emitcode ("; genRRC",""));
5590 /* rotate right with carry */
5591 left = IC_LEFT (ic);
5592 result = IC_RESULT (ic);
5593 aopOp (left, ic, FALSE);
5594 aopOp (result, ic, FALSE);
5596 /* move it to the result */
5597 size = AOP_SIZE (result);
5599 if (size == 1) { /* special case for 1 byte */
5600 l = aopGet (AOP (left), offset, FALSE, FALSE);
5602 emitcode ("rr", "a");
5608 l = aopGet (AOP (left), offset, FALSE, FALSE);
5610 emitcode ("rrc", "a");
5611 if (AOP_SIZE (result) > 1)
5612 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5614 /* now we need to put the carry into the
5615 highest order byte of the result */
5616 if (AOP_SIZE (result) > 1)
5618 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5621 emitcode ("mov", "acc.7,c");
5623 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5624 freeAsmop (left, NULL, ic, TRUE);
5625 freeAsmop (result, NULL, ic, TRUE);
5628 /*-----------------------------------------------------------------*/
5629 /* genRLC - generate code for rotate left with carry */
5630 /*-----------------------------------------------------------------*/
5634 operand *left, *result;
5635 int size, offset = 0;
5638 D(emitcode ("; genRLC",""));
5640 /* rotate right with carry */
5641 left = IC_LEFT (ic);
5642 result = IC_RESULT (ic);
5643 aopOp (left, ic, FALSE);
5644 aopOp (result, ic, FALSE);
5646 /* move it to the result */
5647 size = AOP_SIZE (result);
5651 l = aopGet (AOP (left), offset, FALSE, FALSE);
5653 if (size == 0) { /* special case for 1 byte */
5657 emitcode ("add", "a,acc");
5658 if (AOP_SIZE (result) > 1)
5659 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5662 l = aopGet (AOP (left), offset, FALSE, FALSE);
5664 emitcode ("rlc", "a");
5665 if (AOP_SIZE (result) > 1)
5666 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5669 /* now we need to put the carry into the
5670 highest order byte of the result */
5671 if (AOP_SIZE (result) > 1)
5673 l = aopGet (AOP (result), 0, FALSE, FALSE);
5676 emitcode ("mov", "acc.0,c");
5678 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5679 freeAsmop (left, NULL, ic, TRUE);
5680 freeAsmop (result, NULL, ic, TRUE);
5683 /*-----------------------------------------------------------------*/
5684 /* genGetHbit - generates code get highest order bit */
5685 /*-----------------------------------------------------------------*/
5687 genGetHbit (iCode * ic)
5689 operand *left, *result;
5691 D(emitcode ("; genGetHbit",""));
5693 left = IC_LEFT (ic);
5694 result = IC_RESULT (ic);
5695 aopOp (left, ic, FALSE);
5696 aopOp (result, ic, FALSE);
5698 /* get the highest order byte into a */
5699 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5700 if (AOP_TYPE (result) == AOP_CRY)
5702 emitcode ("rlc", "a");
5707 emitcode ("rl", "a");
5708 emitcode ("anl", "a,#0x01");
5713 freeAsmop (left, NULL, ic, TRUE);
5714 freeAsmop (result, NULL, ic, TRUE);
5717 /*-----------------------------------------------------------------*/
5718 /* AccRol - rotate left accumulator by known count */
5719 /*-----------------------------------------------------------------*/
5721 AccRol (int shCount)
5723 shCount &= 0x0007; // shCount : 0..7
5730 emitcode ("rl", "a");
5733 emitcode ("rl", "a");
5734 emitcode ("rl", "a");
5737 emitcode ("swap", "a");
5738 emitcode ("rr", "a");
5741 emitcode ("swap", "a");
5744 emitcode ("swap", "a");
5745 emitcode ("rl", "a");
5748 emitcode ("rr", "a");
5749 emitcode ("rr", "a");
5752 emitcode ("rr", "a");
5757 /*-----------------------------------------------------------------*/
5758 /* AccLsh - left shift accumulator by known count */
5759 /*-----------------------------------------------------------------*/
5761 AccLsh (int shCount)
5766 emitcode ("add", "a,acc");
5767 else if (shCount == 2)
5769 emitcode ("add", "a,acc");
5770 emitcode ("add", "a,acc");
5774 /* rotate left accumulator */
5776 /* and kill the lower order bits */
5777 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5782 /*-----------------------------------------------------------------*/
5783 /* AccRsh - right shift accumulator by known count */
5784 /*-----------------------------------------------------------------*/
5786 AccRsh (int shCount)
5793 emitcode ("rrc", "a");
5797 /* rotate right accumulator */
5798 AccRol (8 - shCount);
5799 /* and kill the higher order bits */
5800 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5805 /*-----------------------------------------------------------------*/
5806 /* AccSRsh - signed right shift accumulator by known count */
5807 /*-----------------------------------------------------------------*/
5809 AccSRsh (int shCount)
5816 emitcode ("mov", "c,acc.7");
5817 emitcode ("rrc", "a");
5819 else if (shCount == 2)
5821 emitcode ("mov", "c,acc.7");
5822 emitcode ("rrc", "a");
5823 emitcode ("mov", "c,acc.7");
5824 emitcode ("rrc", "a");
5828 tlbl = newiTempLabel (NULL);
5829 /* rotate right accumulator */
5830 AccRol (8 - shCount);
5831 /* and kill the higher order bits */
5832 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5833 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5834 emitcode ("orl", "a,#0x%02x",
5835 (unsigned char) ~SRMask[shCount]);
5836 emitcode ("", "%05d$:", tlbl->key + 100);
5841 /*-----------------------------------------------------------------*/
5842 /* shiftR1Left2Result - shift right one byte from left to result */
5843 /*-----------------------------------------------------------------*/
5845 shiftR1Left2Result (operand * left, int offl,
5846 operand * result, int offr,
5847 int shCount, int sign)
5849 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5850 /* shift right accumulator */
5855 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5858 /*-----------------------------------------------------------------*/
5859 /* shiftL1Left2Result - shift left one byte from left to result */
5860 /*-----------------------------------------------------------------*/
5862 shiftL1Left2Result (operand * left, int offl,
5863 operand * result, int offr, int shCount)
5866 l = aopGet (AOP (left), offl, FALSE, FALSE);
5868 /* shift left accumulator */
5870 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5873 /*-----------------------------------------------------------------*/
5874 /* movLeft2Result - move byte from left to result */
5875 /*-----------------------------------------------------------------*/
5877 movLeft2Result (operand * left, int offl,
5878 operand * result, int offr, int sign)
5881 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5883 l = aopGet (AOP (left), offl, FALSE, FALSE);
5885 if (*l == '@' && (IS_AOP_PREG (result)))
5887 emitcode ("mov", "a,%s", l);
5888 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5893 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
5896 /* MSB sign in acc.7 ! */
5897 if (getDataSize (left) == offl + 1)
5899 emitcode ("mov", "a,%s", l);
5900 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5907 /*-----------------------------------------------------------------*/
5908 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5909 /*-----------------------------------------------------------------*/
5913 emitcode ("rrc", "a");
5914 emitcode ("xch", "a,%s", x);
5915 emitcode ("rrc", "a");
5916 emitcode ("xch", "a,%s", x);
5919 /*-----------------------------------------------------------------*/
5920 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5921 /*-----------------------------------------------------------------*/
5925 emitcode ("xch", "a,%s", x);
5926 emitcode ("rlc", "a");
5927 emitcode ("xch", "a,%s", x);
5928 emitcode ("rlc", "a");
5931 /*-----------------------------------------------------------------*/
5932 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5933 /*-----------------------------------------------------------------*/
5937 emitcode ("xch", "a,%s", x);
5938 emitcode ("add", "a,acc");
5939 emitcode ("xch", "a,%s", x);
5940 emitcode ("rlc", "a");
5943 /*-----------------------------------------------------------------*/
5944 /* AccAXLsh - left shift a:x by known count (0..7) */
5945 /*-----------------------------------------------------------------*/
5947 AccAXLsh (char *x, int shCount)
5962 case 5: // AAAAABBB:CCCCCDDD
5964 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5966 emitcode ("anl", "a,#0x%02x",
5967 SLMask[shCount]); // BBB00000:CCCCCDDD
5969 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5971 AccRol (shCount); // DDDCCCCC:BBB00000
5973 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5975 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5977 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5979 emitcode ("anl", "a,#0x%02x",
5980 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5982 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5984 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5987 case 6: // AAAAAABB:CCCCCCDD
5988 emitcode ("anl", "a,#0x%02x",
5989 SRMask[shCount]); // 000000BB:CCCCCCDD
5990 emitcode ("mov", "c,acc.0"); // c = B
5991 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5993 AccAXRrl1 (x); // BCCCCCCD:D000000B
5994 AccAXRrl1 (x); // BBCCCCCC:DD000000
5996 emitcode("rrc","a");
5997 emitcode("xch","a,%s", x);
5998 emitcode("rrc","a");
5999 emitcode("mov","c,acc.0"); //<< get correct bit
6000 emitcode("xch","a,%s", x);
6002 emitcode("rrc","a");
6003 emitcode("xch","a,%s", x);
6004 emitcode("rrc","a");
6005 emitcode("xch","a,%s", x);
6008 case 7: // a:x <<= 7
6010 emitcode ("anl", "a,#0x%02x",
6011 SRMask[shCount]); // 0000000B:CCCCCCCD
6013 emitcode ("mov", "c,acc.0"); // c = B
6015 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6017 AccAXRrl1 (x); // BCCCCCCC:D0000000
6025 /*-----------------------------------------------------------------*/
6026 /* AccAXRsh - right shift a:x known count (0..7) */
6027 /*-----------------------------------------------------------------*/
6029 AccAXRsh (char *x, int shCount)
6037 AccAXRrl1 (x); // 0->a:x
6042 AccAXRrl1 (x); // 0->a:x
6045 AccAXRrl1 (x); // 0->a:x
6050 case 5: // AAAAABBB:CCCCCDDD = a:x
6052 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6054 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6056 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6058 emitcode ("anl", "a,#0x%02x",
6059 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6061 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6063 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6065 emitcode ("anl", "a,#0x%02x",
6066 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6068 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6070 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6072 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6075 case 6: // AABBBBBB:CCDDDDDD
6077 emitcode ("mov", "c,acc.7");
6078 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6080 emitcode ("mov", "c,acc.7");
6081 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6083 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6085 emitcode ("anl", "a,#0x%02x",
6086 SRMask[shCount]); // 000000AA:BBBBBBCC
6089 case 7: // ABBBBBBB:CDDDDDDD
6091 emitcode ("mov", "c,acc.7"); // c = A
6093 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6095 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6097 emitcode ("anl", "a,#0x%02x",
6098 SRMask[shCount]); // 0000000A:BBBBBBBC
6106 /*-----------------------------------------------------------------*/
6107 /* AccAXRshS - right shift signed a:x known count (0..7) */
6108 /*-----------------------------------------------------------------*/
6110 AccAXRshS (char *x, int shCount)
6118 emitcode ("mov", "c,acc.7");
6119 AccAXRrl1 (x); // s->a:x
6123 emitcode ("mov", "c,acc.7");
6124 AccAXRrl1 (x); // s->a:x
6126 emitcode ("mov", "c,acc.7");
6127 AccAXRrl1 (x); // s->a:x
6132 case 5: // AAAAABBB:CCCCCDDD = a:x
6134 tlbl = newiTempLabel (NULL);
6135 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6137 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6139 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6141 emitcode ("anl", "a,#0x%02x",
6142 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6144 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6146 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6148 emitcode ("anl", "a,#0x%02x",
6149 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6151 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6153 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6155 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6157 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6158 emitcode ("orl", "a,#0x%02x",
6159 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6161 emitcode ("", "%05d$:", tlbl->key + 100);
6162 break; // SSSSAAAA:BBBCCCCC
6164 case 6: // AABBBBBB:CCDDDDDD
6166 tlbl = newiTempLabel (NULL);
6167 emitcode ("mov", "c,acc.7");
6168 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6170 emitcode ("mov", "c,acc.7");
6171 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6173 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6175 emitcode ("anl", "a,#0x%02x",
6176 SRMask[shCount]); // 000000AA:BBBBBBCC
6178 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6179 emitcode ("orl", "a,#0x%02x",
6180 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6182 emitcode ("", "%05d$:", tlbl->key + 100);
6184 case 7: // ABBBBBBB:CDDDDDDD
6186 tlbl = newiTempLabel (NULL);
6187 emitcode ("mov", "c,acc.7"); // c = A
6189 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6191 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6193 emitcode ("anl", "a,#0x%02x",
6194 SRMask[shCount]); // 0000000A:BBBBBBBC
6196 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6197 emitcode ("orl", "a,#0x%02x",
6198 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6200 emitcode ("", "%05d$:", tlbl->key + 100);
6207 /*-----------------------------------------------------------------*/
6208 /* shiftL2Left2Result - shift left two bytes from left to result */
6209 /*-----------------------------------------------------------------*/
6211 shiftL2Left2Result (operand * left, int offl,
6212 operand * result, int offr, int shCount)
6214 if (sameRegs (AOP (result), AOP (left)) &&
6215 ((offl + MSB16) == offr))
6217 /* don't crash result[offr] */
6218 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6219 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6223 movLeft2Result (left, offl, result, offr, 0);
6224 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6226 /* ax << shCount (x = lsb(result)) */
6227 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6228 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6232 /*-----------------------------------------------------------------*/
6233 /* shiftR2Left2Result - shift right two bytes from left to result */
6234 /*-----------------------------------------------------------------*/
6236 shiftR2Left2Result (operand * left, int offl,
6237 operand * result, int offr,
6238 int shCount, int sign)
6240 if (sameRegs (AOP (result), AOP (left)) &&
6241 ((offl + MSB16) == offr))
6243 /* don't crash result[offr] */
6244 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6245 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6249 movLeft2Result (left, offl, result, offr, 0);
6250 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6252 /* a:x >> shCount (x = lsb(result)) */
6254 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6256 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6257 if (getDataSize (result) > 1)
6258 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6261 /*-----------------------------------------------------------------*/
6262 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6263 /*-----------------------------------------------------------------*/
6265 shiftLLeftOrResult (operand * left, int offl,
6266 operand * result, int offr, int shCount)
6268 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6269 /* shift left accumulator */
6271 /* or with result */
6272 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6273 /* back to result */
6274 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6277 /*-----------------------------------------------------------------*/
6278 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6279 /*-----------------------------------------------------------------*/
6281 shiftRLeftOrResult (operand * left, int offl,
6282 operand * result, int offr, int shCount)
6284 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6285 /* shift right 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 /* genlshOne - left shift a one byte quantity by known count */
6295 /*-----------------------------------------------------------------*/
6297 genlshOne (operand * result, operand * left, int shCount)
6299 D(emitcode ("; genlshOne",""));
6301 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6304 /*-----------------------------------------------------------------*/
6305 /* genlshTwo - left shift two bytes by known amount != 0 */
6306 /*-----------------------------------------------------------------*/
6308 genlshTwo (operand * result, operand * left, int shCount)
6312 D(emitcode ("; genlshTwo",""));
6314 size = getDataSize (result);
6316 /* if shCount >= 8 */
6324 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6326 movLeft2Result (left, LSB, result, MSB16, 0);
6328 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6331 /* 1 <= shCount <= 7 */
6335 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6337 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6341 /*-----------------------------------------------------------------*/
6342 /* shiftLLong - shift left one long from left to result */
6343 /* offl = LSB or MSB16 */
6344 /*-----------------------------------------------------------------*/
6346 shiftLLong (operand * left, operand * result, int offr)
6349 int size = AOP_SIZE (result);
6351 if (size >= LSB + offr)
6353 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6355 emitcode ("add", "a,acc");
6356 if (sameRegs (AOP (left), AOP (result)) &&
6357 size >= MSB16 + offr && offr != LSB)
6358 emitcode ("xch", "a,%s",
6359 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6361 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6364 if (size >= MSB16 + offr)
6366 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6368 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6371 emitcode ("rlc", "a");
6372 if (sameRegs (AOP (left), AOP (result)) &&
6373 size >= MSB24 + offr && offr != LSB)
6374 emitcode ("xch", "a,%s",
6375 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6377 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6380 if (size >= MSB24 + offr)
6382 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6384 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6387 emitcode ("rlc", "a");
6388 if (sameRegs (AOP (left), AOP (result)) &&
6389 size >= MSB32 + offr && offr != LSB)
6390 emitcode ("xch", "a,%s",
6391 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6393 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6396 if (size > MSB32 + offr)
6398 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6400 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6403 emitcode ("rlc", "a");
6404 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6407 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6410 /*-----------------------------------------------------------------*/
6411 /* genlshFour - shift four byte by a known amount != 0 */
6412 /*-----------------------------------------------------------------*/
6414 genlshFour (operand * result, operand * left, int shCount)
6418 D(emitcode ("; genlshFour",""));
6420 size = AOP_SIZE (result);
6422 /* if shifting more that 3 bytes */
6427 /* lowest order of left goes to the highest
6428 order of the destination */
6429 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6431 movLeft2Result (left, LSB, result, MSB32, 0);
6432 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6433 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6434 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6438 /* more than two bytes */
6439 else if (shCount >= 16)
6441 /* lower order two bytes goes to higher order two bytes */
6443 /* if some more remaining */
6445 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6448 movLeft2Result (left, MSB16, result, MSB32, 0);
6449 movLeft2Result (left, LSB, result, MSB24, 0);
6451 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6452 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6456 /* if more than 1 byte */
6457 else if (shCount >= 8)
6459 /* lower order three bytes goes to higher order three bytes */
6464 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6466 movLeft2Result (left, LSB, result, MSB16, 0);
6472 movLeft2Result (left, MSB24, result, MSB32, 0);
6473 movLeft2Result (left, MSB16, result, MSB24, 0);
6474 movLeft2Result (left, LSB, result, MSB16, 0);
6475 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6477 else if (shCount == 1)
6478 shiftLLong (left, result, MSB16);
6481 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6482 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6483 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6484 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6489 /* 1 <= shCount <= 7 */
6490 else if (shCount <= 2)
6492 shiftLLong (left, result, LSB);
6494 shiftLLong (result, result, LSB);
6496 /* 3 <= shCount <= 7, optimize */
6499 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6500 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6501 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6505 /*-----------------------------------------------------------------*/
6506 /* genLeftShiftLiteral - left shifting by known count */
6507 /*-----------------------------------------------------------------*/
6509 genLeftShiftLiteral (operand * left,
6514 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6517 D(emitcode ("; genLeftShiftLiteral",""));
6519 freeAsmop (right, NULL, ic, TRUE);
6521 aopOp (left, ic, FALSE);
6522 aopOp (result, ic, FALSE);
6524 size = getSize (operandType (result));
6527 emitcode ("; shift left ", "result %d, left %d", size,
6531 /* I suppose that the left size >= result size */
6536 movLeft2Result (left, size, result, size, 0);
6540 else if (shCount >= (size * 8))
6542 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6548 genlshOne (result, left, shCount);
6552 genlshTwo (result, left, shCount);
6556 genlshFour (result, left, shCount);
6559 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6560 "*** ack! mystery literal shift!\n");
6564 freeAsmop (left, NULL, ic, TRUE);
6565 freeAsmop (result, NULL, ic, TRUE);
6568 /*-----------------------------------------------------------------*/
6569 /* genLeftShift - generates code for left shifting */
6570 /*-----------------------------------------------------------------*/
6572 genLeftShift (iCode * ic)
6574 operand *left, *right, *result;
6577 symbol *tlbl, *tlbl1;
6579 D(emitcode ("; genLeftShift",""));
6581 right = IC_RIGHT (ic);
6582 left = IC_LEFT (ic);
6583 result = IC_RESULT (ic);
6585 aopOp (right, ic, FALSE);
6587 /* if the shift count is known then do it
6588 as efficiently as possible */
6589 if (AOP_TYPE (right) == AOP_LIT)
6591 genLeftShiftLiteral (left, right, result, ic);
6595 /* shift count is unknown then we have to form
6596 a loop get the loop count in B : Note: we take
6597 only the lower order byte since shifting
6598 more that 32 bits make no sense anyway, ( the
6599 largest size of an object can be only 32 bits ) */
6601 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6602 emitcode ("inc", "b");
6603 freeAsmop (right, NULL, ic, TRUE);
6604 aopOp (left, ic, FALSE);
6605 aopOp (result, ic, FALSE);
6607 /* now move the left to the result if they are not the
6609 if (!sameRegs (AOP (left), AOP (result)) &&
6610 AOP_SIZE (result) > 1)
6613 size = AOP_SIZE (result);
6617 l = aopGet (AOP (left), offset, FALSE, TRUE);
6618 if (*l == '@' && (IS_AOP_PREG (result)))
6621 emitcode ("mov", "a,%s", l);
6622 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6625 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6630 tlbl = newiTempLabel (NULL);
6631 size = AOP_SIZE (result);
6633 tlbl1 = newiTempLabel (NULL);
6635 /* if it is only one byte then */
6638 symbol *tlbl1 = newiTempLabel (NULL);
6640 l = aopGet (AOP (left), 0, FALSE, FALSE);
6642 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6643 emitcode ("", "%05d$:", tlbl->key + 100);
6644 emitcode ("add", "a,acc");
6645 emitcode ("", "%05d$:", tlbl1->key + 100);
6646 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6647 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6651 reAdjustPreg (AOP (result));
6653 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6654 emitcode ("", "%05d$:", tlbl->key + 100);
6655 l = aopGet (AOP (result), offset, FALSE, FALSE);
6657 emitcode ("add", "a,acc");
6658 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6661 l = aopGet (AOP (result), offset, FALSE, FALSE);
6663 emitcode ("rlc", "a");
6664 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6666 reAdjustPreg (AOP (result));
6668 emitcode ("", "%05d$:", tlbl1->key + 100);
6669 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6671 freeAsmop (left, NULL, ic, TRUE);
6672 freeAsmop (result, NULL, ic, TRUE);
6675 /*-----------------------------------------------------------------*/
6676 /* genrshOne - right shift a one byte quantity by known count */
6677 /*-----------------------------------------------------------------*/
6679 genrshOne (operand * result, operand * left,
6680 int shCount, int sign)
6682 D(emitcode ("; genrshOne",""));
6684 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6687 /*-----------------------------------------------------------------*/
6688 /* genrshTwo - right shift two bytes by known amount != 0 */
6689 /*-----------------------------------------------------------------*/
6691 genrshTwo (operand * result, operand * left,
6692 int shCount, int sign)
6694 D(emitcode ("; genrshTwo",""));
6696 /* if shCount >= 8 */
6701 shiftR1Left2Result (left, MSB16, result, LSB,
6704 movLeft2Result (left, MSB16, result, LSB, sign);
6705 addSign (result, MSB16, sign);
6708 /* 1 <= shCount <= 7 */
6710 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6713 /*-----------------------------------------------------------------*/
6714 /* shiftRLong - shift right one long from left to result */
6715 /* offl = LSB or MSB16 */
6716 /*-----------------------------------------------------------------*/
6718 shiftRLong (operand * left, int offl,
6719 operand * result, int sign)
6721 int isSameRegs=sameRegs(AOP(left),AOP(result));
6723 if (isSameRegs && offl>1) {
6724 // we are in big trouble, but this shouldn't happen
6725 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6728 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6733 emitcode ("rlc", "a");
6734 emitcode ("subb", "a,acc");
6736 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6738 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6739 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6742 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6747 emitcode ("clr", "c");
6749 emitcode ("mov", "c,acc.7");
6752 emitcode ("rrc", "a");
6754 if (isSameRegs && offl==MSB16) {
6755 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6757 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6758 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6761 emitcode ("rrc", "a");
6762 if (isSameRegs && offl==1) {
6763 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6765 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6766 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6768 emitcode ("rrc", "a");
6769 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6773 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6774 emitcode ("rrc", "a");
6775 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6779 /*-----------------------------------------------------------------*/
6780 /* genrshFour - shift four byte by a known amount != 0 */
6781 /*-----------------------------------------------------------------*/
6783 genrshFour (operand * result, operand * left,
6784 int shCount, int sign)
6786 D(emitcode ("; genrshFour",""));
6788 /* if shifting more that 3 bytes */
6793 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6795 movLeft2Result (left, MSB32, result, LSB, sign);
6796 addSign (result, MSB16, sign);
6798 else if (shCount >= 16)
6802 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6805 movLeft2Result (left, MSB24, result, LSB, 0);
6806 movLeft2Result (left, MSB32, result, MSB16, sign);
6808 addSign (result, MSB24, sign);
6810 else if (shCount >= 8)
6814 shiftRLong (left, MSB16, result, sign);
6815 else if (shCount == 0)
6817 movLeft2Result (left, MSB16, result, LSB, 0);
6818 movLeft2Result (left, MSB24, result, MSB16, 0);
6819 movLeft2Result (left, MSB32, result, MSB24, sign);
6820 addSign (result, MSB32, sign);
6824 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6825 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6826 /* the last shift is signed */
6827 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6828 addSign (result, MSB32, sign);
6832 { /* 1 <= shCount <= 7 */
6835 shiftRLong (left, LSB, result, sign);
6837 shiftRLong (result, LSB, result, sign);
6841 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6842 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6843 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6848 /*-----------------------------------------------------------------*/
6849 /* genRightShiftLiteral - right shifting by known count */
6850 /*-----------------------------------------------------------------*/
6852 genRightShiftLiteral (operand * left,
6858 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6861 D(emitcode ("; genRightShiftLiteral",""));
6863 freeAsmop (right, NULL, ic, TRUE);
6865 aopOp (left, ic, FALSE);
6866 aopOp (result, ic, FALSE);
6869 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6873 size = getDataSize (left);
6874 /* test the LEFT size !!! */
6876 /* I suppose that the left size >= result size */
6879 size = getDataSize (result);
6881 movLeft2Result (left, size, result, size, 0);
6884 else if (shCount >= (size * 8))
6887 /* get sign in acc.7 */
6888 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6890 addSign (result, LSB, sign);
6897 genrshOne (result, left, shCount, sign);
6901 genrshTwo (result, left, shCount, sign);
6905 genrshFour (result, left, shCount, sign);
6911 freeAsmop (left, NULL, ic, TRUE);
6912 freeAsmop (result, NULL, ic, TRUE);
6915 /*-----------------------------------------------------------------*/
6916 /* genSignedRightShift - right shift of signed number */
6917 /*-----------------------------------------------------------------*/
6919 genSignedRightShift (iCode * ic)
6921 operand *right, *left, *result;
6924 symbol *tlbl, *tlbl1;
6926 D(emitcode ("; genSignedRightShift",""));
6928 /* we do it the hard way put the shift count in b
6929 and loop thru preserving the sign */
6931 right = IC_RIGHT (ic);
6932 left = IC_LEFT (ic);
6933 result = IC_RESULT (ic);
6935 aopOp (right, ic, FALSE);
6938 if (AOP_TYPE (right) == AOP_LIT)
6940 genRightShiftLiteral (left, right, result, ic, 1);
6943 /* shift count is unknown then we have to form
6944 a loop get the loop count in B : Note: we take
6945 only the lower order byte since shifting
6946 more that 32 bits make no sense anyway, ( the
6947 largest size of an object can be only 32 bits ) */
6949 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6950 emitcode ("inc", "b");
6951 freeAsmop (right, NULL, ic, TRUE);
6952 aopOp (left, ic, FALSE);
6953 aopOp (result, ic, FALSE);
6955 /* now move the left to the result if they are not the
6957 if (!sameRegs (AOP (left), AOP (result)) &&
6958 AOP_SIZE (result) > 1)
6961 size = AOP_SIZE (result);
6965 l = aopGet (AOP (left), offset, FALSE, TRUE);
6966 if (*l == '@' && IS_AOP_PREG (result))
6969 emitcode ("mov", "a,%s", l);
6970 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6973 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6978 /* mov the highest order bit to OVR */
6979 tlbl = newiTempLabel (NULL);
6980 tlbl1 = newiTempLabel (NULL);
6982 size = AOP_SIZE (result);
6984 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6985 emitcode ("rlc", "a");
6986 emitcode ("mov", "ov,c");
6987 /* if it is only one byte then */
6990 l = aopGet (AOP (left), 0, FALSE, FALSE);
6992 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6993 emitcode ("", "%05d$:", tlbl->key + 100);
6994 emitcode ("mov", "c,ov");
6995 emitcode ("rrc", "a");
6996 emitcode ("", "%05d$:", tlbl1->key + 100);
6997 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6998 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7002 reAdjustPreg (AOP (result));
7003 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7004 emitcode ("", "%05d$:", tlbl->key + 100);
7005 emitcode ("mov", "c,ov");
7008 l = aopGet (AOP (result), offset, FALSE, FALSE);
7010 emitcode ("rrc", "a");
7011 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7013 reAdjustPreg (AOP (result));
7014 emitcode ("", "%05d$:", tlbl1->key + 100);
7015 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7018 freeAsmop (left, NULL, ic, TRUE);
7019 freeAsmop (result, NULL, ic, TRUE);
7022 /*-----------------------------------------------------------------*/
7023 /* genRightShift - generate code for right shifting */
7024 /*-----------------------------------------------------------------*/
7026 genRightShift (iCode * ic)
7028 operand *right, *left, *result;
7032 symbol *tlbl, *tlbl1;
7034 D(emitcode ("; genRightShift",""));
7036 /* if signed then we do it the hard way preserve the
7037 sign bit moving it inwards */
7038 retype = getSpec (operandType (IC_RESULT (ic)));
7040 if (!SPEC_USIGN (retype))
7042 genSignedRightShift (ic);
7046 /* signed & unsigned types are treated the same : i.e. the
7047 signed is NOT propagated inwards : quoting from the
7048 ANSI - standard : "for E1 >> E2, is equivalent to division
7049 by 2**E2 if unsigned or if it has a non-negative value,
7050 otherwise the result is implementation defined ", MY definition
7051 is that the sign does not get propagated */
7053 right = IC_RIGHT (ic);
7054 left = IC_LEFT (ic);
7055 result = IC_RESULT (ic);
7057 aopOp (right, ic, FALSE);
7059 /* if the shift count is known then do it
7060 as efficiently as possible */
7061 if (AOP_TYPE (right) == AOP_LIT)
7063 genRightShiftLiteral (left, right, result, ic, 0);
7067 /* shift count is unknown then we have to form
7068 a loop get the loop count in B : Note: we take
7069 only the lower order byte since shifting
7070 more that 32 bits make no sense anyway, ( the
7071 largest size of an object can be only 32 bits ) */
7073 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7074 emitcode ("inc", "b");
7075 freeAsmop (right, NULL, ic, TRUE);
7076 aopOp (left, ic, FALSE);
7077 aopOp (result, ic, FALSE);
7079 /* now move the left to the result if they are not the
7081 if (!sameRegs (AOP (left), AOP (result)) &&
7082 AOP_SIZE (result) > 1)
7085 size = AOP_SIZE (result);
7089 l = aopGet (AOP (left), offset, FALSE, TRUE);
7090 if (*l == '@' && IS_AOP_PREG (result))
7093 emitcode ("mov", "a,%s", l);
7094 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7097 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7102 tlbl = newiTempLabel (NULL);
7103 tlbl1 = newiTempLabel (NULL);
7104 size = AOP_SIZE (result);
7107 /* if it is only one byte then */
7110 l = aopGet (AOP (left), 0, FALSE, FALSE);
7112 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7113 emitcode ("", "%05d$:", tlbl->key + 100);
7115 emitcode ("rrc", "a");
7116 emitcode ("", "%05d$:", tlbl1->key + 100);
7117 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7118 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7122 reAdjustPreg (AOP (result));
7123 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7124 emitcode ("", "%05d$:", tlbl->key + 100);
7128 l = aopGet (AOP (result), offset, FALSE, FALSE);
7130 emitcode ("rrc", "a");
7131 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7133 reAdjustPreg (AOP (result));
7135 emitcode ("", "%05d$:", tlbl1->key + 100);
7136 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7139 freeAsmop (left, NULL, ic, TRUE);
7140 freeAsmop (result, NULL, ic, TRUE);
7143 /*-----------------------------------------------------------------*/
7144 /* emitPtrByteGet - emits code to get a byte into A through a */
7145 /* pointer register (R0, R1, or DPTR). The */
7146 /* original value of A can be preserved in B. */
7147 /*-----------------------------------------------------------------*/
7149 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7156 emitcode ("mov", "b,a");
7157 emitcode ("mov", "a,@%s", rname);
7162 emitcode ("mov", "b,a");
7163 emitcode ("movx", "a,@%s", rname);
7168 emitcode ("mov", "b,a");
7169 emitcode ("movx", "a,@dptr");
7174 emitcode ("mov", "b,a");
7175 emitcode ("clr", "a");
7176 emitcode ("movc", "a,@a+dptr");
7182 emitcode ("push", "b");
7183 emitcode ("push", "acc");
7185 emitcode ("lcall", "__gptrget");
7187 emitcode ("pop", "b");
7192 /*-----------------------------------------------------------------*/
7193 /* emitPtrByteSet - emits code to set a byte from src through a */
7194 /* pointer register (R0, R1, or DPTR). */
7195 /*-----------------------------------------------------------------*/
7197 emitPtrByteSet (char *rname, int p_type, char *src)
7206 emitcode ("mov", "@%s,a", rname);
7209 emitcode ("mov", "@%s,%s", rname, src);
7214 emitcode ("movx", "@%s,a", rname);
7219 emitcode ("movx", "@dptr,a");
7224 emitcode ("lcall", "__gptrput");
7229 /*-----------------------------------------------------------------*/
7230 /* genUnpackBits - generates code for unpacking bits */
7231 /*-----------------------------------------------------------------*/
7233 genUnpackBits (operand * result, char *rname, int ptype)
7235 int offset = 0; /* result byte offset */
7236 int rsize; /* result size */
7237 int rlen = 0; /* remaining bitfield length */
7238 sym_link *etype; /* bitfield type information */
7239 int blen; /* bitfield length */
7240 int bstr; /* bitfield starting bit within byte */
7242 D(emitcode ("; genUnpackBits",""));
7244 etype = getSpec (operandType (result));
7245 rsize = getSize (operandType (result));
7246 blen = SPEC_BLEN (etype);
7247 bstr = SPEC_BSTR (etype);
7249 /* If the bitfield length is less than a byte */
7252 emitPtrByteGet (rname, ptype, FALSE);
7254 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7255 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7259 /* Bit field did not fit in a byte. Copy all
7260 but the partial byte at the end. */
7261 for (rlen=blen;rlen>=8;rlen-=8)
7263 emitPtrByteGet (rname, ptype, FALSE);
7264 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7266 emitcode ("inc", "%s", rname);
7269 /* Handle the partial byte at the end */
7272 emitPtrByteGet (rname, ptype, FALSE);
7273 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7274 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7282 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7287 /*-----------------------------------------------------------------*/
7288 /* genDataPointerGet - generates code when ptr offset is known */
7289 /*-----------------------------------------------------------------*/
7291 genDataPointerGet (operand * left,
7297 int size, offset = 0;
7299 D(emitcode ("; genDataPointerGet",""));
7301 aopOp (result, ic, TRUE);
7303 /* get the string representation of the name */
7304 l = aopGet (AOP (left), 0, FALSE, TRUE);
7305 size = AOP_SIZE (result);
7309 sprintf (buffer, "(%s + %d)", l + 1, offset);
7311 sprintf (buffer, "%s", l + 1);
7312 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7315 freeAsmop (left, NULL, ic, TRUE);
7316 freeAsmop (result, NULL, ic, TRUE);
7319 /*-----------------------------------------------------------------*/
7320 /* genNearPointerGet - emitcode for near pointer fetch */
7321 /*-----------------------------------------------------------------*/
7323 genNearPointerGet (operand * left,
7331 sym_link *rtype, *retype;
7332 sym_link *ltype = operandType (left);
7335 D(emitcode ("; genNearPointerGet",""));
7337 rtype = operandType (result);
7338 retype = getSpec (rtype);
7340 aopOp (left, ic, FALSE);
7342 /* if left is rematerialisable and
7343 result is not bit variable type and
7344 the left is pointer to data space i.e
7345 lower 128 bytes of space */
7346 if (AOP_TYPE (left) == AOP_IMMD &&
7347 !IS_BITVAR (retype) &&
7348 DCL_TYPE (ltype) == POINTER)
7350 genDataPointerGet (left, result, ic);
7354 /* if the value is already in a pointer register
7355 then don't need anything more */
7356 if (!AOP_INPREG (AOP (left)))
7358 if (IS_AOP_PREG (left))
7360 // Aha, it is a pointer, just in disguise.
7361 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7364 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7365 __FILE__, __LINE__);
7370 emitcode ("mov", "a%s,%s", rname + 1, rname);
7371 rname++; // skip the '@'.
7376 /* otherwise get a free pointer register */
7378 preg = getFreePtr (ic, &aop, FALSE);
7379 emitcode ("mov", "%s,%s",
7381 aopGet (AOP (left), 0, FALSE, TRUE));
7386 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7388 //aopOp (result, ic, FALSE);
7389 aopOp (result, ic, result?TRUE:FALSE);
7391 /* if bitfield then unpack the bits */
7392 if (IS_BITVAR (retype))
7393 genUnpackBits (result, rname, POINTER);
7396 /* we have can just get the values */
7397 int size = AOP_SIZE (result);
7402 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7405 emitcode ("mov", "a,@%s", rname);
7406 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7410 sprintf (buffer, "@%s", rname);
7411 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7415 emitcode ("inc", "%s", rname);
7419 /* now some housekeeping stuff */
7420 if (aop) /* we had to allocate for this iCode */
7422 if (pi) { /* post increment present */
7423 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7425 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7429 /* we did not allocate which means left
7430 already in a pointer register, then
7431 if size > 0 && this could be used again
7432 we have to point it back to where it
7434 if ((AOP_SIZE (result) > 1 &&
7435 !OP_SYMBOL (left)->remat &&
7436 (OP_SYMBOL (left)->liveTo > ic->seq ||
7440 int size = AOP_SIZE (result) - 1;
7442 emitcode ("dec", "%s", rname);
7447 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7448 freeAsmop (left, NULL, ic, TRUE);
7449 if (pi) pi->generated = 1;
7452 /*-----------------------------------------------------------------*/
7453 /* genPagedPointerGet - emitcode for paged pointer fetch */
7454 /*-----------------------------------------------------------------*/
7456 genPagedPointerGet (operand * left,
7464 sym_link *rtype, *retype;
7466 D(emitcode ("; genPagedPointerGet",""));
7468 rtype = operandType (result);
7469 retype = getSpec (rtype);
7471 aopOp (left, ic, FALSE);
7473 /* if the value is already in a pointer register
7474 then don't need anything more */
7475 if (!AOP_INPREG (AOP (left)))
7477 /* otherwise get a free pointer register */
7479 preg = getFreePtr (ic, &aop, FALSE);
7480 emitcode ("mov", "%s,%s",
7482 aopGet (AOP (left), 0, FALSE, TRUE));
7486 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7488 aopOp (result, ic, FALSE);
7490 /* if bitfield then unpack the bits */
7491 if (IS_BITVAR (retype))
7492 genUnpackBits (result, rname, PPOINTER);
7495 /* we have can just get the values */
7496 int size = AOP_SIZE (result);
7502 emitcode ("movx", "a,@%s", rname);
7503 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7508 emitcode ("inc", "%s", rname);
7512 /* now some housekeeping stuff */
7513 if (aop) /* we had to allocate for this iCode */
7515 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7516 freeAsmop (NULL, aop, ic, TRUE);
7520 /* we did not allocate which means left
7521 already in a pointer register, then
7522 if size > 0 && this could be used again
7523 we have to point it back to where it
7525 if ((AOP_SIZE (result) > 1 &&
7526 !OP_SYMBOL (left)->remat &&
7527 (OP_SYMBOL (left)->liveTo > ic->seq ||
7531 int size = AOP_SIZE (result) - 1;
7533 emitcode ("dec", "%s", rname);
7538 freeAsmop (left, NULL, ic, TRUE);
7539 freeAsmop (result, NULL, ic, TRUE);
7540 if (pi) pi->generated = 1;
7544 /*--------------------------------------------------------------------*/
7545 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7546 /*--------------------------------------------------------------------*/
7548 loadDptrFromOperand (operand *op, bool loadBToo)
7550 if (AOP_TYPE (op) != AOP_STR)
7552 /* if this is remateriazable */
7553 if (AOP_TYPE (op) == AOP_IMMD)
7555 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7558 if (AOP(op)->aopu.aop_immd.from_cast_remat)
7559 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7562 wassertl(FALSE, "need pointerCode");
7563 emitcode ("", "; mov b,???");
7564 /* genPointerGet and genPointerSet originally did different
7565 ** things for this case. Both seem wrong.
7566 ** from genPointerGet:
7567 ** emitcode ("mov", "b,#%d", pointerCode (retype));
7568 ** from genPointerSet:
7569 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7574 else if (AOP_TYPE (op) == AOP_DPTR)
7578 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7579 emitcode ("push", "acc");
7580 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7581 emitcode ("push", "acc");
7582 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7583 emitcode ("pop", "dph");
7584 emitcode ("pop", "dpl");
7588 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7589 emitcode ("push", "acc");
7590 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7591 emitcode ("pop", "dpl");
7595 { /* we need to get it byte by byte */
7596 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7597 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7599 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7604 /*-----------------------------------------------------------------*/
7605 /* genFarPointerGet - gget value from far space */
7606 /*-----------------------------------------------------------------*/
7608 genFarPointerGet (operand * left,
7609 operand * result, iCode * ic, iCode * pi)
7612 sym_link *retype = getSpec (operandType (result));
7614 D(emitcode ("; genFarPointerGet",""));
7616 aopOp (left, ic, FALSE);
7617 loadDptrFromOperand (left, FALSE);
7619 /* so dptr now contains the address */
7620 aopOp (result, ic, FALSE);
7622 /* if bit then unpack */
7623 if (IS_BITVAR (retype))
7624 genUnpackBits (result, "dptr", FPOINTER);
7627 size = AOP_SIZE (result);
7632 emitcode ("movx", "a,@dptr");
7633 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7635 emitcode ("inc", "dptr");
7639 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7640 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7641 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7644 freeAsmop (left, NULL, ic, TRUE);
7645 freeAsmop (result, NULL, ic, TRUE);
7648 /*-----------------------------------------------------------------*/
7649 /* genCodePointerGet - gget value from code space */
7650 /*-----------------------------------------------------------------*/
7652 genCodePointerGet (operand * left,
7653 operand * result, iCode * ic, iCode *pi)
7656 sym_link *retype = getSpec (operandType (result));
7658 D(emitcode ("; genCodePointerGet",""));
7660 aopOp (left, ic, FALSE);
7661 loadDptrFromOperand (left, FALSE);
7663 /* so dptr now contains the address */
7664 aopOp (result, ic, FALSE);
7666 /* if bit then unpack */
7667 if (IS_BITVAR (retype))
7668 genUnpackBits (result, "dptr", CPOINTER);
7671 size = AOP_SIZE (result);
7678 emitcode ("clr", "a");
7679 emitcode ("movc", "a,@a+dptr");
7680 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7681 emitcode ("inc", "dptr");
7685 emitcode ("mov", "a,#0x%02x", offset);
7686 emitcode ("movc", "a,@a+dptr");
7687 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7692 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7693 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7694 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7697 freeAsmop (left, NULL, ic, TRUE);
7698 freeAsmop (result, NULL, ic, TRUE);
7701 /*-----------------------------------------------------------------*/
7702 /* genGenPointerGet - gget value from generic pointer space */
7703 /*-----------------------------------------------------------------*/
7705 genGenPointerGet (operand * left,
7706 operand * result, iCode * ic, iCode *pi)
7709 sym_link *retype = getSpec (operandType (result));
7711 D(emitcode ("; genGenPointerGet",""));
7713 aopOp (left, ic, FALSE);
7714 loadDptrFromOperand (left, TRUE);
7716 /* so dptr know contains the address */
7717 aopOp (result, ic, FALSE);
7719 /* if bit then unpack */
7720 if (IS_BITVAR (retype))
7721 genUnpackBits (result, "dptr", GPOINTER);
7724 size = AOP_SIZE (result);
7729 emitcode ("lcall", "__gptrget");
7730 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7732 emitcode ("inc", "dptr");
7736 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7737 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7738 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7741 freeAsmop (left, NULL, ic, TRUE);
7742 freeAsmop (result, NULL, ic, TRUE);
7745 /*-----------------------------------------------------------------*/
7746 /* genPointerGet - generate code for pointer get */
7747 /*-----------------------------------------------------------------*/
7749 genPointerGet (iCode * ic, iCode *pi)
7751 operand *left, *result;
7752 sym_link *type, *etype;
7755 D(emitcode ("; genPointerGet",""));
7757 left = IC_LEFT (ic);
7758 result = IC_RESULT (ic);
7760 /* depending on the type of pointer we need to
7761 move it to the correct pointer register */
7762 type = operandType (left);
7763 etype = getSpec (type);
7764 /* if left is of type of pointer then it is simple */
7765 if (IS_PTR (type) && !IS_FUNC (type->next))
7766 p_type = DCL_TYPE (type);
7769 /* we have to go by the storage class */
7770 p_type = PTR_TYPE (SPEC_OCLS (etype));
7773 /* special case when cast remat */
7774 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7775 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7776 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7777 type = operandType (left);
7778 p_type = DCL_TYPE (type);
7780 /* now that we have the pointer type we assign
7781 the pointer values */
7787 genNearPointerGet (left, result, ic, pi);
7791 genPagedPointerGet (left, result, ic, pi);
7795 genFarPointerGet (left, result, ic, pi);
7799 genCodePointerGet (left, result, ic, pi);
7803 genGenPointerGet (left, result, ic, pi);
7811 /*-----------------------------------------------------------------*/
7812 /* genPackBits - generates code for packed bit storage */
7813 /*-----------------------------------------------------------------*/
7815 genPackBits (sym_link * etype,
7817 char *rname, int p_type)
7819 int offset = 0; /* source byte offset */
7820 int rlen = 0; /* remaining bitfield length */
7821 int blen; /* bitfield length */
7822 int bstr; /* bitfield starting bit within byte */
7823 int litval; /* source literal value (if AOP_LIT) */
7824 unsigned char mask; /* bitmask within current byte */
7826 D(emitcode ("; genPackBits",""));
7828 blen = SPEC_BLEN (etype);
7829 bstr = SPEC_BSTR (etype);
7831 /* If the bitfield length is less than a byte */
7834 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7835 (unsigned char) (0xFF >> (8 - bstr)));
7837 if (AOP_TYPE (right) == AOP_LIT)
7839 /* Case with a bitfield length <8 and literal source
7841 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7843 litval &= (~mask) & 0xff;
7844 emitPtrByteGet (rname, p_type, FALSE);
7845 if ((mask|litval)!=0xff)
7846 emitcode ("anl","a,#0x%02x", mask);
7848 emitcode ("orl","a,#0x%02x", litval);
7852 if ((blen==1) && (p_type!=GPOINTER))
7854 /* Case with a bitfield length == 1 and no generic pointer
7856 if (AOP_TYPE (right) == AOP_CRY)
7857 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7860 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7861 emitcode ("rrc","a");
7863 emitPtrByteGet (rname, p_type, FALSE);
7864 emitcode ("mov","acc.%d,c",bstr);
7868 /* Case with a bitfield length < 8 and arbitrary source
7870 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7871 /* shift and mask source value */
7873 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7875 /* transfer A to B and get next byte */
7876 emitPtrByteGet (rname, p_type, TRUE);
7878 emitcode ("anl", "a,#0x%02x", mask);
7879 emitcode ("orl", "a,b");
7880 if (p_type == GPOINTER)
7881 emitcode ("pop", "b");
7885 emitPtrByteSet (rname, p_type, "a");
7889 /* Bit length is greater than 7 bits. In this case, copy */
7890 /* all except the partial byte at the end */
7891 for (rlen=blen;rlen>=8;rlen-=8)
7893 emitPtrByteSet (rname, p_type,
7894 aopGet (AOP (right), offset++, FALSE, TRUE) );
7896 emitcode ("inc", "%s", rname);
7899 /* If there was a partial byte at the end */
7902 mask = (((unsigned char) -1 << rlen) & 0xff);
7904 if (AOP_TYPE (right) == AOP_LIT)
7906 /* Case with partial byte and literal source
7908 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7909 litval >>= (blen-rlen);
7910 litval &= (~mask) & 0xff;
7911 emitPtrByteGet (rname, p_type, FALSE);
7912 if ((mask|litval)!=0xff)
7913 emitcode ("anl","a,#0x%02x", mask);
7915 emitcode ("orl","a,#0x%02x", litval);
7919 /* Case with partial byte and arbitrary source
7921 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
7922 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7924 /* transfer A to B and get next byte */
7925 emitPtrByteGet (rname, p_type, TRUE);
7927 emitcode ("anl", "a,#0x%02x", mask);
7928 emitcode ("orl", "a,b");
7929 if (p_type == GPOINTER)
7930 emitcode ("pop", "b");
7932 emitPtrByteSet (rname, p_type, "a");
7938 /*-----------------------------------------------------------------*/
7939 /* genDataPointerSet - remat pointer to data space */
7940 /*-----------------------------------------------------------------*/
7942 genDataPointerSet (operand * right,
7946 int size, offset = 0;
7947 char *l, buffer[256];
7949 D(emitcode ("; genDataPointerSet",""));
7951 aopOp (right, ic, FALSE);
7953 l = aopGet (AOP (result), 0, FALSE, TRUE);
7954 size = AOP_SIZE (right);
7958 sprintf (buffer, "(%s + %d)", l + 1, offset);
7960 sprintf (buffer, "%s", l + 1);
7961 emitcode ("mov", "%s,%s", buffer,
7962 aopGet (AOP (right), offset++, FALSE, FALSE));
7965 freeAsmop (right, NULL, ic, TRUE);
7966 freeAsmop (result, NULL, ic, TRUE);
7969 /*-----------------------------------------------------------------*/
7970 /* genNearPointerSet - emitcode for near pointer put */
7971 /*-----------------------------------------------------------------*/
7973 genNearPointerSet (operand * right,
7981 sym_link *retype, *letype;
7982 sym_link *ptype = operandType (result);
7984 D(emitcode ("; genNearPointerSet",""));
7986 retype = getSpec (operandType (right));
7987 letype = getSpec (ptype);
7988 aopOp (result, ic, FALSE);
7990 /* if the result is rematerializable &
7991 in data space & not a bit variable */
7992 if (AOP_TYPE (result) == AOP_IMMD &&
7993 DCL_TYPE (ptype) == POINTER &&
7994 !IS_BITVAR (retype) &&
7995 !IS_BITVAR (letype))
7997 genDataPointerSet (right, result, ic);
8001 /* if the value is already in a pointer register
8002 then don't need anything more */
8003 if (!AOP_INPREG (AOP (result)))
8006 //AOP_TYPE (result) == AOP_STK
8010 // Aha, it is a pointer, just in disguise.
8011 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8014 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8015 __FILE__, __LINE__);
8020 emitcode ("mov", "a%s,%s", rname + 1, rname);
8021 rname++; // skip the '@'.
8026 /* otherwise get a free pointer register */
8028 preg = getFreePtr (ic, &aop, FALSE);
8029 emitcode ("mov", "%s,%s",
8031 aopGet (AOP (result), 0, FALSE, TRUE));
8037 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8040 aopOp (right, ic, FALSE);
8042 /* if bitfield then unpack the bits */
8043 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8044 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8047 /* we have can just get the values */
8048 int size = AOP_SIZE (right);
8053 l = aopGet (AOP (right), offset, FALSE, TRUE);
8057 emitcode ("mov", "@%s,a", rname);
8060 emitcode ("mov", "@%s,%s", rname, l);
8062 emitcode ("inc", "%s", rname);
8067 /* now some housekeeping stuff */
8068 if (aop) /* we had to allocate for this iCode */
8071 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8072 freeAsmop (NULL, aop, ic, TRUE);
8076 /* we did not allocate which means left
8077 already in a pointer register, then
8078 if size > 0 && this could be used again
8079 we have to point it back to where it
8081 if ((AOP_SIZE (right) > 1 &&
8082 !OP_SYMBOL (result)->remat &&
8083 (OP_SYMBOL (result)->liveTo > ic->seq ||
8087 int size = AOP_SIZE (right) - 1;
8089 emitcode ("dec", "%s", rname);
8094 if (pi) pi->generated = 1;
8095 freeAsmop (result, NULL, ic, TRUE);
8096 freeAsmop (right, NULL, ic, TRUE);
8099 /*-----------------------------------------------------------------*/
8100 /* genPagedPointerSet - emitcode for Paged pointer put */
8101 /*-----------------------------------------------------------------*/
8103 genPagedPointerSet (operand * right,
8111 sym_link *retype, *letype;
8113 D(emitcode ("; genPagedPointerSet",""));
8115 retype = getSpec (operandType (right));
8116 letype = getSpec (operandType (result));
8118 aopOp (result, ic, FALSE);
8120 /* if the value is already in a pointer register
8121 then don't need anything more */
8122 if (!AOP_INPREG (AOP (result)))
8124 /* otherwise get a free pointer register */
8126 preg = getFreePtr (ic, &aop, FALSE);
8127 emitcode ("mov", "%s,%s",
8129 aopGet (AOP (result), 0, FALSE, TRUE));
8133 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8135 aopOp (right, ic, FALSE);
8137 /* if bitfield then unpack the bits */
8138 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8139 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8142 /* we have can just get the values */
8143 int size = AOP_SIZE (right);
8148 l = aopGet (AOP (right), offset, FALSE, TRUE);
8151 emitcode ("movx", "@%s,a", rname);
8154 emitcode ("inc", "%s", rname);
8160 /* now some housekeeping stuff */
8161 if (aop) /* we had to allocate for this iCode */
8164 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8165 freeAsmop (NULL, aop, ic, TRUE);
8169 /* we did not allocate which means left
8170 already in a pointer register, then
8171 if size > 0 && this could be used again
8172 we have to point it back to where it
8174 if (AOP_SIZE (right) > 1 &&
8175 !OP_SYMBOL (result)->remat &&
8176 (OP_SYMBOL (result)->liveTo > ic->seq ||
8179 int size = AOP_SIZE (right) - 1;
8181 emitcode ("dec", "%s", rname);
8186 if (pi) pi->generated = 1;
8187 freeAsmop (result, NULL, ic, TRUE);
8188 freeAsmop (right, NULL, ic, TRUE);
8193 /*-----------------------------------------------------------------*/
8194 /* genFarPointerSet - set value from far space */
8195 /*-----------------------------------------------------------------*/
8197 genFarPointerSet (operand * right,
8198 operand * result, iCode * ic, iCode * pi)
8201 sym_link *retype = getSpec (operandType (right));
8202 sym_link *letype = getSpec (operandType (result));
8204 D(emitcode ("; genFarPointerSet",""));
8206 aopOp (result, ic, FALSE);
8207 loadDptrFromOperand (result, FALSE);
8209 /* so dptr know contains the address */
8210 aopOp (right, ic, FALSE);
8212 /* if bit then unpack */
8213 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8214 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8217 size = AOP_SIZE (right);
8222 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8224 emitcode ("movx", "@dptr,a");
8226 emitcode ("inc", "dptr");
8229 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8230 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8231 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8234 freeAsmop (result, NULL, ic, TRUE);
8235 freeAsmop (right, NULL, ic, TRUE);
8238 /*-----------------------------------------------------------------*/
8239 /* genGenPointerSet - set value from generic pointer space */
8240 /*-----------------------------------------------------------------*/
8242 genGenPointerSet (operand * right,
8243 operand * result, iCode * ic, iCode * pi)
8246 sym_link *retype = getSpec (operandType (right));
8247 sym_link *letype = getSpec (operandType (result));
8249 D(emitcode ("; genGenPointerSet",""));
8251 aopOp (result, ic, FALSE);
8252 loadDptrFromOperand (result, TRUE);
8254 /* so dptr know contains the address */
8255 aopOp (right, ic, FALSE);
8257 /* if bit then unpack */
8258 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8259 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8262 size = AOP_SIZE (right);
8267 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8269 emitcode ("lcall", "__gptrput");
8271 emitcode ("inc", "dptr");
8275 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8276 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8277 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8280 freeAsmop (result, NULL, ic, TRUE);
8281 freeAsmop (right, NULL, ic, TRUE);
8284 /*-----------------------------------------------------------------*/
8285 /* genPointerSet - stores the value into a pointer location */
8286 /*-----------------------------------------------------------------*/
8288 genPointerSet (iCode * ic, iCode *pi)
8290 operand *right, *result;
8291 sym_link *type, *etype;
8294 D(emitcode ("; genPointerSet",""));
8296 right = IC_RIGHT (ic);
8297 result = IC_RESULT (ic);
8299 /* depending on the type of pointer we need to
8300 move it to the correct pointer register */
8301 type = operandType (result);
8302 etype = getSpec (type);
8303 /* if left is of type of pointer then it is simple */
8304 if (IS_PTR (type) && !IS_FUNC (type->next))
8306 p_type = DCL_TYPE (type);
8310 /* we have to go by the storage class */
8311 p_type = PTR_TYPE (SPEC_OCLS (etype));
8314 /* special case when cast remat */
8315 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8316 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8317 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8318 type = operandType (result);
8319 p_type = DCL_TYPE (type);
8321 /* now that we have the pointer type we assign
8322 the pointer values */
8328 genNearPointerSet (right, result, ic, pi);
8332 genPagedPointerSet (right, result, ic, pi);
8336 genFarPointerSet (right, result, ic, pi);
8340 genGenPointerSet (right, result, ic, pi);
8344 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8345 "genPointerSet: illegal pointer type");
8350 /*-----------------------------------------------------------------*/
8351 /* genIfx - generate code for Ifx statement */
8352 /*-----------------------------------------------------------------*/
8354 genIfx (iCode * ic, iCode * popIc)
8356 operand *cond = IC_COND (ic);
8359 D(emitcode ("; genIfx",""));
8361 aopOp (cond, ic, FALSE);
8363 /* get the value into acc */
8364 if (AOP_TYPE (cond) != AOP_CRY)
8368 /* the result is now in the accumulator */
8369 freeAsmop (cond, NULL, ic, TRUE);
8371 /* if there was something to be popped then do it */
8375 /* if the condition is a bit variable */
8376 if (isbit && IS_ITEMP (cond) &&
8378 genIfxJump (ic, SPIL_LOC (cond)->rname);
8379 else if (isbit && !IS_ITEMP (cond))
8380 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8382 genIfxJump (ic, "a");
8387 /*-----------------------------------------------------------------*/
8388 /* genAddrOf - generates code for address of */
8389 /*-----------------------------------------------------------------*/
8391 genAddrOf (iCode * ic)
8393 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8396 D(emitcode ("; genAddrOf",""));
8398 aopOp (IC_RESULT (ic), ic, FALSE);
8400 /* if the operand is on the stack then we
8401 need to get the stack offset of this
8405 /* if it has an offset then we need to compute
8409 emitcode ("mov", "a,_bp");
8410 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8411 ((char) (sym->stack - _G.nRegsSaved)) :
8412 ((char) sym->stack)) & 0xff);
8413 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8417 /* we can just move _bp */
8418 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8420 /* fill the result with zero */
8421 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8426 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8432 /* object not on stack then we need the name */
8433 size = AOP_SIZE (IC_RESULT (ic));
8438 char s[SDCC_NAME_MAX];
8440 sprintf (s, "#(%s >> %d)",
8444 sprintf (s, "#%s", sym->rname);
8445 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8449 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8453 /*-----------------------------------------------------------------*/
8454 /* genFarFarAssign - assignment when both are in far space */
8455 /*-----------------------------------------------------------------*/
8457 genFarFarAssign (operand * result, operand * right, iCode * ic)
8459 int size = AOP_SIZE (right);
8463 D(emitcode ("; genFarFarAssign",""));
8465 /* first push the right side on to the stack */
8468 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8470 emitcode ("push", "acc");
8473 freeAsmop (right, NULL, ic, FALSE);
8474 /* now assign DPTR to result */
8475 aopOp (result, ic, FALSE);
8476 size = AOP_SIZE (result);
8479 emitcode ("pop", "acc");
8480 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8482 freeAsmop (result, NULL, ic, FALSE);
8486 /*-----------------------------------------------------------------*/
8487 /* genAssign - generate code for assignment */
8488 /*-----------------------------------------------------------------*/
8490 genAssign (iCode * ic)
8492 operand *result, *right;
8494 unsigned long lit = 0L;
8496 D(emitcode("; genAssign",""));
8498 result = IC_RESULT (ic);
8499 right = IC_RIGHT (ic);
8501 /* if they are the same */
8502 if (operandsEqu (result, right) &&
8503 !isOperandVolatile (result, FALSE) &&
8504 !isOperandVolatile (right, FALSE))
8507 aopOp (right, ic, FALSE);
8509 /* special case both in far space */
8510 if (AOP_TYPE (right) == AOP_DPTR &&
8511 IS_TRUE_SYMOP (result) &&
8512 isOperandInFarSpace (result))
8515 genFarFarAssign (result, right, ic);
8519 aopOp (result, ic, TRUE);
8521 /* if they are the same registers */
8522 if (sameRegs (AOP (right), AOP (result)) &&
8523 !isOperandVolatile (result, FALSE) &&
8524 !isOperandVolatile (right, FALSE))
8527 /* if the result is a bit */
8528 if (AOP_TYPE (result) == AOP_CRY)
8531 /* if the right size is a literal then
8532 we know what the value is */
8533 if (AOP_TYPE (right) == AOP_LIT)
8535 if (((int) operandLitValue (right)))
8536 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8538 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8542 /* the right is also a bit variable */
8543 if (AOP_TYPE (right) == AOP_CRY)
8545 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8546 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8552 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8556 /* bit variables done */
8558 size = AOP_SIZE (result);
8560 if (AOP_TYPE (right) == AOP_LIT)
8561 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8563 (AOP_TYPE (result) != AOP_REG) &&
8564 (AOP_TYPE (right) == AOP_LIT) &&
8565 !IS_FLOAT (operandType (right)) &&
8568 emitcode ("clr", "a");
8571 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8572 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8574 aopPut (AOP (result),
8575 aopGet (AOP (right), size, FALSE, FALSE),
8577 isOperandVolatile (result, FALSE));
8584 aopPut (AOP (result),
8585 aopGet (AOP (right), offset, FALSE, FALSE),
8587 isOperandVolatile (result, FALSE));
8593 freeAsmop (right, NULL, ic, TRUE);
8594 freeAsmop (result, NULL, ic, TRUE);
8597 /*-----------------------------------------------------------------*/
8598 /* genJumpTab - genrates code for jump table */
8599 /*-----------------------------------------------------------------*/
8601 genJumpTab (iCode * ic)
8606 D(emitcode ("; genJumpTab",""));
8608 aopOp (IC_JTCOND (ic), ic, FALSE);
8609 /* get the condition into accumulator */
8610 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8612 /* multiply by three */
8613 emitcode ("add", "a,acc");
8614 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8615 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8617 jtab = newiTempLabel (NULL);
8618 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8619 emitcode ("jmp", "@a+dptr");
8620 emitcode ("", "%05d$:", jtab->key + 100);
8621 /* now generate the jump labels */
8622 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8623 jtab = setNextItem (IC_JTLABELS (ic)))
8624 emitcode ("ljmp", "%05d$", jtab->key + 100);
8628 /*-----------------------------------------------------------------*/
8629 /* genCast - gen code for casting */
8630 /*-----------------------------------------------------------------*/
8632 genCast (iCode * ic)
8634 operand *result = IC_RESULT (ic);
8635 sym_link *ctype = operandType (IC_LEFT (ic));
8636 sym_link *rtype = operandType (IC_RIGHT (ic));
8637 operand *right = IC_RIGHT (ic);
8640 D(emitcode("; genCast",""));
8642 /* if they are equivalent then do nothing */
8643 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8646 aopOp (right, ic, FALSE);
8647 aopOp (result, ic, FALSE);
8649 /* if the result is a bit (and not a bitfield) */
8650 // if (AOP_TYPE (result) == AOP_CRY)
8651 if (IS_BITVAR (OP_SYMBOL (result)->type)
8652 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8654 /* if the right size is a literal then
8655 we know what the value is */
8656 if (AOP_TYPE (right) == AOP_LIT)
8658 if (((int) operandLitValue (right)))
8659 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8661 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8666 /* the right is also a bit variable */
8667 if (AOP_TYPE (right) == AOP_CRY)
8669 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8670 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8676 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8681 /* if they are the same size : or less */
8682 if (AOP_SIZE (result) <= AOP_SIZE (right))
8685 /* if they are in the same place */
8686 if (sameRegs (AOP (right), AOP (result)))
8689 /* if they in different places then copy */
8690 size = AOP_SIZE (result);
8694 aopPut (AOP (result),
8695 aopGet (AOP (right), offset, FALSE, FALSE),
8697 isOperandVolatile (result, FALSE));
8704 /* if the result is of type pointer */
8709 sym_link *type = operandType (right);
8710 sym_link *etype = getSpec (type);
8712 /* pointer to generic pointer */
8713 if (IS_GENPTR (ctype))
8716 p_type = DCL_TYPE (type);
8719 if (SPEC_SCLS(etype)==S_REGISTER) {
8720 // let's assume it is a generic pointer
8723 /* we have to go by the storage class */
8724 p_type = PTR_TYPE (SPEC_OCLS (etype));
8728 /* the first two bytes are known */
8729 size = GPTRSIZE - 1;
8733 aopPut (AOP (result),
8734 aopGet (AOP (right), offset, FALSE, FALSE),
8736 isOperandVolatile (result, FALSE));
8739 /* the last byte depending on type */
8741 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8746 // pointerTypeToGPByte will have bitched.
8750 sprintf(gpValStr, "#0x%d", gpVal);
8751 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8756 /* just copy the pointers */
8757 size = AOP_SIZE (result);
8761 aopPut (AOP (result),
8762 aopGet (AOP (right), offset, FALSE, FALSE),
8764 isOperandVolatile (result, FALSE));
8770 /* so we now know that the size of destination is greater
8771 than the size of the source */
8772 /* we move to result for the size of source */
8773 size = AOP_SIZE (right);
8777 aopPut (AOP (result),
8778 aopGet (AOP (right), offset, FALSE, FALSE),
8780 isOperandVolatile (result, FALSE));
8784 /* now depending on the sign of the source && destination */
8785 size = AOP_SIZE (result) - AOP_SIZE (right);
8786 /* if unsigned or not an integral type */
8787 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8790 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8794 /* we need to extend the sign :{ */
8795 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8798 emitcode ("rlc", "a");
8799 emitcode ("subb", "a,acc");
8801 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8804 /* we are done hurray !!!! */
8807 freeAsmop (right, NULL, ic, TRUE);
8808 freeAsmop (result, NULL, ic, TRUE);
8812 /*-----------------------------------------------------------------*/
8813 /* genDjnz - generate decrement & jump if not zero instrucion */
8814 /*-----------------------------------------------------------------*/
8816 genDjnz (iCode * ic, iCode * ifx)
8822 D(emitcode ("; genDjnz",""));
8824 /* if the if condition has a false label
8825 then we cannot save */
8829 /* if the minus is not of the form
8831 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8832 !IS_OP_LITERAL (IC_RIGHT (ic)))
8835 if (operandLitValue (IC_RIGHT (ic)) != 1)
8838 /* if the size of this greater than one then no
8840 if (getSize (operandType (IC_RESULT (ic))) > 1)
8843 /* otherwise we can save BIG */
8844 lbl = newiTempLabel (NULL);
8845 lbl1 = newiTempLabel (NULL);
8847 aopOp (IC_RESULT (ic), ic, FALSE);
8849 if (AOP_NEEDSACC(IC_RESULT(ic)))
8851 /* If the result is accessed indirectly via
8852 * the accumulator, we must explicitly write
8853 * it back after the decrement.
8855 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8857 if (strcmp(rByte, "a"))
8859 /* Something is hopelessly wrong */
8860 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8861 __FILE__, __LINE__);
8862 /* We can just give up; the generated code will be inefficient,
8865 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8868 emitcode ("dec", "%s", rByte);
8869 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8870 emitcode ("jnz", "%05d$", lbl->key + 100);
8872 else if (IS_AOP_PREG (IC_RESULT (ic)))
8874 emitcode ("dec", "%s",
8875 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8876 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8877 emitcode ("jnz", "%05d$", lbl->key + 100);
8881 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8884 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8885 emitcode ("", "%05d$:", lbl->key + 100);
8886 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8887 emitcode ("", "%05d$:", lbl1->key + 100);
8889 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8894 /*-----------------------------------------------------------------*/
8895 /* genReceive - generate code for a receive iCode */
8896 /*-----------------------------------------------------------------*/
8898 genReceive (iCode * ic)
8900 int size = getSize (operandType (IC_RESULT (ic)));
8902 D(emitcode ("; genReceive",""));
8904 if (ic->argreg == 1) { /* first parameter */
8905 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8906 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8907 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8909 offset = fReturnSizeMCS51 - size;
8911 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8912 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8915 aopOp (IC_RESULT (ic), ic, FALSE);
8916 size = AOP_SIZE (IC_RESULT (ic));
8919 emitcode ("pop", "acc");
8920 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8925 aopOp (IC_RESULT (ic), ic, FALSE);
8927 assignResultValue (IC_RESULT (ic));
8929 } else { /* second receive onwards */
8931 aopOp (IC_RESULT (ic), ic, FALSE);
8932 rb1off = ic->argreg;
8934 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8937 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8940 /*-----------------------------------------------------------------*/
8941 /* genDummyRead - generate code for dummy read of volatiles */
8942 /*-----------------------------------------------------------------*/
8944 genDummyRead (iCode * ic)
8949 D(emitcode("; genDummyRead",""));
8951 right = IC_RIGHT (ic);
8953 aopOp (right, ic, FALSE);
8955 /* if the result is a bit */
8956 if (AOP_TYPE (right) == AOP_CRY)
8958 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8962 /* bit variables done */
8964 size = AOP_SIZE (right);
8968 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
8973 freeAsmop (right, NULL, ic, TRUE);
8976 /*-----------------------------------------------------------------*/
8977 /* gen51Code - generate code for 8051 based controllers */
8978 /*-----------------------------------------------------------------*/
8980 gen51Code (iCode * lic)
8985 lineHead = lineCurr = NULL;
8987 /* print the allocation information */
8988 if (allocInfo && currFunc)
8989 printAllocInfo (currFunc, codeOutFile);
8990 /* if debug information required */
8991 if (options.debug && currFunc)
8993 debugFile->writeFunction(currFunc);
8995 if (IS_STATIC (currFunc->etype))
8996 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8998 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9001 /* stack pointer name */
9002 if (options.useXstack)
9008 for (ic = lic; ic; ic = ic->next)
9010 _G.current_iCode = ic;
9012 if (ic->lineno && cln != ic->lineno)
9017 emitcode ("", "C$%s$%d$%d$%d ==.",
9018 FileBaseName (ic->filename), ic->lineno,
9019 ic->level, ic->block);
9022 if (!options.noCcodeInAsm) {
9023 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9024 printCLine(ic->filename, ic->lineno));
9028 if (options.iCodeInAsm) {
9032 for (i=0; i<8; i++) {
9033 sprintf (®sInUse[i],
9034 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9037 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9039 /* if the result is marked as
9040 spilt and rematerializable or code for
9041 this has already been generated then
9043 if (resultRemat (ic) || ic->generated)
9046 /* depending on the operation */
9066 /* IPOP happens only when trying to restore a
9067 spilt live range, if there is an ifx statement
9068 following this pop then the if statement might
9069 be using some of the registers being popped which
9070 would destory the contents of the register so
9071 we need to check for this condition and handle it */
9073 ic->next->op == IFX &&
9074 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9075 genIfx (ic->next, ic);
9093 genEndFunction (ic);
9113 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9130 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9134 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9141 /* note these two are xlated by algebraic equivalence
9142 during parsing SDCC.y */
9143 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9144 "got '>=' or '<=' shouldn't have come here");
9148 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9160 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9164 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9168 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9195 case GET_VALUE_AT_ADDRESS:
9196 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9200 if (POINTER_SET (ic))
9201 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9227 addSet (&_G.sendSet, ic);
9230 case DUMMY_READ_VOLATILE:
9239 _G.current_iCode = NULL;
9241 /* now we are ready to call the
9242 peep hole optimizer */
9243 if (!options.nopeep)
9244 peepHole (&lineHead);
9246 /* now do the actual printing */
9247 printLine (lineHead, codeOutFile);