1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
80 static char *rb1regs[] = {
81 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
84 extern int mcs51_ptrRegReq;
85 extern int mcs51_nRegs;
86 extern FILE *codeOutFile;
87 static void saveRBank (int, iCode *, bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
93 #define CLRC emitcode("clr","c")
94 #define SETC emitcode("setb","c")
96 static lineNode *lineHead = NULL;
97 static lineNode *lineCurr = NULL;
99 static unsigned char SLMask[] =
100 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
101 0xE0, 0xC0, 0x80, 0x00};
102 static unsigned char SRMask[] =
103 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
104 0x07, 0x03, 0x01, 0x00};
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple */
113 /*-----------------------------------------------------------------*/
115 emitcode (char *inst, const char *fmt,...)
118 char lb[INITIAL_INLINEASM];
126 sprintf (lb, "%s\t", inst);
128 sprintf (lb, "%s", inst);
129 vsprintf (lb + (strlen (lb)), fmt, ap);
132 vsprintf (lb, fmt, ap);
134 while (isspace (*lbp))
138 lineCurr = (lineCurr ?
139 connectLine (lineCurr, newLineNode (lb)) :
140 (lineHead = newLineNode (lb)));
141 lineCurr->isInline = _G.inLine;
142 lineCurr->isDebug = _G.debugLine;
143 lineCurr->ic = _G.current_iCode;
144 lineCurr->isComment = (*lbp==';');
148 /*-----------------------------------------------------------------*/
149 /* mova - moves specified value into accumulator */
150 /*-----------------------------------------------------------------*/
154 /* do some early peephole optimization */
155 if (!strcmp(x, "a") || !strcmp(x, "acc"))
158 emitcode("mov","a,%s", x);
161 /*-----------------------------------------------------------------*/
162 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
163 /*-----------------------------------------------------------------*/
165 getFreePtr (iCode * ic, asmop ** aopp, bool result)
167 bool r0iu = FALSE, r1iu = FALSE;
168 bool r0ou = FALSE, r1ou = FALSE;
170 /* the logic: if r0 & r1 used in the instruction
171 then we are in trouble otherwise */
173 /* first check if r0 & r1 are used by this
174 instruction, in which case we are in trouble */
175 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
176 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
181 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
182 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
184 /* if no usage of r0 then return it */
187 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
188 (*aopp)->type = AOP_R0;
190 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
193 /* if no usage of r1 then return it */
196 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
197 (*aopp)->type = AOP_R1;
199 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
202 /* now we know they both have usage */
203 /* if r0 not used in this instruction */
206 /* push it if not already pushed */
209 emitcode ("push", "%s",
210 mcs51_regWithIdx (R0_IDX)->dname);
214 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
215 (*aopp)->type = AOP_R0;
217 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
220 /* if r1 not used then */
224 /* push it if not already pushed */
227 emitcode ("push", "%s",
228 mcs51_regWithIdx (R1_IDX)->dname);
232 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
233 (*aopp)->type = AOP_R1;
234 return mcs51_regWithIdx (R1_IDX);
237 /* I said end of world, but not quite end of world yet */
239 /* we can push it on the stack */
240 (*aopp)->type = AOP_STK;
243 /* in the case that result AND left AND right needs a pointer reg
244 we can safely use the result's */
245 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
246 (*aopp)->type = AOP_R0;
247 return mcs51_regWithIdx (R0_IDX);
249 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
250 (*aopp)->type = AOP_R1;
251 return mcs51_regWithIdx (R1_IDX);
255 /* now this is REALLY the end of the world */
256 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
257 "getFreePtr should never reach here");
261 /*-----------------------------------------------------------------*/
262 /* newAsmop - creates a new asmOp */
263 /*-----------------------------------------------------------------*/
265 newAsmop (short type)
269 aop = Safe_calloc (1, sizeof (asmop));
274 /*-----------------------------------------------------------------*/
275 /* pointerCode - returns the code for a pointer type */
276 /*-----------------------------------------------------------------*/
278 pointerCode (sym_link * etype)
281 return PTR_TYPE (SPEC_OCLS (etype));
286 /*-----------------------------------------------------------------*/
287 /* leftRightUseAcc - returns size of accumulator use by operands */
288 /*-----------------------------------------------------------------*/
290 leftRightUseAcc(iCode *ic)
299 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
300 "null iCode pointer");
307 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
310 size = getSize (OP_SYMBOL (op)->type);
315 else if (ic->op == JUMPTABLE)
318 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
321 size = getSize (OP_SYMBOL (op)->type);
329 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
332 size = getSize (OP_SYMBOL (op)->type);
337 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
340 size = getSize (OP_SYMBOL (op)->type);
353 /*-----------------------------------------------------------------*/
354 /* aopForSym - for a true symbol */
355 /*-----------------------------------------------------------------*/
357 aopForSym (iCode * ic, symbol * sym, bool result)
362 wassertl (ic != NULL, "Got a null iCode");
363 wassertl (sym != NULL, "Got a null symbol");
365 space = SPEC_OCLS (sym->etype);
367 /* if already has one */
371 /* assign depending on the storage class */
372 /* if it is on the stack or indirectly addressable */
373 /* space we need to assign either r0 or r1 to it */
374 if (sym->onStack || sym->iaccess)
376 sym->aop = aop = newAsmop (0);
377 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
378 aop->size = getSize (sym->type);
380 /* now assign the address of the variable to
381 the pointer register */
382 if (aop->type != AOP_STK)
387 if (_G.accInUse || leftRightUseAcc (ic))
388 emitcode ("push", "acc");
390 emitcode ("mov", "a,_bp");
391 emitcode ("add", "a,#0x%02x",
393 ((char) (sym->stack - _G.nRegsSaved)) :
394 ((char) sym->stack)) & 0xff);
395 emitcode ("mov", "%s,a",
396 aop->aopu.aop_ptr->name);
398 if (_G.accInUse || leftRightUseAcc (ic))
399 emitcode ("pop", "acc");
402 emitcode ("mov", "%s,#%s",
403 aop->aopu.aop_ptr->name,
405 aop->paged = space->paged;
408 aop->aopu.aop_stk = sym->stack;
412 /* if in bit space */
413 if (IN_BITSPACE (space))
415 sym->aop = aop = newAsmop (AOP_CRY);
416 aop->aopu.aop_dir = sym->rname;
417 aop->size = getSize (sym->type);
420 /* if it is in direct space */
421 if (IN_DIRSPACE (space))
423 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
424 //printTypeChainRaw(sym->type, NULL);
425 //printf("space = %s\n", space ? space->sname : "NULL");
426 sym->aop = aop = newAsmop (AOP_DIR);
427 aop->aopu.aop_dir = sym->rname;
428 aop->size = getSize (sym->type);
432 /* special case for a function */
433 if (IS_FUNC (sym->type))
435 sym->aop = aop = newAsmop (AOP_IMMD);
436 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
437 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
438 aop->size = FPTRSIZE;
442 /* only remaining is far space */
443 /* in which case DPTR gets the address */
444 sym->aop = aop = newAsmop (AOP_DPTR);
445 emitcode ("mov", "dptr,#%s", sym->rname);
446 aop->size = getSize (sym->type);
448 /* if it is in code space */
449 if (IN_CODESPACE (space))
455 /*-----------------------------------------------------------------*/
456 /* aopForRemat - rematerialzes an object */
457 /*-----------------------------------------------------------------*/
459 aopForRemat (symbol * sym)
461 iCode *ic = sym->rematiCode;
462 asmop *aop = newAsmop (AOP_IMMD);
469 val += (int) operandLitValue (IC_RIGHT (ic));
470 else if (ic->op == '-')
471 val -= (int) operandLitValue (IC_RIGHT (ic));
472 else if (IS_CAST_ICODE(ic)) {
473 sym_link *from_type = operandType(IC_RIGHT(ic));
474 aop->aopu.aop_immd.from_cast_remat = 1;
475 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
476 ptr_type = DCL_TYPE(from_type);
477 if (ptr_type == IPOINTER) {
484 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
488 sprintf (buffer, "(%s %c 0x%04x)",
489 OP_SYMBOL (IC_LEFT (ic))->rname,
490 val >= 0 ? '+' : '-',
493 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
495 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
496 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
497 /* set immd2 field if required */
498 if (aop->aopu.aop_immd.from_cast_remat) {
499 sprintf(buffer,"#0x%02x",ptr_type);
500 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
501 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
507 /*-----------------------------------------------------------------*/
508 /* regsInCommon - two operands have some registers in common */
509 /*-----------------------------------------------------------------*/
511 regsInCommon (operand * op1, operand * op2)
516 /* if they have registers in common */
517 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
520 sym1 = OP_SYMBOL (op1);
521 sym2 = OP_SYMBOL (op2);
523 if (sym1->nRegs == 0 || sym2->nRegs == 0)
526 for (i = 0; i < sym1->nRegs; i++)
532 for (j = 0; j < sym2->nRegs; j++)
537 if (sym2->regs[j] == sym1->regs[i])
545 /*-----------------------------------------------------------------*/
546 /* operandsEqu - equivalent */
547 /*-----------------------------------------------------------------*/
549 operandsEqu (operand * op1, operand * op2)
553 /* if they not symbols */
554 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
557 sym1 = OP_SYMBOL (op1);
558 sym2 = OP_SYMBOL (op2);
560 /* if both are itemps & one is spilt
561 and the other is not then false */
562 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
563 sym1->isspilt != sym2->isspilt)
566 /* if they are the same */
570 if (strcmp (sym1->rname, sym2->rname) == 0)
574 /* if left is a tmp & right is not */
575 if (IS_ITEMP (op1) &&
578 (sym1->usl.spillLoc == sym2))
581 if (IS_ITEMP (op2) &&
585 (sym2->usl.spillLoc == sym1))
591 /*-----------------------------------------------------------------*/
592 /* sameRegs - two asmops have the same registers */
593 /*-----------------------------------------------------------------*/
595 sameRegs (asmop * aop1, asmop * aop2)
602 if (aop1->type != AOP_REG ||
603 aop2->type != AOP_REG)
606 if (aop1->size != aop2->size)
609 for (i = 0; i < aop1->size; i++)
610 if (aop1->aopu.aop_reg[i] !=
611 aop2->aopu.aop_reg[i])
617 /*-----------------------------------------------------------------*/
618 /* aopOp - allocates an asmop for an operand : */
619 /*-----------------------------------------------------------------*/
621 aopOp (operand * op, iCode * ic, bool result)
630 /* if this a literal */
631 if (IS_OP_LITERAL (op))
633 op->aop = aop = newAsmop (AOP_LIT);
634 aop->aopu.aop_lit = op->operand.valOperand;
635 aop->size = getSize (operandType (op));
639 /* if already has a asmop then continue */
643 /* if the underlying symbol has a aop */
644 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
646 op->aop = OP_SYMBOL (op)->aop;
650 /* if this is a true symbol */
651 if (IS_TRUE_SYMOP (op))
653 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
657 /* this is a temporary : this has
663 e) can be a return use only */
665 sym = OP_SYMBOL (op);
667 /* if the type is a conditional */
668 if (sym->regType == REG_CND)
670 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
675 /* if it is spilt then two situations
677 b) has a spill location */
678 if (sym->isspilt || sym->nRegs == 0)
681 /* rematerialize it NOW */
684 sym->aop = op->aop = aop =
686 aop->size = getSize (sym->type);
693 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
694 aop->size = getSize (sym->type);
695 for (i = 0; i < 2; i++)
696 aop->aopu.aop_str[i] = accUse[i];
704 aop = op->aop = sym->aop = newAsmop (AOP_STR);
705 aop->size = getSize (sym->type);
706 for (i = 0; i < fReturnSizeMCS51; i++)
707 aop->aopu.aop_str[i] = fReturn[i];
711 if (sym->usl.spillLoc)
713 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
715 /* force a new aop if sizes differ */
716 sym->usl.spillLoc->aop = NULL;
718 sym->aop = op->aop = aop =
719 aopForSym (ic, sym->usl.spillLoc, result);
720 aop->size = getSize (sym->type);
724 /* else must be a dummy iTemp */
725 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
726 aop->size = getSize (sym->type);
730 /* must be in a register */
731 sym->aop = op->aop = aop = newAsmop (AOP_REG);
732 aop->size = sym->nRegs;
733 for (i = 0; i < sym->nRegs; i++)
734 aop->aopu.aop_reg[i] = sym->regs[i];
737 /*-----------------------------------------------------------------*/
738 /* freeAsmop - free up the asmop given to an operand */
739 /*----------------------------------------------------------------*/
741 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
758 /* depending on the asmop type only three cases need work AOP_RO
759 , AOP_R1 && AOP_STK */
767 emitcode ("pop", "ar0");
771 bitVectUnSetBit (ic->rUsed, R0_IDX);
779 emitcode ("pop", "ar1");
783 bitVectUnSetBit (ic->rUsed, R1_IDX);
789 int stk = aop->aopu.aop_stk + aop->size - 1;
790 bitVectUnSetBit (ic->rUsed, R0_IDX);
791 bitVectUnSetBit (ic->rUsed, R1_IDX);
793 getFreePtr (ic, &aop, FALSE);
797 emitcode ("mov", "a,_bp");
798 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
799 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
803 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
808 emitcode ("pop", "acc");
809 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
812 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
815 freeAsmop (op, NULL, ic, TRUE);
818 emitcode ("pop", "ar1");
824 emitcode ("pop", "ar0");
831 /* all other cases just dealloc */
837 OP_SYMBOL (op)->aop = NULL;
838 /* if the symbol has a spill */
840 SPIL_LOC (op)->aop = NULL;
845 /*-----------------------------------------------------------------*/
846 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
847 /* clobber the accumulator */
848 /*-----------------------------------------------------------------*/
850 aopGetUsesAcc (asmop *aop, int offset)
852 if (offset > (aop->size - 1))
870 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
879 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
885 /* Error case --- will have been caught already */
891 /*-----------------------------------------------------------------*/
892 /* aopGet - for fetching value of the aop */
893 /*-----------------------------------------------------------------*/
895 aopGet (asmop * aop, int offset, bool bit16, bool dname)
900 /* offset is greater than
902 if (offset > (aop->size - 1) &&
903 aop->type != AOP_LIT)
906 /* depending on type */
914 /* if we need to increment it */
915 while (offset > aop->coff)
917 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
921 while (offset < aop->coff)
923 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
930 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
931 return (dname ? "acc" : "a");
933 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
934 rs = Safe_calloc (1, strlen (s) + 1);
939 if (aop->code && aop->coff==0 && offset>=1) {
940 emitcode ("mov", "a,#0x%02x", offset);
941 emitcode ("movc", "a,@a+dptr");
942 return (dname ? "acc" : "a");
945 while (offset > aop->coff)
947 emitcode ("inc", "dptr");
951 while (offset < aop->coff)
953 emitcode ("lcall", "__decdptr");
960 emitcode ("clr", "a");
961 emitcode ("movc", "a,@a+dptr");
965 emitcode ("movx", "a,@dptr");
967 return (dname ? "acc" : "a");
971 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
972 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
974 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
976 sprintf (s, "#(%s >> %d)",
977 aop->aopu.aop_immd.aop_immd1,
981 aop->aopu.aop_immd.aop_immd1);
982 rs = Safe_calloc (1, strlen (s) + 1);
988 sprintf (s, "(%s + %d)",
992 sprintf (s, "%s", aop->aopu.aop_dir);
993 rs = Safe_calloc (1, strlen (s) + 1);
999 return aop->aopu.aop_reg[offset]->dname;
1001 return aop->aopu.aop_reg[offset]->name;
1004 emitcode ("clr", "a");
1005 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1006 emitcode ("rlc", "a");
1007 return (dname ? "acc" : "a");
1010 if (!offset && dname)
1012 return aop->aopu.aop_str[offset];
1015 return aopLiteral (aop->aopu.aop_lit, offset);
1019 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1023 return aop->aopu.aop_str[offset];
1027 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1028 "aopget got unsupported aop->type");
1031 /*-----------------------------------------------------------------*/
1032 /* aopPut - puts a string for a aop */
1033 /*-----------------------------------------------------------------*/
1035 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1039 if (aop->size && offset > (aop->size - 1))
1041 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1042 "aopPut got offset > aop->size");
1046 /* will assign value to value */
1047 /* depending on where it is ofcourse */
1051 MOVA (s); /* read s in case it was volatile */
1056 sprintf (d, "(%s + %d)",
1057 aop->aopu.aop_dir, offset);
1059 sprintf (d, "%s", aop->aopu.aop_dir);
1061 if (strcmp (d, s) ||
1063 emitcode ("mov", "%s,%s", d, s);
1068 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1069 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1072 strcmp (s, "r0") == 0 ||
1073 strcmp (s, "r1") == 0 ||
1074 strcmp (s, "r2") == 0 ||
1075 strcmp (s, "r3") == 0 ||
1076 strcmp (s, "r4") == 0 ||
1077 strcmp (s, "r5") == 0 ||
1078 strcmp (s, "r6") == 0 ||
1079 strcmp (s, "r7") == 0)
1080 emitcode ("mov", "%s,%s",
1081 aop->aopu.aop_reg[offset]->dname, s);
1083 emitcode ("mov", "%s,%s",
1084 aop->aopu.aop_reg[offset]->name, s);
1091 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1092 "aopPut writing to code space");
1096 while (offset > aop->coff)
1099 emitcode ("inc", "dptr");
1102 while (offset < aop->coff)
1105 emitcode ("lcall", "__decdptr");
1110 /* if not in accumulater */
1113 emitcode ("movx", "@dptr,a");
1118 while (offset > aop->coff)
1121 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1123 while (offset < aop->coff)
1126 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1133 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1139 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1141 else if (strcmp (s, "r0") == 0 ||
1142 strcmp (s, "r1") == 0 ||
1143 strcmp (s, "r2") == 0 ||
1144 strcmp (s, "r3") == 0 ||
1145 strcmp (s, "r4") == 0 ||
1146 strcmp (s, "r5") == 0 ||
1147 strcmp (s, "r6") == 0 ||
1148 strcmp (s, "r7") == 0)
1151 sprintf (buffer, "a%s", s);
1152 emitcode ("mov", "@%s,%s",
1153 aop->aopu.aop_ptr->name, buffer);
1156 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1161 if (strcmp (s, "a") == 0)
1162 emitcode ("push", "acc");
1166 emitcode ("push", "acc");
1168 emitcode ("push", s);
1174 /* if bit variable */
1175 if (!aop->aopu.aop_dir)
1177 emitcode ("clr", "a");
1178 emitcode ("rlc", "a");
1183 emitcode ("clr", "%s", aop->aopu.aop_dir);
1185 emitcode ("setb", "%s", aop->aopu.aop_dir);
1186 else if (!strcmp (s, "c"))
1187 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1190 if (strcmp (s, "a"))
1195 /* set C, if a >= 1 */
1196 emitcode ("add", "a,#0xff");
1197 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1205 if (strcmp (aop->aopu.aop_str[offset], s) ||
1207 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1212 if (!offset && (strcmp (s, "acc") == 0) &&
1216 if (strcmp (aop->aopu.aop_str[offset], s) &&
1218 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1222 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1223 "aopPut got unsupported aop->type");
1231 /*-----------------------------------------------------------------*/
1232 /* pointToEnd :- points to the last byte of the operand */
1233 /*-----------------------------------------------------------------*/
1235 pointToEnd (asmop * aop)
1241 aop->coff = count = (aop->size - 1);
1247 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1251 emitcode ("inc", "dptr");
1258 /*-----------------------------------------------------------------*/
1259 /* reAdjustPreg - points a register back to where it should */
1260 /*-----------------------------------------------------------------*/
1262 reAdjustPreg (asmop * aop)
1264 if ((aop->coff==0) || aop->size <= 1)
1272 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1277 emitcode ("lcall", "__decdptr");
1284 #define AOP(op) op->aop
1285 #define AOP_TYPE(op) AOP(op)->type
1286 #define AOP_SIZE(op) AOP(op)->size
1287 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1288 AOP_TYPE(x) == AOP_R0))
1290 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1291 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1293 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1294 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1295 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1298 /*-----------------------------------------------------------------*/
1299 /* opIsGptr: returns non-zero if the passed operand is */
1300 /* a generic pointer type. */
1301 /*-----------------------------------------------------------------*/
1303 opIsGptr (operand * op)
1305 sym_link *type = operandType (op);
1307 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1314 /*-----------------------------------------------------------------*/
1315 /* getDataSize - get the operand data size */
1316 /*-----------------------------------------------------------------*/
1318 getDataSize (operand * op)
1321 size = AOP_SIZE (op);
1322 if (size == GPTRSIZE)
1324 sym_link *type = operandType (op);
1325 if (IS_GENPTR (type))
1327 /* generic pointer; arithmetic operations
1328 * should ignore the high byte (pointer type).
1336 /*-----------------------------------------------------------------*/
1337 /* outAcc - output Acc */
1338 /*-----------------------------------------------------------------*/
1340 outAcc (operand * result)
1343 size = getDataSize (result);
1346 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1349 /* unsigned or positive */
1352 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1357 /*-----------------------------------------------------------------*/
1358 /* outBitC - output a bit C */
1359 /*-----------------------------------------------------------------*/
1361 outBitC (operand * result)
1363 /* if the result is bit */
1364 if (AOP_TYPE (result) == AOP_CRY)
1365 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1368 emitcode ("clr", "a");
1369 emitcode ("rlc", "a");
1374 /*-----------------------------------------------------------------*/
1375 /* toBoolean - emit code for orl a,operator(sizeop) */
1376 /*-----------------------------------------------------------------*/
1378 toBoolean (operand * oper)
1380 int size = AOP_SIZE (oper) - 1;
1382 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1384 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1388 /*-----------------------------------------------------------------*/
1389 /* genNot - generate code for ! operation */
1390 /*-----------------------------------------------------------------*/
1396 D(emitcode ("; genNot",""));
1398 /* assign asmOps to operand & result */
1399 aopOp (IC_LEFT (ic), ic, FALSE);
1400 aopOp (IC_RESULT (ic), ic, TRUE);
1402 /* if in bit space then a special case */
1403 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1405 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1406 emitcode ("cpl", "c");
1407 outBitC (IC_RESULT (ic));
1411 toBoolean (IC_LEFT (ic));
1413 tlbl = newiTempLabel (NULL);
1414 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1415 emitcode ("", "%05d$:", tlbl->key + 100);
1416 outBitC (IC_RESULT (ic));
1419 /* release the aops */
1420 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1421 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1425 /*-----------------------------------------------------------------*/
1426 /* genCpl - generate code for complement */
1427 /*-----------------------------------------------------------------*/
1435 D(emitcode ("; genCpl",""));
1437 /* assign asmOps to operand & result */
1438 aopOp (IC_LEFT (ic), ic, FALSE);
1439 aopOp (IC_RESULT (ic), ic, TRUE);
1441 /* special case if in bit space */
1442 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1444 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1446 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1447 emitcode ("cpl", "c");
1448 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1452 tlbl=newiTempLabel(NULL);
1453 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1454 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1455 IS_AOP_PREG (IC_LEFT (ic)))
1457 emitcode ("cjne", "%s,#0x01,%05d$",
1458 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1463 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1465 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1467 emitcode ("", "%05d$:", tlbl->key + 100);
1468 outBitC (IC_RESULT(ic));
1472 size = AOP_SIZE (IC_RESULT (ic));
1475 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1477 emitcode ("cpl", "a");
1478 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1483 /* release the aops */
1484 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1485 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1488 /*-----------------------------------------------------------------*/
1489 /* genUminusFloat - unary minus for floating points */
1490 /*-----------------------------------------------------------------*/
1492 genUminusFloat (operand * op, operand * result)
1494 int size, offset = 0;
1497 D(emitcode ("; genUminusFloat",""));
1499 /* for this we just copy and then flip the bit */
1501 size = AOP_SIZE (op) - 1;
1505 aopPut (AOP (result),
1506 aopGet (AOP (op), offset, FALSE, FALSE),
1508 isOperandVolatile (result, FALSE));
1512 l = aopGet (AOP (op), offset, FALSE, FALSE);
1516 emitcode ("cpl", "acc.7");
1517 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1520 /*-----------------------------------------------------------------*/
1521 /* genUminus - unary minus code generation */
1522 /*-----------------------------------------------------------------*/
1524 genUminus (iCode * ic)
1527 sym_link *optype, *rtype;
1530 D(emitcode ("; genUminus",""));
1533 aopOp (IC_LEFT (ic), ic, FALSE);
1534 aopOp (IC_RESULT (ic), ic, TRUE);
1536 /* if both in bit space then special
1538 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1539 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1542 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1543 emitcode ("cpl", "c");
1544 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1548 optype = operandType (IC_LEFT (ic));
1549 rtype = operandType (IC_RESULT (ic));
1551 /* if float then do float stuff */
1552 if (IS_FLOAT (optype))
1554 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1558 /* otherwise subtract from zero */
1559 size = AOP_SIZE (IC_LEFT (ic));
1564 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1565 if (!strcmp (l, "a"))
1569 emitcode ("cpl", "a");
1570 emitcode ("addc", "a,#0");
1576 emitcode ("clr", "a");
1577 emitcode ("subb", "a,%s", l);
1579 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1582 /* if any remaining bytes in the result */
1583 /* we just need to propagate the sign */
1584 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1586 emitcode ("rlc", "a");
1587 emitcode ("subb", "a,acc");
1589 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1593 /* release the aops */
1594 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1595 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1598 /*-----------------------------------------------------------------*/
1599 /* saveRegisters - will look for a call and save the registers */
1600 /*-----------------------------------------------------------------*/
1602 saveRegisters (iCode * lic)
1609 for (ic = lic; ic; ic = ic->next)
1610 if (ic->op == CALL || ic->op == PCALL)
1615 fprintf (stderr, "found parameter push with no function call\n");
1619 /* if the registers have been saved already or don't need to be then
1623 if (IS_SYMOP(IC_LEFT(ic)) &&
1624 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1625 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1628 /* safe the registers in use at this time but skip the
1629 ones for the result */
1630 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1631 mcs51_rUmaskForOp (IC_RESULT(ic)));
1634 if (options.useXstack)
1636 if (bitVectBitValue (rsave, R0_IDX))
1637 emitcode ("mov", "b,r0");
1638 emitcode ("mov", "r0,%s", spname);
1639 for (i = 0; i < mcs51_nRegs; i++)
1641 if (bitVectBitValue (rsave, i))
1644 emitcode ("mov", "a,b");
1646 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1647 emitcode ("movx", "@r0,a");
1648 emitcode ("inc", "r0");
1651 emitcode ("mov", "%s,r0", spname);
1652 if (bitVectBitValue (rsave, R0_IDX))
1653 emitcode ("mov", "r0,b");
1656 for (i = 0; i < mcs51_nRegs; i++)
1658 if (bitVectBitValue (rsave, i))
1659 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1663 /*-----------------------------------------------------------------*/
1664 /* unsaveRegisters - pop the pushed registers */
1665 /*-----------------------------------------------------------------*/
1667 unsaveRegisters (iCode * ic)
1672 /* restore the registers in use at this time but skip the
1673 ones for the result */
1674 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1675 mcs51_rUmaskForOp (IC_RESULT(ic)));
1677 if (options.useXstack)
1679 emitcode ("mov", "r0,%s", spname);
1680 for (i = mcs51_nRegs; i >= 0; i--)
1682 if (bitVectBitValue (rsave, i))
1684 emitcode ("dec", "r0");
1685 emitcode ("movx", "a,@r0");
1687 emitcode ("mov", "b,a");
1689 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1693 emitcode ("mov", "%s,r0", spname);
1694 if (bitVectBitValue (rsave, R0_IDX))
1695 emitcode ("mov", "r0,b");
1698 for (i = mcs51_nRegs; i >= 0; i--)
1700 if (bitVectBitValue (rsave, i))
1701 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1707 /*-----------------------------------------------------------------*/
1709 /*-----------------------------------------------------------------*/
1711 pushSide (operand * oper, int size)
1716 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1717 if (AOP_TYPE (oper) != AOP_REG &&
1718 AOP_TYPE (oper) != AOP_DIR &&
1721 emitcode ("mov", "a,%s", l);
1722 emitcode ("push", "acc");
1725 emitcode ("push", "%s", l);
1729 /*-----------------------------------------------------------------*/
1730 /* assignResultValue - */
1731 /*-----------------------------------------------------------------*/
1733 assignResultValue (operand * oper)
1736 int size = AOP_SIZE (oper);
1739 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1745 /*-----------------------------------------------------------------*/
1746 /* genXpush - pushes onto the external stack */
1747 /*-----------------------------------------------------------------*/
1749 genXpush (iCode * ic)
1751 asmop *aop = newAsmop (0);
1753 int size, offset = 0;
1755 D(emitcode ("; genXpush",""));
1757 aopOp (IC_LEFT (ic), ic, FALSE);
1758 r = getFreePtr (ic, &aop, FALSE);
1761 emitcode ("mov", "%s,_spx", r->name);
1763 size = AOP_SIZE (IC_LEFT (ic));
1767 char *l = aopGet (AOP (IC_LEFT (ic)),
1768 offset++, FALSE, FALSE);
1770 emitcode ("movx", "@%s,a", r->name);
1771 emitcode ("inc", "%s", r->name);
1776 emitcode ("mov", "_spx,%s", r->name);
1778 freeAsmop (NULL, aop, ic, TRUE);
1779 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1782 /*-----------------------------------------------------------------*/
1783 /* genIpush - genrate code for pushing this gets a little complex */
1784 /*-----------------------------------------------------------------*/
1786 genIpush (iCode * ic)
1788 int size, offset = 0;
1791 D(emitcode ("; genIpush",""));
1793 /* if this is not a parm push : ie. it is spill push
1794 and spill push is always done on the local stack */
1798 /* and the item is spilt then do nothing */
1799 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1802 aopOp (IC_LEFT (ic), ic, FALSE);
1803 size = AOP_SIZE (IC_LEFT (ic));
1804 /* push it on the stack */
1807 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1813 emitcode ("push", "%s", l);
1818 /* this is a paramter push: in this case we call
1819 the routine to find the call and save those
1820 registers that need to be saved */
1823 /* if use external stack then call the external
1824 stack pushing routine */
1825 if (options.useXstack)
1831 /* then do the push */
1832 aopOp (IC_LEFT (ic), ic, FALSE);
1835 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1836 size = AOP_SIZE (IC_LEFT (ic));
1840 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1841 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1842 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1845 emitcode ("mov", "a,%s", l);
1846 emitcode ("push", "acc");
1849 emitcode ("push", "%s", l);
1852 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1855 /*-----------------------------------------------------------------*/
1856 /* genIpop - recover the registers: can happen only for spilling */
1857 /*-----------------------------------------------------------------*/
1859 genIpop (iCode * ic)
1863 D(emitcode ("; genIpop",""));
1865 /* if the temp was not pushed then */
1866 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1869 aopOp (IC_LEFT (ic), ic, FALSE);
1870 size = AOP_SIZE (IC_LEFT (ic));
1871 offset = (size - 1);
1873 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1876 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1879 /*-----------------------------------------------------------------*/
1880 /* unsaveRBank - restores the resgister bank from stack */
1881 /*-----------------------------------------------------------------*/
1883 unsaveRBank (int bank, iCode * ic, bool popPsw)
1889 if (options.useXstack)
1893 /* Assume r0 is available for use. */
1894 r = mcs51_regWithIdx (R0_IDX);;
1899 r = getFreePtr (ic, &aop, FALSE);
1901 emitcode ("mov", "%s,_spx", r->name);
1906 if (options.useXstack)
1908 emitcode ("movx", "a,@%s", r->name);
1909 emitcode ("mov", "psw,a");
1910 emitcode ("dec", "%s", r->name);
1914 emitcode ("pop", "psw");
1918 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1920 if (options.useXstack)
1922 emitcode ("movx", "a,@%s", r->name);
1923 emitcode ("mov", "(%s+%d),a",
1924 regs8051[i].base, 8 * bank + regs8051[i].offset);
1925 emitcode ("dec", "%s", r->name);
1929 emitcode ("pop", "(%s+%d)",
1930 regs8051[i].base, 8 * bank + regs8051[i].offset);
1933 if (options.useXstack)
1935 emitcode ("mov", "_spx,%s", r->name);
1940 freeAsmop (NULL, aop, ic, TRUE);
1944 /*-----------------------------------------------------------------*/
1945 /* saveRBank - saves an entire register bank on the stack */
1946 /*-----------------------------------------------------------------*/
1948 saveRBank (int bank, iCode * ic, bool pushPsw)
1954 if (options.useXstack)
1958 /* Assume r0 is available for use. */
1959 r = mcs51_regWithIdx (R0_IDX);;
1964 r = getFreePtr (ic, &aop, FALSE);
1966 emitcode ("mov", "%s,_spx", r->name);
1969 for (i = 0; i < mcs51_nRegs; i++)
1971 if (options.useXstack)
1973 emitcode ("inc", "%s", r->name);
1974 emitcode ("mov", "a,(%s+%d)",
1975 regs8051[i].base, 8 * bank + regs8051[i].offset);
1976 emitcode ("movx", "@%s,a", r->name);
1979 emitcode ("push", "(%s+%d)",
1980 regs8051[i].base, 8 * bank + regs8051[i].offset);
1985 if (options.useXstack)
1987 emitcode ("mov", "a,psw");
1988 emitcode ("movx", "@%s,a", r->name);
1989 emitcode ("inc", "%s", r->name);
1990 emitcode ("mov", "_spx,%s", r->name);
1995 emitcode ("push", "psw");
1998 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2003 freeAsmop (NULL, aop, ic, TRUE);
2012 /*-----------------------------------------------------------------*/
2013 /* genSend - gen code for SEND */
2014 /*-----------------------------------------------------------------*/
2015 static void genSend(set *sendSet)
2020 for (sic = setFirstItem (_G.sendSet); sic;
2021 sic = setNextItem (_G.sendSet)) {
2022 int size, offset = 0;
2023 aopOp (IC_LEFT (sic), sic, FALSE);
2024 size = AOP_SIZE (IC_LEFT (sic));
2026 if (sic->argreg == 1) {
2028 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2030 if (strcmp (l, fReturn[offset]))
2031 emitcode ("mov", "%s,%s", fReturn[offset], l);
2037 emitcode ("mov","b1_%d,%s",rb1_count++,
2038 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2041 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2045 /*-----------------------------------------------------------------*/
2046 /* genCall - generates a call statement */
2047 /*-----------------------------------------------------------------*/
2049 genCall (iCode * ic)
2052 // bool restoreBank = FALSE;
2053 bool swapBanks = FALSE;
2055 D(emitcode("; genCall",""));
2057 dtype = operandType (IC_LEFT (ic));
2058 /* if send set is not empty the assign */
2061 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2062 genSend(reverseSet(_G.sendSet));
2064 genSend(_G.sendSet);
2070 /* if we are calling a not _naked function that is not using
2071 the same register bank then we need to save the
2072 destination registers on the stack */
2073 dtype = operandType (IC_LEFT (ic));
2074 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2075 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2076 !IFFUNC_ISISR (dtype))
2081 /* if caller saves & we have not saved then */
2087 emitcode ("mov", "psw,#0x%02x",
2088 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2092 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2093 OP_SYMBOL (IC_LEFT (ic))->rname :
2094 OP_SYMBOL (IC_LEFT (ic))->name));
2098 emitcode ("mov", "psw,#0x%02x",
2099 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2102 /* if we need assign a result value */
2103 if ((IS_ITEMP (IC_RESULT (ic)) &&
2104 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2105 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2106 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2107 IS_TRUE_SYMOP (IC_RESULT (ic)))
2111 aopOp (IC_RESULT (ic), ic, FALSE);
2114 assignResultValue (IC_RESULT (ic));
2116 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2119 /* adjust the stack for parameters if
2124 if (ic->parmBytes > 3)
2126 emitcode ("mov", "a,%s", spname);
2127 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2128 emitcode ("mov", "%s,a", spname);
2131 for (i = 0; i < ic->parmBytes; i++)
2132 emitcode ("dec", "%s", spname);
2135 /* if we hade saved some registers then unsave them */
2136 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2137 unsaveRegisters (ic);
2139 // /* if register bank was saved then pop them */
2141 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2144 /*-----------------------------------------------------------------*/
2145 /* -10l - generates a call by pointer statement */
2146 /*-----------------------------------------------------------------*/
2148 genPcall (iCode * ic)
2151 symbol *rlbl = newiTempLabel (NULL);
2152 // bool restoreBank=FALSE;
2153 bool swapBanks = FALSE;
2155 D(emitcode("; genPCall",""));
2157 /* if caller saves & we have not saved then */
2161 /* if we are calling a not _naked function that is not using
2162 the same register bank then we need to save the
2163 destination registers on the stack */
2164 dtype = operandType (IC_LEFT (ic))->next;
2165 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2166 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2167 !IFFUNC_ISISR (dtype))
2169 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2170 // restoreBank=TRUE;
2172 // need caution message to user here
2175 /* push the return address on to the stack */
2176 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2177 emitcode ("push", "acc");
2178 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2179 emitcode ("push", "acc");
2181 /* now push the calling address */
2182 aopOp (IC_LEFT (ic), ic, FALSE);
2184 pushSide (IC_LEFT (ic), FPTRSIZE);
2186 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2188 /* if send set is not empty the assign */
2191 genSend(reverseSet(_G.sendSet));
2197 emitcode ("mov", "psw,#0x%02x",
2198 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2202 emitcode ("ret", "");
2203 emitcode ("", "%05d$:", (rlbl->key + 100));
2208 emitcode ("mov", "psw,#0x%02x",
2209 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2212 /* if we need assign a result value */
2213 if ((IS_ITEMP (IC_RESULT (ic)) &&
2214 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2215 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2216 IS_TRUE_SYMOP (IC_RESULT (ic)))
2220 aopOp (IC_RESULT (ic), ic, FALSE);
2223 assignResultValue (IC_RESULT (ic));
2225 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2228 /* adjust the stack for parameters if
2233 if (ic->parmBytes > 3)
2235 emitcode ("mov", "a,%s", spname);
2236 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2237 emitcode ("mov", "%s,a", spname);
2240 for (i = 0; i < ic->parmBytes; i++)
2241 emitcode ("dec", "%s", spname);
2245 // /* if register bank was saved then unsave them */
2247 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2249 /* if we hade saved some registers then
2251 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2252 unsaveRegisters (ic);
2255 /*-----------------------------------------------------------------*/
2256 /* resultRemat - result is rematerializable */
2257 /*-----------------------------------------------------------------*/
2259 resultRemat (iCode * ic)
2261 if (SKIP_IC (ic) || ic->op == IFX)
2264 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2266 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2267 if (sym->remat && !POINTER_SET (ic))
2274 #if defined(__BORLANDC__) || defined(_MSC_VER)
2275 #define STRCASECMP stricmp
2277 #define STRCASECMP strcasecmp
2280 /*-----------------------------------------------------------------*/
2281 /* inExcludeList - return 1 if the string is in exclude Reg list */
2282 /*-----------------------------------------------------------------*/
2284 regsCmp(void *p1, void *p2)
2286 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2290 inExcludeList (char *s)
2292 const char *p = setFirstItem(options.excludeRegsSet);
2294 if (p == NULL || STRCASECMP(p, "none") == 0)
2298 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2301 /*-----------------------------------------------------------------*/
2302 /* genFunction - generated code for function entry */
2303 /*-----------------------------------------------------------------*/
2305 genFunction (iCode * ic)
2309 bool switchedPSW = FALSE;
2310 int calleesaves_saved_register = -1;
2313 /* create the function header */
2314 emitcode (";", "-----------------------------------------");
2315 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2316 emitcode (";", "-----------------------------------------");
2318 emitcode ("", "%s:", sym->rname);
2319 ftype = operandType (IC_LEFT (ic));
2321 if (IFFUNC_ISNAKED(ftype))
2323 emitcode(";", "naked function: no prologue.");
2327 /* here we need to generate the equates for the
2328 register bank if required */
2329 if (FUNC_REGBANK (ftype) != rbank)
2333 rbank = FUNC_REGBANK (ftype);
2334 for (i = 0; i < mcs51_nRegs; i++)
2336 if (strcmp (regs8051[i].base, "0") == 0)
2337 emitcode ("", "%s = 0x%02x",
2339 8 * rbank + regs8051[i].offset);
2341 emitcode ("", "%s = %s + 0x%02x",
2344 8 * rbank + regs8051[i].offset);
2348 /* if this is an interrupt service routine then
2349 save acc, b, dpl, dph */
2350 if (IFFUNC_ISISR (sym->type))
2353 if (!inExcludeList ("acc"))
2354 emitcode ("push", "acc");
2355 if (!inExcludeList ("b"))
2356 emitcode ("push", "b");
2357 if (!inExcludeList ("dpl"))
2358 emitcode ("push", "dpl");
2359 if (!inExcludeList ("dph"))
2360 emitcode ("push", "dph");
2361 /* if this isr has no bank i.e. is going to
2362 run with bank 0 , then we need to save more
2364 if (!FUNC_REGBANK (sym->type))
2367 /* if this function does not call any other
2368 function then we can be economical and
2369 save only those registers that are used */
2370 if (!IFFUNC_HASFCALL(sym->type))
2374 /* if any registers used */
2377 /* save the registers used */
2378 for (i = 0; i < sym->regsUsed->size; i++)
2380 if (bitVectBitValue (sym->regsUsed, i) ||
2381 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2382 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2390 /* this function has a function call cannot
2391 determines register usage so we will have to push the
2393 saveRBank (0, ic, FALSE);
2394 if (options.parms_in_bank1) {
2396 for (i=0; i < 8 ; i++ ) {
2397 emitcode ("push","%s",rb1regs[i]);
2404 /* This ISR uses a non-zero bank.
2406 * We assume that the bank is available for our
2409 * However, if this ISR calls a function which uses some
2410 * other bank, we must save that bank entirely.
2412 unsigned long banksToSave = 0;
2414 if (IFFUNC_HASFCALL(sym->type))
2417 #define MAX_REGISTER_BANKS 4
2422 for (i = ic; i; i = i->next)
2424 if (i->op == ENDFUNCTION)
2426 /* we got to the end OK. */
2434 dtype = operandType (IC_LEFT(i));
2436 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2438 /* Mark this bank for saving. */
2439 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2441 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2445 banksToSave |= (1 << FUNC_REGBANK(dtype));
2448 /* And note that we don't need to do it in
2456 /* This is a mess; we have no idea what
2457 * register bank the called function might
2460 * The only thing I can think of to do is
2461 * throw a warning and hope.
2463 werror(W_FUNCPTR_IN_USING_ISR);
2467 if (banksToSave && options.useXstack)
2469 /* Since we aren't passing it an ic,
2470 * saveRBank will assume r0 is available to abuse.
2472 * So switch to our (trashable) bank now, so
2473 * the caller's R0 isn't trashed.
2475 emitcode ("push", "psw");
2476 emitcode ("mov", "psw,#0x%02x",
2477 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2481 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2483 if (banksToSave & (1 << ix))
2485 saveRBank(ix, NULL, FALSE);
2489 // TODO: this needs a closer look
2490 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2495 /* if callee-save to be used for this function
2496 then save the registers being used in this function */
2497 if (IFFUNC_CALLEESAVES(sym->type))
2501 /* if any registers used */
2504 /* save the registers used */
2505 for (i = 0; i < sym->regsUsed->size; i++)
2507 if (bitVectBitValue (sym->regsUsed, i) ||
2508 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2510 /* remember one saved register for later usage */
2511 if (calleesaves_saved_register < 0)
2512 calleesaves_saved_register = i;
2513 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2521 /* set the register bank to the desired value */
2522 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2525 emitcode ("push", "psw");
2526 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2529 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2532 if (options.useXstack)
2534 emitcode ("mov", "r0,%s", spname);
2535 emitcode ("mov", "a,_bp");
2536 emitcode ("movx", "@r0,a");
2537 emitcode ("inc", "%s", spname);
2541 /* set up the stack */
2542 emitcode ("push", "_bp"); /* save the callers stack */
2544 emitcode ("mov", "_bp,%s", spname);
2547 /* adjust the stack for the function */
2553 werror (W_STACK_OVERFLOW, sym->name);
2555 if (i > 3 && sym->recvSize < 4)
2558 emitcode ("mov", "a,sp");
2559 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2560 emitcode ("mov", "sp,a");
2565 if (IFFUNC_CALLEESAVES(sym->type))
2567 /* if it's a callee-saves function we need a saved register */
2568 if (calleesaves_saved_register >= 0)
2570 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2571 emitcode ("mov", "a,sp");
2572 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2573 emitcode ("mov", "sp,a");
2574 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2577 /* do it the hard way */
2579 emitcode ("inc", "sp");
2583 /* not callee-saves, we can clobber r0 */
2584 emitcode ("mov", "r0,a");
2585 emitcode ("mov", "a,sp");
2586 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2587 emitcode ("mov", "sp,a");
2588 emitcode ("mov", "a,r0");
2593 emitcode ("inc", "sp");
2599 emitcode ("mov", "a,_spx");
2600 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2601 emitcode ("mov", "_spx,a");
2604 /* if critical function then turn interrupts off */
2605 if (IFFUNC_ISCRITICAL (ftype))
2607 symbol *tlbl = newiTempLabel (NULL);
2608 emitcode ("setb", "c");
2609 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2610 emitcode ("clr", "c");
2611 emitcode ("", "%05d$:", (tlbl->key + 100));
2612 emitcode ("push", "psw"); /* save old ea via c in psw */
2616 /*-----------------------------------------------------------------*/
2617 /* genEndFunction - generates epilogue for functions */
2618 /*-----------------------------------------------------------------*/
2620 genEndFunction (iCode * ic)
2622 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2624 if (IFFUNC_ISNAKED(sym->type))
2626 emitcode(";", "naked function: no epilogue.");
2630 if (IFFUNC_ISCRITICAL (sym->type))
2632 emitcode ("pop", "psw"); /* restore ea via c in psw */
2633 emitcode ("mov", "ea,c");
2636 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2638 emitcode ("mov", "%s,_bp", spname);
2641 /* if use external stack but some variables were
2642 added to the local stack then decrement the
2644 if (options.useXstack && sym->stack)
2646 emitcode ("mov", "a,sp");
2647 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2648 emitcode ("mov", "sp,a");
2652 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2654 if (options.useXstack)
2656 emitcode ("mov", "r0,%s", spname);
2657 emitcode ("movx", "a,@r0");
2658 emitcode ("mov", "_bp,a");
2659 emitcode ("dec", "%s", spname);
2663 emitcode ("pop", "_bp");
2667 /* restore the register bank */
2668 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2670 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2671 || !options.useXstack)
2673 /* Special case of ISR using non-zero bank with useXstack
2676 emitcode ("pop", "psw");
2680 if (IFFUNC_ISISR (sym->type))
2683 /* now we need to restore the registers */
2684 /* if this isr has no bank i.e. is going to
2685 run with bank 0 , then we need to save more
2687 if (!FUNC_REGBANK (sym->type))
2689 /* if this function does not call any other
2690 function then we can be economical and
2691 save only those registers that are used */
2692 if (!IFFUNC_HASFCALL(sym->type))
2696 /* if any registers used */
2699 /* save the registers used */
2700 for (i = sym->regsUsed->size; i >= 0; i--)
2702 if (bitVectBitValue (sym->regsUsed, i) ||
2703 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2704 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2711 if (options.parms_in_bank1) {
2713 for (i = 7 ; i >= 0 ; i-- ) {
2714 emitcode ("pop","%s",rb1regs[i]);
2717 /* this function has a function call cannot
2718 determines register usage so we will have to pop the
2720 unsaveRBank (0, ic, FALSE);
2725 /* This ISR uses a non-zero bank.
2727 * Restore any register banks saved by genFunction
2730 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2733 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2735 if (savedBanks & (1 << ix))
2737 unsaveRBank(ix, NULL, FALSE);
2741 if (options.useXstack)
2743 /* Restore bank AFTER calling unsaveRBank,
2744 * since it can trash r0.
2746 emitcode ("pop", "psw");
2750 if (!inExcludeList ("dph"))
2751 emitcode ("pop", "dph");
2752 if (!inExcludeList ("dpl"))
2753 emitcode ("pop", "dpl");
2754 if (!inExcludeList ("b"))
2755 emitcode ("pop", "b");
2756 if (!inExcludeList ("acc"))
2757 emitcode ("pop", "acc");
2759 /* if debug then send end of function */
2760 if (options.debug && currFunc)
2763 emitcode ("", "C$%s$%d$%d$%d ==.",
2764 FileBaseName (ic->filename), currFunc->lastLine,
2765 ic->level, ic->block);
2766 if (IS_STATIC (currFunc->etype))
2767 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2769 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2773 emitcode ("reti", "");
2777 if (IFFUNC_CALLEESAVES(sym->type))
2781 /* if any registers used */
2784 /* save the registers used */
2785 for (i = sym->regsUsed->size; i >= 0; i--)
2787 if (bitVectBitValue (sym->regsUsed, i) ||
2788 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2789 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2795 /* if debug then send end of function */
2796 if (options.debug && currFunc)
2799 emitcode ("", "C$%s$%d$%d$%d ==.",
2800 FileBaseName (ic->filename), currFunc->lastLine,
2801 ic->level, ic->block);
2802 if (IS_STATIC (currFunc->etype))
2803 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2805 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2809 emitcode ("ret", "");
2814 /*-----------------------------------------------------------------*/
2815 /* genRet - generate code for return statement */
2816 /*-----------------------------------------------------------------*/
2820 int size, offset = 0, pushed = 0;
2822 D(emitcode ("; genRet",""));
2824 /* if we have no return value then
2825 just generate the "ret" */
2829 /* we have something to return then
2830 move the return value into place */
2831 aopOp (IC_LEFT (ic), ic, FALSE);
2832 size = AOP_SIZE (IC_LEFT (ic));
2837 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2840 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2842 emitcode ("push", "%s", l);
2847 l = aopGet (AOP (IC_LEFT (ic)), offset,
2849 if (strcmp (fReturn[offset], l))
2850 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2859 if (strcmp (fReturn[pushed], "a"))
2860 emitcode ("pop", fReturn[pushed]);
2862 emitcode ("pop", "acc");
2865 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2868 /* generate a jump to the return label
2869 if the next is not the return statement */
2870 if (!(ic->next && ic->next->op == LABEL &&
2871 IC_LABEL (ic->next) == returnLabel))
2873 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2877 /*-----------------------------------------------------------------*/
2878 /* genLabel - generates a label */
2879 /*-----------------------------------------------------------------*/
2881 genLabel (iCode * ic)
2883 /* special case never generate */
2884 if (IC_LABEL (ic) == entryLabel)
2887 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2890 /*-----------------------------------------------------------------*/
2891 /* genGoto - generates a ljmp */
2892 /*-----------------------------------------------------------------*/
2894 genGoto (iCode * ic)
2896 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2899 /*-----------------------------------------------------------------*/
2900 /* findLabelBackwards: walks back through the iCode chain looking */
2901 /* for the given label. Returns number of iCode instructions */
2902 /* between that label and given ic. */
2903 /* Returns zero if label not found. */
2904 /*-----------------------------------------------------------------*/
2906 findLabelBackwards (iCode * ic, int key)
2915 /* If we have any pushes or pops, we cannot predict the distance.
2916 I don't like this at all, this should be dealt with in the
2918 if (ic->op == IPUSH || ic->op == IPOP) {
2922 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2931 /*-----------------------------------------------------------------*/
2932 /* genPlusIncr :- does addition with increment if possible */
2933 /*-----------------------------------------------------------------*/
2935 genPlusIncr (iCode * ic)
2937 unsigned int icount;
2938 unsigned int size = getDataSize (IC_RESULT (ic));
2940 /* will try to generate an increment */
2941 /* if the right side is not a literal
2943 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2946 /* if the literal value of the right hand side
2947 is greater than 4 then it is not worth it */
2948 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2951 D(emitcode ("; genPlusIncr",""));
2953 /* if increment >=16 bits in register or direct space */
2954 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2955 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2963 /* If the next instruction is a goto and the goto target
2964 * is < 10 instructions previous to this, we can generate
2965 * jumps straight to that target.
2967 if (ic->next && ic->next->op == GOTO
2968 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2969 && labelRange <= 10)
2971 emitcode (";", "tail increment optimized");
2972 tlbl = IC_LABEL (ic->next);
2977 tlbl = newiTempLabel (NULL);
2980 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2981 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2982 IS_AOP_PREG (IC_RESULT (ic)))
2983 emitcode ("cjne", "%s,#0x00,%05d$",
2984 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2988 emitcode ("clr", "a");
2989 emitcode ("cjne", "a,%s,%05d$",
2990 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2994 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2997 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2998 IS_AOP_PREG (IC_RESULT (ic)))
2999 emitcode ("cjne", "%s,#0x00,%05d$",
3000 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3003 emitcode ("cjne", "a,%s,%05d$",
3004 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3007 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3011 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3012 IS_AOP_PREG (IC_RESULT (ic)))
3013 emitcode ("cjne", "%s,#0x00,%05d$",
3014 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3018 emitcode ("cjne", "a,%s,%05d$",
3019 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3022 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3027 emitcode ("", "%05d$:", tlbl->key + 100);
3032 /* if the sizes are greater than 1 then we cannot */
3033 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3034 AOP_SIZE (IC_LEFT (ic)) > 1)
3037 /* we can if the aops of the left & result match or
3038 if they are in registers and the registers are the
3040 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3045 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3046 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3047 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3053 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3062 /*-----------------------------------------------------------------*/
3063 /* outBitAcc - output a bit in acc */
3064 /*-----------------------------------------------------------------*/
3066 outBitAcc (operand * result)
3068 symbol *tlbl = newiTempLabel (NULL);
3069 /* if the result is a bit */
3070 if (AOP_TYPE (result) == AOP_CRY)
3072 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3076 emitcode ("jz", "%05d$", tlbl->key + 100);
3077 emitcode ("mov", "a,%s", one);
3078 emitcode ("", "%05d$:", tlbl->key + 100);
3083 /*-----------------------------------------------------------------*/
3084 /* genPlusBits - generates code for addition of two bits */
3085 /*-----------------------------------------------------------------*/
3087 genPlusBits (iCode * ic)
3089 D(emitcode ("; genPlusBits",""));
3091 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3093 symbol *lbl = newiTempLabel (NULL);
3094 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3095 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3096 emitcode ("cpl", "c");
3097 emitcode ("", "%05d$:", (lbl->key + 100));
3098 outBitC (IC_RESULT (ic));
3102 emitcode ("clr", "a");
3103 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3104 emitcode ("rlc", "a");
3105 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3106 emitcode ("addc", "a,#0x00");
3107 outAcc (IC_RESULT (ic));
3112 /* This is the original version of this code.
3114 * This is being kept around for reference,
3115 * because I am not entirely sure I got it right...
3118 adjustArithmeticResult (iCode * ic)
3120 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3121 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3122 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3123 aopPut (AOP (IC_RESULT (ic)),
3124 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3126 isOperandVolatile (IC_RESULT (ic), FALSE));
3128 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3129 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3130 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3131 aopPut (AOP (IC_RESULT (ic)),
3132 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3134 isOperandVolatile (IC_RESULT (ic), FALSE));
3136 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3137 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3138 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3139 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3140 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3143 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3144 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3148 /* This is the pure and virtuous version of this code.
3149 * I'm pretty certain it's right, but not enough to toss the old
3153 adjustArithmeticResult (iCode * ic)
3155 if (opIsGptr (IC_RESULT (ic)) &&
3156 opIsGptr (IC_LEFT (ic)) &&
3157 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3159 aopPut (AOP (IC_RESULT (ic)),
3160 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3162 isOperandVolatile (IC_RESULT (ic), FALSE));
3165 if (opIsGptr (IC_RESULT (ic)) &&
3166 opIsGptr (IC_RIGHT (ic)) &&
3167 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3169 aopPut (AOP (IC_RESULT (ic)),
3170 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3172 isOperandVolatile (IC_RESULT (ic), FALSE));
3175 if (opIsGptr (IC_RESULT (ic)) &&
3176 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3177 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3178 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3179 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3182 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3183 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3188 /*-----------------------------------------------------------------*/
3189 /* genPlus - generates code for addition */
3190 /*-----------------------------------------------------------------*/
3192 genPlus (iCode * ic)
3194 int size, offset = 0;
3196 asmop *leftOp, *rightOp;
3198 /* special cases :- */
3200 D(emitcode ("; genPlus",""));
3202 aopOp (IC_LEFT (ic), ic, FALSE);
3203 aopOp (IC_RIGHT (ic), ic, FALSE);
3204 aopOp (IC_RESULT (ic), ic, TRUE);
3206 /* if literal, literal on the right or
3207 if left requires ACC or right is already
3209 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3210 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3211 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3213 operand *t = IC_RIGHT (ic);
3214 IC_RIGHT (ic) = IC_LEFT (ic);
3218 /* if both left & right are in bit
3220 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3221 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3227 /* if left in bit space & right literal */
3228 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3229 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3231 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3232 /* if result in bit space */
3233 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3235 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3236 emitcode ("cpl", "c");
3237 outBitC (IC_RESULT (ic));
3241 size = getDataSize (IC_RESULT (ic));
3244 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3245 emitcode ("addc", "a,#00");
3246 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3252 /* if I can do an increment instead
3253 of add then GOOD for ME */
3254 if (genPlusIncr (ic) == TRUE)
3257 size = getDataSize (IC_RESULT (ic));
3259 leftOp = AOP(IC_LEFT(ic));
3260 rightOp = AOP(IC_RIGHT(ic));
3265 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3267 emitcode("mov", "b,a");
3268 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3269 emitcode("xch", "a,b");
3270 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3271 emitcode (add, "a,b");
3273 else if (aopGetUsesAcc (leftOp, offset))
3275 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3276 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3280 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3281 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3283 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3284 add = "addc"; /* further adds must propagate carry */
3287 adjustArithmeticResult (ic);
3290 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3291 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3292 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3295 /*-----------------------------------------------------------------*/
3296 /* genMinusDec :- does subtraction with deccrement if possible */
3297 /*-----------------------------------------------------------------*/
3299 genMinusDec (iCode * ic)
3301 unsigned int icount;
3302 unsigned int size = getDataSize (IC_RESULT (ic));
3304 /* will try to generate an increment */
3305 /* if the right side is not a literal
3307 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3310 /* if the literal value of the right hand side
3311 is greater than 4 then it is not worth it */
3312 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3315 D(emitcode ("; genMinusDec",""));
3317 /* if decrement >=16 bits in register or direct space */
3318 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3319 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3327 /* If the next instruction is a goto and the goto target
3328 * is <= 10 instructions previous to this, we can generate
3329 * jumps straight to that target.
3331 if (ic->next && ic->next->op == GOTO
3332 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3333 && labelRange <= 10)
3335 emitcode (";", "tail decrement optimized");
3336 tlbl = IC_LABEL (ic->next);
3341 tlbl = newiTempLabel (NULL);
3345 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3346 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3347 IS_AOP_PREG (IC_RESULT (ic)))
3348 emitcode ("cjne", "%s,#0xff,%05d$"
3349 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3353 emitcode ("mov", "a,#0xff");
3354 emitcode ("cjne", "a,%s,%05d$"
3355 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3358 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3361 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3362 IS_AOP_PREG (IC_RESULT (ic)))
3363 emitcode ("cjne", "%s,#0xff,%05d$"
3364 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3368 emitcode ("cjne", "a,%s,%05d$"
3369 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3372 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3376 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3377 IS_AOP_PREG (IC_RESULT (ic)))
3378 emitcode ("cjne", "%s,#0xff,%05d$"
3379 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3383 emitcode ("cjne", "a,%s,%05d$"
3384 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3387 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3391 emitcode ("", "%05d$:", tlbl->key + 100);
3396 /* if the sizes are greater than 1 then we cannot */
3397 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3398 AOP_SIZE (IC_LEFT (ic)) > 1)
3401 /* we can if the aops of the left & result match or
3402 if they are in registers and the registers are the
3404 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3408 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3416 /*-----------------------------------------------------------------*/
3417 /* addSign - complete with sign */
3418 /*-----------------------------------------------------------------*/
3420 addSign (operand * result, int offset, int sign)
3422 int size = (getDataSize (result) - offset);
3427 emitcode ("rlc", "a");
3428 emitcode ("subb", "a,acc");
3430 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3434 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3438 /*-----------------------------------------------------------------*/
3439 /* genMinusBits - generates code for subtraction of two bits */
3440 /*-----------------------------------------------------------------*/
3442 genMinusBits (iCode * ic)
3444 symbol *lbl = newiTempLabel (NULL);
3446 D(emitcode ("; genMinusBits",""));
3448 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3450 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3451 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3452 emitcode ("cpl", "c");
3453 emitcode ("", "%05d$:", (lbl->key + 100));
3454 outBitC (IC_RESULT (ic));
3458 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3459 emitcode ("subb", "a,acc");
3460 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3461 emitcode ("inc", "a");
3462 emitcode ("", "%05d$:", (lbl->key + 100));
3463 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3464 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3468 /*-----------------------------------------------------------------*/
3469 /* genMinus - generates code for subtraction */
3470 /*-----------------------------------------------------------------*/
3472 genMinus (iCode * ic)
3474 int size, offset = 0;
3476 D(emitcode ("; genMinus",""));
3478 aopOp (IC_LEFT (ic), ic, FALSE);
3479 aopOp (IC_RIGHT (ic), ic, FALSE);
3480 aopOp (IC_RESULT (ic), ic, TRUE);
3482 /* special cases :- */
3483 /* if both left & right are in bit space */
3484 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3485 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3491 /* if I can do an decrement instead
3492 of subtract then GOOD for ME */
3493 if (genMinusDec (ic) == TRUE)
3496 size = getDataSize (IC_RESULT (ic));
3498 /* if literal, add a,#-lit, else normal subb */
3499 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3501 unsigned long lit = 0L;
3503 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3508 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3509 /* first add without previous c */
3511 if (!size && lit== (unsigned long) -1) {
3512 emitcode ("dec", "a");
3514 emitcode ("add", "a,#0x%02x",
3515 (unsigned int) (lit & 0x0FFL));
3518 emitcode ("addc", "a,#0x%02x",
3519 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3521 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3526 asmop *leftOp, *rightOp;
3528 leftOp = AOP(IC_LEFT(ic));
3529 rightOp = AOP(IC_RIGHT(ic));
3533 if (aopGetUsesAcc(rightOp, offset)) {
3534 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3535 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3537 emitcode( "setb", "c");
3539 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3540 emitcode("cpl", "a");
3542 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3545 emitcode ("subb", "a,%s",
3546 aopGet(rightOp, offset, FALSE, TRUE));
3549 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3554 adjustArithmeticResult (ic);
3557 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3558 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3559 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3563 /*-----------------------------------------------------------------*/
3564 /* genMultbits :- multiplication of bits */
3565 /*-----------------------------------------------------------------*/
3567 genMultbits (operand * left,
3571 D(emitcode ("; genMultbits",""));
3573 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3574 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3579 /*-----------------------------------------------------------------*/
3580 /* genMultOneByte : 8*8=8/16 bit multiplication */
3581 /*-----------------------------------------------------------------*/
3583 genMultOneByte (operand * left,
3587 sym_link *opetype = operandType (result);
3589 int size=AOP_SIZE(result);
3591 D(emitcode ("; genMultOneByte",""));
3593 if (size<1 || size>2) {
3594 // this should never happen
3595 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3596 AOP_SIZE(result), __FILE__, lineno);
3600 /* (if two literals: the value is computed before) */
3601 /* if one literal, literal on the right */
3602 if (AOP_TYPE (left) == AOP_LIT)
3607 //emitcode (";", "swapped left and right");
3610 if (SPEC_USIGN(opetype)
3611 // ignore the sign of left and right, what else can we do?
3612 || (SPEC_USIGN(operandType(left)) &&
3613 SPEC_USIGN(operandType(right)))) {
3614 // just an unsigned 8*8=8/16 multiply
3615 //emitcode (";","unsigned");
3616 // TODO: check for accumulator clash between left & right aops?
3617 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3618 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3619 emitcode ("mul", "ab");
3620 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3622 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3627 // we have to do a signed multiply
3629 //emitcode (";", "signed");
3630 emitcode ("clr", "F0"); // reset sign flag
3631 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3633 lbl=newiTempLabel(NULL);
3634 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3635 // left side is negative, 8-bit two's complement, this fails for -128
3636 emitcode ("setb", "F0"); // set sign flag
3637 emitcode ("cpl", "a");
3638 emitcode ("inc", "a");
3640 emitcode ("", "%05d$:", lbl->key+100);
3643 if (AOP_TYPE(right)==AOP_LIT) {
3644 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3645 /* AND literal negative */
3647 emitcode ("cpl", "F0"); // complement sign flag
3648 emitcode ("mov", "b,#0x%02x", -val);
3650 emitcode ("mov", "b,#0x%02x", val);
3653 lbl=newiTempLabel(NULL);
3654 emitcode ("mov", "b,a");
3655 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3656 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3657 // right side is negative, 8-bit two's complement
3658 emitcode ("cpl", "F0"); // complement sign flag
3659 emitcode ("cpl", "a");
3660 emitcode ("inc", "a");
3661 emitcode ("", "%05d$:", lbl->key+100);
3663 emitcode ("mul", "ab");
3665 lbl=newiTempLabel(NULL);
3666 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3667 // only ONE op was negative, we have to do a 8/16-bit two's complement
3668 emitcode ("cpl", "a"); // lsb
3670 emitcode ("inc", "a");
3672 emitcode ("add", "a,#1");
3673 emitcode ("xch", "a,b");
3674 emitcode ("cpl", "a"); // msb
3675 emitcode ("addc", "a,#0");
3676 emitcode ("xch", "a,b");
3679 emitcode ("", "%05d$:", lbl->key+100);
3680 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3682 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3686 /*-----------------------------------------------------------------*/
3687 /* genMult - generates code for multiplication */
3688 /*-----------------------------------------------------------------*/
3690 genMult (iCode * ic)
3692 operand *left = IC_LEFT (ic);
3693 operand *right = IC_RIGHT (ic);
3694 operand *result = IC_RESULT (ic);
3696 D(emitcode ("; genMult",""));
3698 /* assign the amsops */
3699 aopOp (left, ic, FALSE);
3700 aopOp (right, ic, FALSE);
3701 aopOp (result, ic, TRUE);
3703 /* special cases first */
3705 if (AOP_TYPE (left) == AOP_CRY &&
3706 AOP_TYPE (right) == AOP_CRY)
3708 genMultbits (left, right, result);
3712 /* if both are of size == 1 */
3713 #if 0 // one of them can be a sloc shared with the result
3714 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3716 if (getSize(operandType(left)) == 1 &&
3717 getSize(operandType(right)) == 1)
3720 genMultOneByte (left, right, result);
3724 /* should have been converted to function call */
3725 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3726 getSize(OP_SYMBOL(right)->type));
3730 freeAsmop (result, NULL, ic, TRUE);
3731 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3732 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3735 /*-----------------------------------------------------------------*/
3736 /* genDivbits :- division of bits */
3737 /*-----------------------------------------------------------------*/
3739 genDivbits (operand * left,
3746 D(emitcode ("; genDivbits",""));
3748 /* the result must be bit */
3749 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3750 l = aopGet (AOP (left), 0, FALSE, FALSE);
3754 emitcode ("div", "ab");
3755 emitcode ("rrc", "a");
3756 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3759 /*-----------------------------------------------------------------*/
3760 /* genDivOneByte : 8 bit division */
3761 /*-----------------------------------------------------------------*/
3763 genDivOneByte (operand * left,
3767 sym_link *opetype = operandType (result);
3772 D(emitcode ("; genDivOneByte",""));
3774 size = AOP_SIZE (result) - 1;
3776 /* signed or unsigned */
3777 if (SPEC_USIGN (opetype))
3779 /* unsigned is easy */
3780 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3781 l = aopGet (AOP (left), 0, FALSE, FALSE);
3783 emitcode ("div", "ab");
3784 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3786 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3790 /* signed is a little bit more difficult */
3792 /* save the signs of the operands */
3793 l = aopGet (AOP (left), 0, FALSE, FALSE);
3795 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3796 emitcode ("push", "acc"); /* save it on the stack */
3798 /* now sign adjust for both left & right */
3799 l = aopGet (AOP (right), 0, FALSE, FALSE);
3801 lbl = newiTempLabel (NULL);
3802 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3803 emitcode ("cpl", "a");
3804 emitcode ("inc", "a");
3805 emitcode ("", "%05d$:", (lbl->key + 100));
3806 emitcode ("mov", "b,a");
3808 /* sign adjust left side */
3809 l = aopGet (AOP (left), 0, FALSE, FALSE);
3812 lbl = newiTempLabel (NULL);
3813 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3814 emitcode ("cpl", "a");
3815 emitcode ("inc", "a");
3816 emitcode ("", "%05d$:", (lbl->key + 100));
3818 /* now the division */
3819 emitcode ("div", "ab");
3820 /* we are interested in the lower order
3822 emitcode ("mov", "b,a");
3823 lbl = newiTempLabel (NULL);
3824 emitcode ("pop", "acc");
3825 /* if there was an over flow we don't
3826 adjust the sign of the result */
3827 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3828 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3830 emitcode ("clr", "a");
3831 emitcode ("subb", "a,b");
3832 emitcode ("mov", "b,a");
3833 emitcode ("", "%05d$:", (lbl->key + 100));
3835 /* now we are done */
3836 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3839 emitcode ("mov", "c,b.7");
3840 emitcode ("subb", "a,acc");
3843 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3847 /*-----------------------------------------------------------------*/
3848 /* genDiv - generates code for division */
3849 /*-----------------------------------------------------------------*/
3853 operand *left = IC_LEFT (ic);
3854 operand *right = IC_RIGHT (ic);
3855 operand *result = IC_RESULT (ic);
3857 D(emitcode ("; genDiv",""));
3859 /* assign the amsops */
3860 aopOp (left, ic, FALSE);
3861 aopOp (right, ic, FALSE);
3862 aopOp (result, ic, TRUE);
3864 /* special cases first */
3866 if (AOP_TYPE (left) == AOP_CRY &&
3867 AOP_TYPE (right) == AOP_CRY)
3869 genDivbits (left, right, result);
3873 /* if both are of size == 1 */
3874 if (AOP_SIZE (left) == 1 &&
3875 AOP_SIZE (right) == 1)
3877 genDivOneByte (left, right, result);
3881 /* should have been converted to function call */
3884 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3885 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3886 freeAsmop (result, NULL, ic, TRUE);
3889 /*-----------------------------------------------------------------*/
3890 /* genModbits :- modulus of bits */
3891 /*-----------------------------------------------------------------*/
3893 genModbits (operand * left,
3900 D(emitcode ("; genModbits",""));
3902 /* the result must be bit */
3903 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3904 l = aopGet (AOP (left), 0, FALSE, FALSE);
3908 emitcode ("div", "ab");
3909 emitcode ("mov", "a,b");
3910 emitcode ("rrc", "a");
3911 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3914 /*-----------------------------------------------------------------*/
3915 /* genModOneByte : 8 bit modulus */
3916 /*-----------------------------------------------------------------*/
3918 genModOneByte (operand * left,
3922 sym_link *opetype = operandType (result);
3926 D(emitcode ("; genModOneByte",""));
3928 /* signed or unsigned */
3929 if (SPEC_USIGN (opetype))
3931 /* unsigned is easy */
3932 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3933 l = aopGet (AOP (left), 0, FALSE, FALSE);
3935 emitcode ("div", "ab");
3936 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3940 /* signed is a little bit more difficult */
3942 /* save the signs of the operands */
3943 l = aopGet (AOP (left), 0, FALSE, FALSE);
3946 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3947 emitcode ("push", "acc"); /* save it on the stack */
3949 /* now sign adjust for both left & right */
3950 l = aopGet (AOP (right), 0, FALSE, FALSE);
3953 lbl = newiTempLabel (NULL);
3954 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3955 emitcode ("cpl", "a");
3956 emitcode ("inc", "a");
3957 emitcode ("", "%05d$:", (lbl->key + 100));
3958 emitcode ("mov", "b,a");
3960 /* sign adjust left side */
3961 l = aopGet (AOP (left), 0, FALSE, FALSE);
3964 lbl = newiTempLabel (NULL);
3965 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3966 emitcode ("cpl", "a");
3967 emitcode ("inc", "a");
3968 emitcode ("", "%05d$:", (lbl->key + 100));
3970 /* now the multiplication */
3971 emitcode ("div", "ab");
3972 /* we are interested in the lower order
3974 lbl = newiTempLabel (NULL);
3975 emitcode ("pop", "acc");
3976 /* if there was an over flow we don't
3977 adjust the sign of the result */
3978 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3979 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3981 emitcode ("clr", "a");
3982 emitcode ("subb", "a,b");
3983 emitcode ("mov", "b,a");
3984 emitcode ("", "%05d$:", (lbl->key + 100));
3986 /* now we are done */
3987 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3991 /*-----------------------------------------------------------------*/
3992 /* genMod - generates code for division */
3993 /*-----------------------------------------------------------------*/
3997 operand *left = IC_LEFT (ic);
3998 operand *right = IC_RIGHT (ic);
3999 operand *result = IC_RESULT (ic);
4001 D(emitcode ("; genMod",""));
4003 /* assign the amsops */
4004 aopOp (left, ic, FALSE);
4005 aopOp (right, ic, FALSE);
4006 aopOp (result, ic, TRUE);
4008 /* special cases first */
4010 if (AOP_TYPE (left) == AOP_CRY &&
4011 AOP_TYPE (right) == AOP_CRY)
4013 genModbits (left, right, result);
4017 /* if both are of size == 1 */
4018 if (AOP_SIZE (left) == 1 &&
4019 AOP_SIZE (right) == 1)
4021 genModOneByte (left, right, result);
4025 /* should have been converted to function call */
4029 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4030 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4031 freeAsmop (result, NULL, ic, TRUE);
4034 /*-----------------------------------------------------------------*/
4035 /* genIfxJump :- will create a jump depending on the ifx */
4036 /*-----------------------------------------------------------------*/
4038 genIfxJump (iCode * ic, char *jval)
4041 symbol *tlbl = newiTempLabel (NULL);
4044 D(emitcode ("; genIfxJump",""));
4046 /* if true label then we jump if condition
4050 jlbl = IC_TRUE (ic);
4051 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4052 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4056 /* false label is present */
4057 jlbl = IC_FALSE (ic);
4058 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4059 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4061 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4062 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4064 emitcode (inst, "%05d$", tlbl->key + 100);
4065 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4066 emitcode ("", "%05d$:", tlbl->key + 100);
4068 /* mark the icode as generated */
4072 /*-----------------------------------------------------------------*/
4073 /* genCmp :- greater or less than comparison */
4074 /*-----------------------------------------------------------------*/
4076 genCmp (operand * left, operand * right,
4077 operand * result, iCode * ifx, int sign, iCode *ic)
4079 int size, offset = 0;
4080 unsigned long lit = 0L;
4083 D(emitcode ("; genCmp",""));
4085 /* if left & right are bit variables */
4086 if (AOP_TYPE (left) == AOP_CRY &&
4087 AOP_TYPE (right) == AOP_CRY)
4089 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4090 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4094 /* subtract right from left if at the
4095 end the carry flag is set then we know that
4096 left is greater than right */
4097 size = max (AOP_SIZE (left), AOP_SIZE (right));
4099 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4100 if ((size == 1) && !sign &&
4101 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4103 symbol *lbl = newiTempLabel (NULL);
4104 emitcode ("cjne", "%s,%s,%05d$",
4105 aopGet (AOP (left), offset, FALSE, FALSE),
4106 aopGet (AOP (right), offset, FALSE, FALSE),
4108 emitcode ("", "%05d$:", lbl->key + 100);
4112 if (AOP_TYPE (right) == AOP_LIT)
4114 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4115 /* optimize if(x < 0) or if(x >= 0) */
4124 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4125 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4127 genIfxJump (ifx, "acc.7");
4131 emitcode ("rlc", "a");
4139 rightInB = aopGetUsesAcc(AOP (right), offset);
4141 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4142 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4143 if (sign && size == 0)
4145 emitcode ("xrl", "a,#0x80");
4146 if (AOP_TYPE (right) == AOP_LIT)
4148 unsigned long lit = (unsigned long)
4149 floatFromVal (AOP (right)->aopu.aop_lit);
4150 emitcode ("subb", "a,#0x%02x",
4151 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4156 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4157 emitcode ("xrl", "b,#0x80");
4158 emitcode ("subb", "a,b");
4164 emitcode ("subb", "a,b");
4166 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4174 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4175 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4176 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4182 /* if the result is used in the next
4183 ifx conditional branch then generate
4184 code a little differently */
4186 genIfxJump (ifx, "c");
4189 /* leave the result in acc */
4193 /*-----------------------------------------------------------------*/
4194 /* genCmpGt :- greater than comparison */
4195 /*-----------------------------------------------------------------*/
4197 genCmpGt (iCode * ic, iCode * ifx)
4199 operand *left, *right, *result;
4200 sym_link *letype, *retype;
4203 D(emitcode ("; genCmpGt",""));
4205 left = IC_LEFT (ic);
4206 right = IC_RIGHT (ic);
4207 result = IC_RESULT (ic);
4209 letype = getSpec (operandType (left));
4210 retype = getSpec (operandType (right));
4211 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4212 /* assign the amsops */
4213 aopOp (left, ic, FALSE);
4214 aopOp (right, ic, FALSE);
4215 aopOp (result, ic, TRUE);
4217 genCmp (right, left, result, ifx, sign,ic);
4219 freeAsmop (result, NULL, ic, TRUE);
4222 /*-----------------------------------------------------------------*/
4223 /* genCmpLt - less than comparisons */
4224 /*-----------------------------------------------------------------*/
4226 genCmpLt (iCode * ic, iCode * ifx)
4228 operand *left, *right, *result;
4229 sym_link *letype, *retype;
4232 D(emitcode ("; genCmpLt",""));
4234 left = IC_LEFT (ic);
4235 right = IC_RIGHT (ic);
4236 result = IC_RESULT (ic);
4238 letype = getSpec (operandType (left));
4239 retype = getSpec (operandType (right));
4240 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4242 /* assign the amsops */
4243 aopOp (left, ic, FALSE);
4244 aopOp (right, ic, FALSE);
4245 aopOp (result, ic, TRUE);
4247 genCmp (left, right, result, ifx, sign,ic);
4249 freeAsmop (result, NULL, ic, TRUE);
4252 /*-----------------------------------------------------------------*/
4253 /* gencjneshort - compare and jump if not equal */
4254 /*-----------------------------------------------------------------*/
4256 gencjneshort (operand * left, operand * right, symbol * lbl)
4258 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4260 unsigned long lit = 0L;
4262 /* if the left side is a literal or
4263 if the right is in a pointer register and left
4265 if ((AOP_TYPE (left) == AOP_LIT) ||
4266 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4272 if (AOP_TYPE (right) == AOP_LIT)
4273 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4275 /* if the right side is a literal then anything goes */
4276 if (AOP_TYPE (right) == AOP_LIT &&
4277 AOP_TYPE (left) != AOP_DIR &&
4278 AOP_TYPE (left) != AOP_IMMD)
4282 emitcode ("cjne", "%s,%s,%05d$",
4283 aopGet (AOP (left), offset, FALSE, FALSE),
4284 aopGet (AOP (right), offset, FALSE, FALSE),
4290 /* if the right side is in a register or in direct space or
4291 if the left is a pointer register & right is not */
4292 else if (AOP_TYPE (right) == AOP_REG ||
4293 AOP_TYPE (right) == AOP_DIR ||
4294 AOP_TYPE (right) == AOP_LIT ||
4295 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4296 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4300 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4301 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4302 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4303 emitcode ("jnz", "%05d$", lbl->key + 100);
4305 emitcode ("cjne", "a,%s,%05d$",
4306 aopGet (AOP (right), offset, FALSE, TRUE),
4313 /* right is a pointer reg need both a & b */
4316 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4317 if (strcmp (l, "b"))
4318 emitcode ("mov", "b,%s", l);
4319 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4320 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4326 /*-----------------------------------------------------------------*/
4327 /* gencjne - compare and jump if not equal */
4328 /*-----------------------------------------------------------------*/
4330 gencjne (operand * left, operand * right, symbol * lbl)
4332 symbol *tlbl = newiTempLabel (NULL);
4334 gencjneshort (left, right, lbl);
4336 emitcode ("mov", "a,%s", one);
4337 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4338 emitcode ("", "%05d$:", lbl->key + 100);
4339 emitcode ("clr", "a");
4340 emitcode ("", "%05d$:", tlbl->key + 100);
4343 /*-----------------------------------------------------------------*/
4344 /* genCmpEq - generates code for equal to */
4345 /*-----------------------------------------------------------------*/
4347 genCmpEq (iCode * ic, iCode * ifx)
4349 operand *left, *right, *result;
4351 D(emitcode ("; genCmpEq",""));
4353 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4354 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4355 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4357 /* if literal, literal on the right or
4358 if the right is in a pointer register and left
4360 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4361 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4363 operand *t = IC_RIGHT (ic);
4364 IC_RIGHT (ic) = IC_LEFT (ic);
4368 if (ifx && !AOP_SIZE (result))
4371 /* if they are both bit variables */
4372 if (AOP_TYPE (left) == AOP_CRY &&
4373 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4375 if (AOP_TYPE (right) == AOP_LIT)
4377 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4380 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4381 emitcode ("cpl", "c");
4385 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4389 emitcode ("clr", "c");
4391 /* AOP_TYPE(right) == AOP_CRY */
4395 symbol *lbl = newiTempLabel (NULL);
4396 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4397 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4398 emitcode ("cpl", "c");
4399 emitcode ("", "%05d$:", (lbl->key + 100));
4401 /* if true label then we jump if condition
4403 tlbl = newiTempLabel (NULL);
4406 emitcode ("jnc", "%05d$", tlbl->key + 100);
4407 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4411 emitcode ("jc", "%05d$", tlbl->key + 100);
4412 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4414 emitcode ("", "%05d$:", tlbl->key + 100);
4418 tlbl = newiTempLabel (NULL);
4419 gencjneshort (left, right, tlbl);
4422 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4423 emitcode ("", "%05d$:", tlbl->key + 100);
4427 symbol *lbl = newiTempLabel (NULL);
4428 emitcode ("sjmp", "%05d$", lbl->key + 100);
4429 emitcode ("", "%05d$:", tlbl->key + 100);
4430 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4431 emitcode ("", "%05d$:", lbl->key + 100);
4434 /* mark the icode as generated */
4439 /* if they are both bit variables */
4440 if (AOP_TYPE (left) == AOP_CRY &&
4441 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4443 if (AOP_TYPE (right) == AOP_LIT)
4445 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4448 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4449 emitcode ("cpl", "c");
4453 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4457 emitcode ("clr", "c");
4459 /* AOP_TYPE(right) == AOP_CRY */
4463 symbol *lbl = newiTempLabel (NULL);
4464 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4465 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4466 emitcode ("cpl", "c");
4467 emitcode ("", "%05d$:", (lbl->key + 100));
4470 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4477 genIfxJump (ifx, "c");
4480 /* if the result is used in an arithmetic operation
4481 then put the result in place */
4486 gencjne (left, right, newiTempLabel (NULL));
4487 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4489 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4494 genIfxJump (ifx, "a");
4497 /* if the result is used in an arithmetic operation
4498 then put the result in place */
4499 if (AOP_TYPE (result) != AOP_CRY)
4501 /* leave the result in acc */
4505 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4506 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4507 freeAsmop (result, NULL, ic, TRUE);
4510 /*-----------------------------------------------------------------*/
4511 /* ifxForOp - returns the icode containing the ifx for operand */
4512 /*-----------------------------------------------------------------*/
4514 ifxForOp (operand * op, iCode * ic)
4516 /* if true symbol then needs to be assigned */
4517 if (IS_TRUE_SYMOP (op))
4520 /* if this has register type condition and
4521 the next instruction is ifx with the same operand
4522 and live to of the operand is upto the ifx only then */
4524 ic->next->op == IFX &&
4525 IC_COND (ic->next)->key == op->key &&
4526 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4532 /*-----------------------------------------------------------------*/
4533 /* hasInc - operand is incremented before any other use */
4534 /*-----------------------------------------------------------------*/
4536 hasInc (operand *op, iCode *ic,int osize)
4538 sym_link *type = operandType(op);
4539 sym_link *retype = getSpec (type);
4540 iCode *lic = ic->next;
4543 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4544 if (!IS_SYMOP(op)) return NULL;
4546 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4547 if (IS_AGGREGATE(type->next)) return NULL;
4548 if (osize != (isize = getSize(type->next))) return NULL;
4551 /* if operand of the form op = op + <sizeof *op> */
4552 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4553 isOperandEqual(IC_RESULT(lic),op) &&
4554 isOperandLiteral(IC_RIGHT(lic)) &&
4555 operandLitValue(IC_RIGHT(lic)) == isize) {
4558 /* if the operand used or deffed */
4559 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4562 /* if GOTO or IFX */
4563 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4569 /*-----------------------------------------------------------------*/
4570 /* genAndOp - for && operation */
4571 /*-----------------------------------------------------------------*/
4573 genAndOp (iCode * ic)
4575 operand *left, *right, *result;
4578 D(emitcode ("; genAndOp",""));
4580 /* note here that && operations that are in an
4581 if statement are taken away by backPatchLabels
4582 only those used in arthmetic operations remain */
4583 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4584 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4585 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4587 /* if both are bit variables */
4588 if (AOP_TYPE (left) == AOP_CRY &&
4589 AOP_TYPE (right) == AOP_CRY)
4591 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4592 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4597 tlbl = newiTempLabel (NULL);
4599 emitcode ("jz", "%05d$", tlbl->key + 100);
4601 emitcode ("", "%05d$:", tlbl->key + 100);
4605 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4606 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4607 freeAsmop (result, NULL, ic, TRUE);
4611 /*-----------------------------------------------------------------*/
4612 /* genOrOp - for || operation */
4613 /*-----------------------------------------------------------------*/
4615 genOrOp (iCode * ic)
4617 operand *left, *right, *result;
4620 D(emitcode ("; genOrOp",""));
4622 /* note here that || operations that are in an
4623 if statement are taken away by backPatchLabels
4624 only those used in arthmetic operations remain */
4625 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4626 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4627 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4629 /* if both are bit variables */
4630 if (AOP_TYPE (left) == AOP_CRY &&
4631 AOP_TYPE (right) == AOP_CRY)
4633 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4634 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4639 tlbl = newiTempLabel (NULL);
4641 emitcode ("jnz", "%05d$", tlbl->key + 100);
4643 emitcode ("", "%05d$:", tlbl->key + 100);
4647 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4648 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4649 freeAsmop (result, NULL, ic, TRUE);
4652 /*-----------------------------------------------------------------*/
4653 /* isLiteralBit - test if lit == 2^n */
4654 /*-----------------------------------------------------------------*/
4656 isLiteralBit (unsigned long lit)
4658 unsigned long pw[32] =
4659 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4660 0x100L, 0x200L, 0x400L, 0x800L,
4661 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4662 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4663 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4664 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4665 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4668 for (idx = 0; idx < 32; idx++)
4674 /*-----------------------------------------------------------------*/
4675 /* continueIfTrue - */
4676 /*-----------------------------------------------------------------*/
4678 continueIfTrue (iCode * ic)
4681 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4685 /*-----------------------------------------------------------------*/
4687 /*-----------------------------------------------------------------*/
4689 jumpIfTrue (iCode * ic)
4692 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4696 /*-----------------------------------------------------------------*/
4697 /* jmpTrueOrFalse - */
4698 /*-----------------------------------------------------------------*/
4700 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4702 // ugly but optimized by peephole
4705 symbol *nlbl = newiTempLabel (NULL);
4706 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4707 emitcode ("", "%05d$:", tlbl->key + 100);
4708 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4709 emitcode ("", "%05d$:", nlbl->key + 100);
4713 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4714 emitcode ("", "%05d$:", tlbl->key + 100);
4719 /*-----------------------------------------------------------------*/
4720 /* genAnd - code for and */
4721 /*-----------------------------------------------------------------*/
4723 genAnd (iCode * ic, iCode * ifx)
4725 operand *left, *right, *result;
4726 int size, offset = 0;
4727 unsigned long lit = 0L;
4731 D(emitcode ("; genAnd",""));
4733 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4734 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4735 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4738 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4740 AOP_TYPE (left), AOP_TYPE (right));
4741 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4743 AOP_SIZE (left), AOP_SIZE (right));
4746 /* if left is a literal & right is not then exchange them */
4747 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4748 AOP_NEEDSACC (left))
4750 operand *tmp = right;
4755 /* if result = right then exchange them */
4756 if (sameRegs (AOP (result), AOP (right)))
4758 operand *tmp = right;
4763 /* if right is bit then exchange them */
4764 if (AOP_TYPE (right) == AOP_CRY &&
4765 AOP_TYPE (left) != AOP_CRY)
4767 operand *tmp = right;
4771 if (AOP_TYPE (right) == AOP_LIT)
4772 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4774 size = AOP_SIZE (result);
4777 // result = bit & yy;
4778 if (AOP_TYPE (left) == AOP_CRY)
4780 // c = bit & literal;
4781 if (AOP_TYPE (right) == AOP_LIT)
4785 if (size && sameRegs (AOP (result), AOP (left)))
4788 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4793 if (size && (AOP_TYPE (result) == AOP_CRY))
4795 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4798 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4803 emitcode ("clr", "c");
4808 if (AOP_TYPE (right) == AOP_CRY)
4811 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4812 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4817 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4819 emitcode ("rrc", "a");
4820 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4828 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4829 genIfxJump (ifx, "c");
4833 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4834 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4835 if ((AOP_TYPE (right) == AOP_LIT) &&
4836 (AOP_TYPE (result) == AOP_CRY) &&
4837 (AOP_TYPE (left) != AOP_CRY))
4839 int posbit = isLiteralBit (lit);
4844 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4847 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4853 sprintf (buffer, "acc.%d", posbit & 0x07);
4854 genIfxJump (ifx, buffer);
4861 symbol *tlbl = newiTempLabel (NULL);
4862 int sizel = AOP_SIZE (left);
4864 emitcode ("setb", "c");
4867 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4869 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4871 if ((posbit = isLiteralBit (bytelit)) != 0)
4872 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4875 if (bytelit != 0x0FFL)
4876 emitcode ("anl", "a,%s",
4877 aopGet (AOP (right), offset, FALSE, TRUE));
4878 emitcode ("jnz", "%05d$", tlbl->key + 100);
4883 // bit = left & literal
4886 emitcode ("clr", "c");
4887 emitcode ("", "%05d$:", tlbl->key + 100);
4889 // if(left & literal)
4893 jmpTrueOrFalse (ifx, tlbl);
4901 /* if left is same as result */
4902 if (sameRegs (AOP (result), AOP (left)))
4904 for (; size--; offset++)
4906 if (AOP_TYPE (right) == AOP_LIT)
4908 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4910 else if (bytelit == 0)
4912 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4914 else if (IS_AOP_PREG (result))
4916 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4917 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4918 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4921 emitcode ("anl", "%s,%s",
4922 aopGet (AOP (left), offset, FALSE, TRUE),
4923 aopGet (AOP (right), offset, FALSE, FALSE));
4927 if (AOP_TYPE (left) == AOP_ACC)
4928 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4931 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4932 if (IS_AOP_PREG (result))
4934 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4935 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4939 emitcode ("anl", "%s,a",
4940 aopGet (AOP (left), offset, FALSE, TRUE));
4947 // left & result in different registers
4948 if (AOP_TYPE (result) == AOP_CRY)
4951 // if(size), result in bit
4952 // if(!size && ifx), conditional oper: if(left & right)
4953 symbol *tlbl = newiTempLabel (NULL);
4954 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4956 emitcode ("setb", "c");
4959 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4960 emitcode ("anl", "a,%s",
4961 aopGet (AOP (right), offset, FALSE, FALSE));
4963 if (AOP_TYPE(left)==AOP_ACC) {
4964 emitcode("mov", "b,a");
4965 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4966 emitcode("anl", "a,b");
4968 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4969 emitcode ("anl", "a,%s",
4970 aopGet (AOP (left), offset, FALSE, FALSE));
4973 emitcode ("jnz", "%05d$", tlbl->key + 100);
4979 emitcode ("", "%05d$:", tlbl->key + 100);
4983 jmpTrueOrFalse (ifx, tlbl);
4987 for (; (size--); offset++)
4990 // result = left & right
4991 if (AOP_TYPE (right) == AOP_LIT)
4993 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4995 aopPut (AOP (result),
4996 aopGet (AOP (left), offset, FALSE, FALSE),
4998 isOperandVolatile (result, FALSE));
5001 else if (bytelit == 0)
5003 /* dummy read of volatile operand */
5004 if (isOperandVolatile (left, FALSE))
5005 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5006 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5010 // faster than result <- left, anl result,right
5011 // and better if result is SFR
5012 if (AOP_TYPE (left) == AOP_ACC)
5013 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5016 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5017 emitcode ("anl", "a,%s",
5018 aopGet (AOP (left), offset, FALSE, FALSE));
5020 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5026 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5027 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5028 freeAsmop (result, NULL, ic, TRUE);
5031 /*-----------------------------------------------------------------*/
5032 /* genOr - code for or */
5033 /*-----------------------------------------------------------------*/
5035 genOr (iCode * ic, iCode * ifx)
5037 operand *left, *right, *result;
5038 int size, offset = 0;
5039 unsigned long lit = 0L;
5041 D(emitcode ("; genOr",""));
5043 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5044 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5045 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5048 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5050 AOP_TYPE (left), AOP_TYPE (right));
5051 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5053 AOP_SIZE (left), AOP_SIZE (right));
5056 /* if left is a literal & right is not then exchange them */
5057 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5058 AOP_NEEDSACC (left))
5060 operand *tmp = right;
5065 /* if result = right then exchange them */
5066 if (sameRegs (AOP (result), AOP (right)))
5068 operand *tmp = right;
5073 /* if right is bit then exchange them */
5074 if (AOP_TYPE (right) == AOP_CRY &&
5075 AOP_TYPE (left) != AOP_CRY)
5077 operand *tmp = right;
5081 if (AOP_TYPE (right) == AOP_LIT)
5082 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5084 size = AOP_SIZE (result);
5088 if (AOP_TYPE (left) == AOP_CRY)
5090 if (AOP_TYPE (right) == AOP_LIT)
5092 // c = bit | literal;
5095 // lit != 0 => result = 1
5096 if (AOP_TYPE (result) == AOP_CRY)
5099 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5101 continueIfTrue (ifx);
5104 emitcode ("setb", "c");
5108 // lit == 0 => result = left
5109 if (size && sameRegs (AOP (result), AOP (left)))
5111 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5116 if (AOP_TYPE (right) == AOP_CRY)
5119 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5120 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5125 symbol *tlbl = newiTempLabel (NULL);
5126 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5127 emitcode ("setb", "c");
5128 emitcode ("jb", "%s,%05d$",
5129 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5131 emitcode ("jnz", "%05d$", tlbl->key + 100);
5132 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5134 jmpTrueOrFalse (ifx, tlbl);
5140 emitcode ("", "%05d$:", tlbl->key + 100);
5149 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5150 genIfxJump (ifx, "c");
5154 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5155 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5156 if ((AOP_TYPE (right) == AOP_LIT) &&
5157 (AOP_TYPE (result) == AOP_CRY) &&
5158 (AOP_TYPE (left) != AOP_CRY))
5164 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5166 continueIfTrue (ifx);
5171 // lit = 0, result = boolean(left)
5173 emitcode ("setb", "c");
5177 symbol *tlbl = newiTempLabel (NULL);
5178 emitcode ("jnz", "%05d$", tlbl->key + 100);
5180 emitcode ("", "%05d$:", tlbl->key + 100);
5184 genIfxJump (ifx, "a");
5192 /* if left is same as result */
5193 if (sameRegs (AOP (result), AOP (left)))
5195 for (; size--; offset++)
5197 if (AOP_TYPE (right) == AOP_LIT)
5199 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5201 /* dummy read of volatile operand */
5202 if (isOperandVolatile (left, FALSE))
5203 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5207 else if (IS_AOP_PREG (left))
5209 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5210 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5211 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5214 emitcode ("orl", "%s,%s",
5215 aopGet (AOP (left), offset, FALSE, TRUE),
5216 aopGet (AOP (right), offset, FALSE, FALSE));
5220 if (AOP_TYPE (left) == AOP_ACC)
5221 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5224 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5225 if (IS_AOP_PREG (left))
5227 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5228 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5231 emitcode ("orl", "%s,a",
5232 aopGet (AOP (left), offset, FALSE, TRUE));
5239 // left & result in different registers
5240 if (AOP_TYPE (result) == AOP_CRY)
5243 // if(size), result in bit
5244 // if(!size && ifx), conditional oper: if(left | right)
5245 symbol *tlbl = newiTempLabel (NULL);
5246 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5248 emitcode ("setb", "c");
5251 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5252 emitcode ("orl", "a,%s",
5253 aopGet (AOP (right), offset, FALSE, FALSE));
5255 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5256 emitcode ("orl", "a,%s",
5257 aopGet (AOP (left), offset, FALSE, FALSE));
5259 emitcode ("jnz", "%05d$", tlbl->key + 100);
5265 emitcode ("", "%05d$:", tlbl->key + 100);
5269 jmpTrueOrFalse (ifx, tlbl);
5272 for (; (size--); offset++)
5275 // result = left & right
5276 if (AOP_TYPE (right) == AOP_LIT)
5278 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5280 aopPut (AOP (result),
5281 aopGet (AOP (left), offset, FALSE, FALSE),
5283 isOperandVolatile (result, FALSE));
5287 // faster than result <- left, anl result,right
5288 // and better if result is SFR
5289 if (AOP_TYPE (left) == AOP_ACC)
5290 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5293 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5294 emitcode ("orl", "a,%s",
5295 aopGet (AOP (left), offset, FALSE, FALSE));
5297 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5302 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5303 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5304 freeAsmop (result, NULL, ic, TRUE);
5307 /*-----------------------------------------------------------------*/
5308 /* genXor - code for xclusive or */
5309 /*-----------------------------------------------------------------*/
5311 genXor (iCode * ic, iCode * ifx)
5313 operand *left, *right, *result;
5314 int size, offset = 0;
5315 unsigned long lit = 0L;
5317 D(emitcode ("; genXor",""));
5319 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5320 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5321 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5324 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5326 AOP_TYPE (left), AOP_TYPE (right));
5327 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5329 AOP_SIZE (left), AOP_SIZE (right));
5332 /* if left is a literal & right is not ||
5333 if left needs acc & right does not */
5334 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5335 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5337 operand *tmp = right;
5342 /* if result = right then exchange them */
5343 if (sameRegs (AOP (result), AOP (right)))
5345 operand *tmp = right;
5350 /* if right is bit then exchange them */
5351 if (AOP_TYPE (right) == AOP_CRY &&
5352 AOP_TYPE (left) != AOP_CRY)
5354 operand *tmp = right;
5358 if (AOP_TYPE (right) == AOP_LIT)
5359 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5361 size = AOP_SIZE (result);
5365 if (AOP_TYPE (left) == AOP_CRY)
5367 if (AOP_TYPE (right) == AOP_LIT)
5369 // c = bit & literal;
5372 // lit>>1 != 0 => result = 1
5373 if (AOP_TYPE (result) == AOP_CRY)
5376 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5378 continueIfTrue (ifx);
5381 emitcode ("setb", "c");
5388 // lit == 0, result = left
5389 if (size && sameRegs (AOP (result), AOP (left)))
5391 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5395 // lit == 1, result = not(left)
5396 if (size && sameRegs (AOP (result), AOP (left)))
5398 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5403 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5404 emitcode ("cpl", "c");
5413 symbol *tlbl = newiTempLabel (NULL);
5414 if (AOP_TYPE (right) == AOP_CRY)
5417 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5421 int sizer = AOP_SIZE (right);
5423 // if val>>1 != 0, result = 1
5424 emitcode ("setb", "c");
5427 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5429 // test the msb of the lsb
5430 emitcode ("anl", "a,#0xfe");
5431 emitcode ("jnz", "%05d$", tlbl->key + 100);
5435 emitcode ("rrc", "a");
5437 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5438 emitcode ("cpl", "c");
5439 emitcode ("", "%05d$:", (tlbl->key + 100));
5446 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5447 genIfxJump (ifx, "c");
5451 if (sameRegs (AOP (result), AOP (left)))
5453 /* if left is same as result */
5454 for (; size--; offset++)
5456 if (AOP_TYPE (right) == AOP_LIT)
5458 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5460 else if (IS_AOP_PREG (left))
5462 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5463 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5464 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5467 emitcode ("xrl", "%s,%s",
5468 aopGet (AOP (left), offset, FALSE, TRUE),
5469 aopGet (AOP (right), offset, FALSE, FALSE));
5473 if (AOP_TYPE (left) == AOP_ACC)
5474 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5477 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5478 if (IS_AOP_PREG (left))
5480 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5481 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5484 emitcode ("xrl", "%s,a",
5485 aopGet (AOP (left), offset, FALSE, TRUE));
5492 // left & result in different registers
5493 if (AOP_TYPE (result) == AOP_CRY)
5496 // if(size), result in bit
5497 // if(!size && ifx), conditional oper: if(left ^ right)
5498 symbol *tlbl = newiTempLabel (NULL);
5499 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5501 emitcode ("setb", "c");
5504 if ((AOP_TYPE (right) == AOP_LIT) &&
5505 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5507 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5511 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5512 emitcode ("xrl", "a,%s",
5513 aopGet (AOP (right), offset, FALSE, FALSE));
5515 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5516 emitcode ("xrl", "a,%s",
5517 aopGet (AOP (left), offset, FALSE, FALSE));
5520 emitcode ("jnz", "%05d$", tlbl->key + 100);
5526 emitcode ("", "%05d$:", tlbl->key + 100);
5530 jmpTrueOrFalse (ifx, tlbl);
5533 for (; (size--); offset++)
5536 // result = left & right
5537 if (AOP_TYPE (right) == AOP_LIT)
5539 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5541 aopPut (AOP (result),
5542 aopGet (AOP (left), offset, FALSE, FALSE),
5544 isOperandVolatile (result, FALSE));
5548 // faster than result <- left, anl result,right
5549 // and better if result is SFR
5550 if (AOP_TYPE (left) == AOP_ACC)
5551 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5554 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5555 emitcode ("xrl", "a,%s",
5556 aopGet (AOP (left), offset, FALSE, TRUE));
5558 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5563 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5564 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5565 freeAsmop (result, NULL, ic, TRUE);
5568 /*-----------------------------------------------------------------*/
5569 /* genInline - write the inline code out */
5570 /*-----------------------------------------------------------------*/
5572 genInline (iCode * ic)
5574 char *buffer, *bp, *bp1;
5576 D(emitcode ("; genInline",""));
5578 _G.inLine += (!options.asmpeep);
5580 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5581 strcpy (buffer, IC_INLINE (ic));
5583 /* emit each line as a code */
5608 /* emitcode("",buffer); */
5609 _G.inLine -= (!options.asmpeep);
5612 /*-----------------------------------------------------------------*/
5613 /* genRRC - rotate right with carry */
5614 /*-----------------------------------------------------------------*/
5618 operand *left, *result;
5619 int size, offset = 0;
5622 D(emitcode ("; genRRC",""));
5624 /* rotate right with carry */
5625 left = IC_LEFT (ic);
5626 result = IC_RESULT (ic);
5627 aopOp (left, ic, FALSE);
5628 aopOp (result, ic, FALSE);
5630 /* move it to the result */
5631 size = AOP_SIZE (result);
5633 if (size == 1) { /* special case for 1 byte */
5634 l = aopGet (AOP (left), offset, FALSE, FALSE);
5636 emitcode ("rr", "a");
5642 l = aopGet (AOP (left), offset, FALSE, FALSE);
5644 emitcode ("rrc", "a");
5645 if (AOP_SIZE (result) > 1)
5646 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5648 /* now we need to put the carry into the
5649 highest order byte of the result */
5650 if (AOP_SIZE (result) > 1)
5652 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5655 emitcode ("mov", "acc.7,c");
5657 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5658 freeAsmop (left, NULL, ic, TRUE);
5659 freeAsmop (result, NULL, ic, TRUE);
5662 /*-----------------------------------------------------------------*/
5663 /* genRLC - generate code for rotate left with carry */
5664 /*-----------------------------------------------------------------*/
5668 operand *left, *result;
5669 int size, offset = 0;
5672 D(emitcode ("; genRLC",""));
5674 /* rotate right with carry */
5675 left = IC_LEFT (ic);
5676 result = IC_RESULT (ic);
5677 aopOp (left, ic, FALSE);
5678 aopOp (result, ic, FALSE);
5680 /* move it to the result */
5681 size = AOP_SIZE (result);
5685 l = aopGet (AOP (left), offset, FALSE, FALSE);
5687 if (size == 0) { /* special case for 1 byte */
5691 emitcode ("add", "a,acc");
5692 if (AOP_SIZE (result) > 1)
5693 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5696 l = aopGet (AOP (left), offset, FALSE, FALSE);
5698 emitcode ("rlc", "a");
5699 if (AOP_SIZE (result) > 1)
5700 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5703 /* now we need to put the carry into the
5704 highest order byte of the result */
5705 if (AOP_SIZE (result) > 1)
5707 l = aopGet (AOP (result), 0, FALSE, FALSE);
5710 emitcode ("mov", "acc.0,c");
5712 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5713 freeAsmop (left, NULL, ic, TRUE);
5714 freeAsmop (result, NULL, ic, TRUE);
5717 /*-----------------------------------------------------------------*/
5718 /* genGetHbit - generates code get highest order bit */
5719 /*-----------------------------------------------------------------*/
5721 genGetHbit (iCode * ic)
5723 operand *left, *result;
5725 D(emitcode ("; genGetHbit",""));
5727 left = IC_LEFT (ic);
5728 result = IC_RESULT (ic);
5729 aopOp (left, ic, FALSE);
5730 aopOp (result, ic, FALSE);
5732 /* get the highest order byte into a */
5733 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5734 if (AOP_TYPE (result) == AOP_CRY)
5736 emitcode ("rlc", "a");
5741 emitcode ("rl", "a");
5742 emitcode ("anl", "a,#0x01");
5747 freeAsmop (left, NULL, ic, TRUE);
5748 freeAsmop (result, NULL, ic, TRUE);
5751 /*-----------------------------------------------------------------*/
5752 /* AccRol - rotate left accumulator by known count */
5753 /*-----------------------------------------------------------------*/
5755 AccRol (int shCount)
5757 shCount &= 0x0007; // shCount : 0..7
5764 emitcode ("rl", "a");
5767 emitcode ("rl", "a");
5768 emitcode ("rl", "a");
5771 emitcode ("swap", "a");
5772 emitcode ("rr", "a");
5775 emitcode ("swap", "a");
5778 emitcode ("swap", "a");
5779 emitcode ("rl", "a");
5782 emitcode ("rr", "a");
5783 emitcode ("rr", "a");
5786 emitcode ("rr", "a");
5791 /*-----------------------------------------------------------------*/
5792 /* AccLsh - left shift accumulator by known count */
5793 /*-----------------------------------------------------------------*/
5795 AccLsh (int shCount)
5800 emitcode ("add", "a,acc");
5801 else if (shCount == 2)
5803 emitcode ("add", "a,acc");
5804 emitcode ("add", "a,acc");
5808 /* rotate left accumulator */
5810 /* and kill the lower order bits */
5811 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5816 /*-----------------------------------------------------------------*/
5817 /* AccRsh - right shift accumulator by known count */
5818 /*-----------------------------------------------------------------*/
5820 AccRsh (int shCount)
5827 emitcode ("rrc", "a");
5831 /* rotate right accumulator */
5832 AccRol (8 - shCount);
5833 /* and kill the higher order bits */
5834 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5839 /*-----------------------------------------------------------------*/
5840 /* AccSRsh - signed right shift accumulator by known count */
5841 /*-----------------------------------------------------------------*/
5843 AccSRsh (int shCount)
5850 emitcode ("mov", "c,acc.7");
5851 emitcode ("rrc", "a");
5853 else if (shCount == 2)
5855 emitcode ("mov", "c,acc.7");
5856 emitcode ("rrc", "a");
5857 emitcode ("mov", "c,acc.7");
5858 emitcode ("rrc", "a");
5862 tlbl = newiTempLabel (NULL);
5863 /* rotate right accumulator */
5864 AccRol (8 - shCount);
5865 /* and kill the higher order bits */
5866 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5867 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5868 emitcode ("orl", "a,#0x%02x",
5869 (unsigned char) ~SRMask[shCount]);
5870 emitcode ("", "%05d$:", tlbl->key + 100);
5875 /*-----------------------------------------------------------------*/
5876 /* shiftR1Left2Result - shift right one byte from left to result */
5877 /*-----------------------------------------------------------------*/
5879 shiftR1Left2Result (operand * left, int offl,
5880 operand * result, int offr,
5881 int shCount, int sign)
5883 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5884 /* shift right accumulator */
5889 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5892 /*-----------------------------------------------------------------*/
5893 /* shiftL1Left2Result - shift left one byte from left to result */
5894 /*-----------------------------------------------------------------*/
5896 shiftL1Left2Result (operand * left, int offl,
5897 operand * result, int offr, int shCount)
5900 l = aopGet (AOP (left), offl, FALSE, FALSE);
5902 /* shift left accumulator */
5904 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5907 /*-----------------------------------------------------------------*/
5908 /* movLeft2Result - move byte from left to result */
5909 /*-----------------------------------------------------------------*/
5911 movLeft2Result (operand * left, int offl,
5912 operand * result, int offr, int sign)
5915 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5917 l = aopGet (AOP (left), offl, FALSE, FALSE);
5919 if (*l == '@' && (IS_AOP_PREG (result)))
5921 emitcode ("mov", "a,%s", l);
5922 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5927 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
5930 /* MSB sign in acc.7 ! */
5931 if (getDataSize (left) == offl + 1)
5933 emitcode ("mov", "a,%s", l);
5934 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5941 /*-----------------------------------------------------------------*/
5942 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5943 /*-----------------------------------------------------------------*/
5947 emitcode ("rrc", "a");
5948 emitcode ("xch", "a,%s", x);
5949 emitcode ("rrc", "a");
5950 emitcode ("xch", "a,%s", x);
5953 /*-----------------------------------------------------------------*/
5954 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5955 /*-----------------------------------------------------------------*/
5959 emitcode ("xch", "a,%s", x);
5960 emitcode ("rlc", "a");
5961 emitcode ("xch", "a,%s", x);
5962 emitcode ("rlc", "a");
5965 /*-----------------------------------------------------------------*/
5966 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5967 /*-----------------------------------------------------------------*/
5971 emitcode ("xch", "a,%s", x);
5972 emitcode ("add", "a,acc");
5973 emitcode ("xch", "a,%s", x);
5974 emitcode ("rlc", "a");
5977 /*-----------------------------------------------------------------*/
5978 /* AccAXLsh - left shift a:x by known count (0..7) */
5979 /*-----------------------------------------------------------------*/
5981 AccAXLsh (char *x, int shCount)
5996 case 5: // AAAAABBB:CCCCCDDD
5998 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6000 emitcode ("anl", "a,#0x%02x",
6001 SLMask[shCount]); // BBB00000:CCCCCDDD
6003 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6005 AccRol (shCount); // DDDCCCCC:BBB00000
6007 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6009 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6011 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6013 emitcode ("anl", "a,#0x%02x",
6014 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6016 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6018 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6021 case 6: // AAAAAABB:CCCCCCDD
6022 emitcode ("anl", "a,#0x%02x",
6023 SRMask[shCount]); // 000000BB:CCCCCCDD
6024 emitcode ("mov", "c,acc.0"); // c = B
6025 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6027 AccAXRrl1 (x); // BCCCCCCD:D000000B
6028 AccAXRrl1 (x); // BBCCCCCC:DD000000
6030 emitcode("rrc","a");
6031 emitcode("xch","a,%s", x);
6032 emitcode("rrc","a");
6033 emitcode("mov","c,acc.0"); //<< get correct bit
6034 emitcode("xch","a,%s", x);
6036 emitcode("rrc","a");
6037 emitcode("xch","a,%s", x);
6038 emitcode("rrc","a");
6039 emitcode("xch","a,%s", x);
6042 case 7: // a:x <<= 7
6044 emitcode ("anl", "a,#0x%02x",
6045 SRMask[shCount]); // 0000000B:CCCCCCCD
6047 emitcode ("mov", "c,acc.0"); // c = B
6049 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6051 AccAXRrl1 (x); // BCCCCCCC:D0000000
6059 /*-----------------------------------------------------------------*/
6060 /* AccAXRsh - right shift a:x known count (0..7) */
6061 /*-----------------------------------------------------------------*/
6063 AccAXRsh (char *x, int shCount)
6071 AccAXRrl1 (x); // 0->a:x
6076 AccAXRrl1 (x); // 0->a:x
6079 AccAXRrl1 (x); // 0->a:x
6084 case 5: // AAAAABBB:CCCCCDDD = a:x
6086 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6088 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6090 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6092 emitcode ("anl", "a,#0x%02x",
6093 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6095 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6097 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6099 emitcode ("anl", "a,#0x%02x",
6100 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6102 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6104 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6106 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6109 case 6: // AABBBBBB:CCDDDDDD
6111 emitcode ("mov", "c,acc.7");
6112 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6114 emitcode ("mov", "c,acc.7");
6115 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6117 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6119 emitcode ("anl", "a,#0x%02x",
6120 SRMask[shCount]); // 000000AA:BBBBBBCC
6123 case 7: // ABBBBBBB:CDDDDDDD
6125 emitcode ("mov", "c,acc.7"); // c = A
6127 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6129 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6131 emitcode ("anl", "a,#0x%02x",
6132 SRMask[shCount]); // 0000000A:BBBBBBBC
6140 /*-----------------------------------------------------------------*/
6141 /* AccAXRshS - right shift signed a:x known count (0..7) */
6142 /*-----------------------------------------------------------------*/
6144 AccAXRshS (char *x, int shCount)
6152 emitcode ("mov", "c,acc.7");
6153 AccAXRrl1 (x); // s->a:x
6157 emitcode ("mov", "c,acc.7");
6158 AccAXRrl1 (x); // s->a:x
6160 emitcode ("mov", "c,acc.7");
6161 AccAXRrl1 (x); // s->a:x
6166 case 5: // AAAAABBB:CCCCCDDD = a:x
6168 tlbl = newiTempLabel (NULL);
6169 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6171 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6173 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6175 emitcode ("anl", "a,#0x%02x",
6176 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6178 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6180 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6182 emitcode ("anl", "a,#0x%02x",
6183 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6185 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6187 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6189 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6191 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6192 emitcode ("orl", "a,#0x%02x",
6193 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6195 emitcode ("", "%05d$:", tlbl->key + 100);
6196 break; // SSSSAAAA:BBBCCCCC
6198 case 6: // AABBBBBB:CCDDDDDD
6200 tlbl = newiTempLabel (NULL);
6201 emitcode ("mov", "c,acc.7");
6202 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6204 emitcode ("mov", "c,acc.7");
6205 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6207 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6209 emitcode ("anl", "a,#0x%02x",
6210 SRMask[shCount]); // 000000AA:BBBBBBCC
6212 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6213 emitcode ("orl", "a,#0x%02x",
6214 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6216 emitcode ("", "%05d$:", tlbl->key + 100);
6218 case 7: // ABBBBBBB:CDDDDDDD
6220 tlbl = newiTempLabel (NULL);
6221 emitcode ("mov", "c,acc.7"); // c = A
6223 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6225 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6227 emitcode ("anl", "a,#0x%02x",
6228 SRMask[shCount]); // 0000000A:BBBBBBBC
6230 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6231 emitcode ("orl", "a,#0x%02x",
6232 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6234 emitcode ("", "%05d$:", tlbl->key + 100);
6241 /*-----------------------------------------------------------------*/
6242 /* shiftL2Left2Result - shift left two bytes from left to result */
6243 /*-----------------------------------------------------------------*/
6245 shiftL2Left2Result (operand * left, int offl,
6246 operand * result, int offr, int shCount)
6248 if (sameRegs (AOP (result), AOP (left)) &&
6249 ((offl + MSB16) == offr))
6251 /* don't crash result[offr] */
6252 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6253 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6257 movLeft2Result (left, offl, result, offr, 0);
6258 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6260 /* ax << shCount (x = lsb(result)) */
6261 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6262 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6266 /*-----------------------------------------------------------------*/
6267 /* shiftR2Left2Result - shift right two bytes from left to result */
6268 /*-----------------------------------------------------------------*/
6270 shiftR2Left2Result (operand * left, int offl,
6271 operand * result, int offr,
6272 int shCount, int sign)
6274 if (sameRegs (AOP (result), AOP (left)) &&
6275 ((offl + MSB16) == offr))
6277 /* don't crash result[offr] */
6278 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6279 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6283 movLeft2Result (left, offl, result, offr, 0);
6284 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6286 /* a:x >> shCount (x = lsb(result)) */
6288 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6290 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6291 if (getDataSize (result) > 1)
6292 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6295 /*-----------------------------------------------------------------*/
6296 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6297 /*-----------------------------------------------------------------*/
6299 shiftLLeftOrResult (operand * left, int offl,
6300 operand * result, int offr, int shCount)
6302 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6303 /* shift left accumulator */
6305 /* or with result */
6306 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6307 /* back to result */
6308 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6311 /*-----------------------------------------------------------------*/
6312 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6313 /*-----------------------------------------------------------------*/
6315 shiftRLeftOrResult (operand * left, int offl,
6316 operand * result, int offr, int shCount)
6318 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6319 /* shift right accumulator */
6321 /* or with result */
6322 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6323 /* back to result */
6324 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6327 /*-----------------------------------------------------------------*/
6328 /* genlshOne - left shift a one byte quantity by known count */
6329 /*-----------------------------------------------------------------*/
6331 genlshOne (operand * result, operand * left, int shCount)
6333 D(emitcode ("; genlshOne",""));
6335 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6338 /*-----------------------------------------------------------------*/
6339 /* genlshTwo - left shift two bytes by known amount != 0 */
6340 /*-----------------------------------------------------------------*/
6342 genlshTwo (operand * result, operand * left, int shCount)
6346 D(emitcode ("; genlshTwo",""));
6348 size = getDataSize (result);
6350 /* if shCount >= 8 */
6358 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6360 movLeft2Result (left, LSB, result, MSB16, 0);
6362 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6365 /* 1 <= shCount <= 7 */
6369 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6371 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6375 /*-----------------------------------------------------------------*/
6376 /* shiftLLong - shift left one long from left to result */
6377 /* offl = LSB or MSB16 */
6378 /*-----------------------------------------------------------------*/
6380 shiftLLong (operand * left, operand * result, int offr)
6383 int size = AOP_SIZE (result);
6385 if (size >= LSB + offr)
6387 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6389 emitcode ("add", "a,acc");
6390 if (sameRegs (AOP (left), AOP (result)) &&
6391 size >= MSB16 + offr && offr != LSB)
6392 emitcode ("xch", "a,%s",
6393 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6395 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6398 if (size >= MSB16 + offr)
6400 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6402 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6405 emitcode ("rlc", "a");
6406 if (sameRegs (AOP (left), AOP (result)) &&
6407 size >= MSB24 + offr && offr != LSB)
6408 emitcode ("xch", "a,%s",
6409 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6411 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6414 if (size >= MSB24 + offr)
6416 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6418 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6421 emitcode ("rlc", "a");
6422 if (sameRegs (AOP (left), AOP (result)) &&
6423 size >= MSB32 + offr && offr != LSB)
6424 emitcode ("xch", "a,%s",
6425 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6427 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6430 if (size > MSB32 + offr)
6432 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6434 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6437 emitcode ("rlc", "a");
6438 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6441 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6444 /*-----------------------------------------------------------------*/
6445 /* genlshFour - shift four byte by a known amount != 0 */
6446 /*-----------------------------------------------------------------*/
6448 genlshFour (operand * result, operand * left, int shCount)
6452 D(emitcode ("; genlshFour",""));
6454 size = AOP_SIZE (result);
6456 /* if shifting more that 3 bytes */
6461 /* lowest order of left goes to the highest
6462 order of the destination */
6463 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6465 movLeft2Result (left, LSB, result, MSB32, 0);
6466 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6467 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6468 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6472 /* more than two bytes */
6473 else if (shCount >= 16)
6475 /* lower order two bytes goes to higher order two bytes */
6477 /* if some more remaining */
6479 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6482 movLeft2Result (left, MSB16, result, MSB32, 0);
6483 movLeft2Result (left, LSB, result, MSB24, 0);
6485 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6486 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6490 /* if more than 1 byte */
6491 else if (shCount >= 8)
6493 /* lower order three bytes goes to higher order three bytes */
6498 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6500 movLeft2Result (left, LSB, result, MSB16, 0);
6506 movLeft2Result (left, MSB24, result, MSB32, 0);
6507 movLeft2Result (left, MSB16, result, MSB24, 0);
6508 movLeft2Result (left, LSB, result, MSB16, 0);
6509 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6511 else if (shCount == 1)
6512 shiftLLong (left, result, MSB16);
6515 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6516 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6517 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6518 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6523 /* 1 <= shCount <= 7 */
6524 else if (shCount <= 2)
6526 shiftLLong (left, result, LSB);
6528 shiftLLong (result, result, LSB);
6530 /* 3 <= shCount <= 7, optimize */
6533 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6534 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6535 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6539 /*-----------------------------------------------------------------*/
6540 /* genLeftShiftLiteral - left shifting by known count */
6541 /*-----------------------------------------------------------------*/
6543 genLeftShiftLiteral (operand * left,
6548 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6551 D(emitcode ("; genLeftShiftLiteral",""));
6553 freeAsmop (right, NULL, ic, TRUE);
6555 aopOp (left, ic, FALSE);
6556 aopOp (result, ic, FALSE);
6558 size = getSize (operandType (result));
6561 emitcode ("; shift left ", "result %d, left %d", size,
6565 /* I suppose that the left size >= result size */
6570 movLeft2Result (left, size, result, size, 0);
6574 else if (shCount >= (size * 8))
6576 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6582 genlshOne (result, left, shCount);
6586 genlshTwo (result, left, shCount);
6590 genlshFour (result, left, shCount);
6593 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6594 "*** ack! mystery literal shift!\n");
6598 freeAsmop (left, NULL, ic, TRUE);
6599 freeAsmop (result, NULL, ic, TRUE);
6602 /*-----------------------------------------------------------------*/
6603 /* genLeftShift - generates code for left shifting */
6604 /*-----------------------------------------------------------------*/
6606 genLeftShift (iCode * ic)
6608 operand *left, *right, *result;
6611 symbol *tlbl, *tlbl1;
6613 D(emitcode ("; genLeftShift",""));
6615 right = IC_RIGHT (ic);
6616 left = IC_LEFT (ic);
6617 result = IC_RESULT (ic);
6619 aopOp (right, ic, FALSE);
6621 /* if the shift count is known then do it
6622 as efficiently as possible */
6623 if (AOP_TYPE (right) == AOP_LIT)
6625 genLeftShiftLiteral (left, right, result, ic);
6629 /* shift count is unknown then we have to form
6630 a loop get the loop count in B : Note: we take
6631 only the lower order byte since shifting
6632 more that 32 bits make no sense anyway, ( the
6633 largest size of an object can be only 32 bits ) */
6635 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6636 emitcode ("inc", "b");
6637 freeAsmop (right, NULL, ic, TRUE);
6638 aopOp (left, ic, FALSE);
6639 aopOp (result, ic, FALSE);
6641 /* now move the left to the result if they are not the
6643 if (!sameRegs (AOP (left), AOP (result)) &&
6644 AOP_SIZE (result) > 1)
6647 size = AOP_SIZE (result);
6651 l = aopGet (AOP (left), offset, FALSE, TRUE);
6652 if (*l == '@' && (IS_AOP_PREG (result)))
6655 emitcode ("mov", "a,%s", l);
6656 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6659 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6664 tlbl = newiTempLabel (NULL);
6665 size = AOP_SIZE (result);
6667 tlbl1 = newiTempLabel (NULL);
6669 /* if it is only one byte then */
6672 symbol *tlbl1 = newiTempLabel (NULL);
6674 l = aopGet (AOP (left), 0, FALSE, FALSE);
6676 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6677 emitcode ("", "%05d$:", tlbl->key + 100);
6678 emitcode ("add", "a,acc");
6679 emitcode ("", "%05d$:", tlbl1->key + 100);
6680 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6681 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6685 reAdjustPreg (AOP (result));
6687 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6688 emitcode ("", "%05d$:", tlbl->key + 100);
6689 l = aopGet (AOP (result), offset, FALSE, FALSE);
6691 emitcode ("add", "a,acc");
6692 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6695 l = aopGet (AOP (result), offset, FALSE, FALSE);
6697 emitcode ("rlc", "a");
6698 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6700 reAdjustPreg (AOP (result));
6702 emitcode ("", "%05d$:", tlbl1->key + 100);
6703 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6705 freeAsmop (left, NULL, ic, TRUE);
6706 freeAsmop (result, NULL, ic, TRUE);
6709 /*-----------------------------------------------------------------*/
6710 /* genrshOne - right shift a one byte quantity by known count */
6711 /*-----------------------------------------------------------------*/
6713 genrshOne (operand * result, operand * left,
6714 int shCount, int sign)
6716 D(emitcode ("; genrshOne",""));
6718 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6721 /*-----------------------------------------------------------------*/
6722 /* genrshTwo - right shift two bytes by known amount != 0 */
6723 /*-----------------------------------------------------------------*/
6725 genrshTwo (operand * result, operand * left,
6726 int shCount, int sign)
6728 D(emitcode ("; genrshTwo",""));
6730 /* if shCount >= 8 */
6735 shiftR1Left2Result (left, MSB16, result, LSB,
6738 movLeft2Result (left, MSB16, result, LSB, sign);
6739 addSign (result, MSB16, sign);
6742 /* 1 <= shCount <= 7 */
6744 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6747 /*-----------------------------------------------------------------*/
6748 /* shiftRLong - shift right one long from left to result */
6749 /* offl = LSB or MSB16 */
6750 /*-----------------------------------------------------------------*/
6752 shiftRLong (operand * left, int offl,
6753 operand * result, int sign)
6755 int isSameRegs=sameRegs(AOP(left),AOP(result));
6757 if (isSameRegs && offl>1) {
6758 // we are in big trouble, but this shouldn't happen
6759 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6762 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6767 emitcode ("rlc", "a");
6768 emitcode ("subb", "a,acc");
6770 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6772 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6773 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6776 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6781 emitcode ("clr", "c");
6783 emitcode ("mov", "c,acc.7");
6786 emitcode ("rrc", "a");
6788 if (isSameRegs && offl==MSB16) {
6789 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6791 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6792 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6795 emitcode ("rrc", "a");
6796 if (isSameRegs && offl==1) {
6797 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6799 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6800 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6802 emitcode ("rrc", "a");
6803 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6807 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6808 emitcode ("rrc", "a");
6809 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6813 /*-----------------------------------------------------------------*/
6814 /* genrshFour - shift four byte by a known amount != 0 */
6815 /*-----------------------------------------------------------------*/
6817 genrshFour (operand * result, operand * left,
6818 int shCount, int sign)
6820 D(emitcode ("; genrshFour",""));
6822 /* if shifting more that 3 bytes */
6827 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6829 movLeft2Result (left, MSB32, result, LSB, sign);
6830 addSign (result, MSB16, sign);
6832 else if (shCount >= 16)
6836 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6839 movLeft2Result (left, MSB24, result, LSB, 0);
6840 movLeft2Result (left, MSB32, result, MSB16, sign);
6842 addSign (result, MSB24, sign);
6844 else if (shCount >= 8)
6848 shiftRLong (left, MSB16, result, sign);
6849 else if (shCount == 0)
6851 movLeft2Result (left, MSB16, result, LSB, 0);
6852 movLeft2Result (left, MSB24, result, MSB16, 0);
6853 movLeft2Result (left, MSB32, result, MSB24, sign);
6854 addSign (result, MSB32, sign);
6858 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6859 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6860 /* the last shift is signed */
6861 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6862 addSign (result, MSB32, sign);
6866 { /* 1 <= shCount <= 7 */
6869 shiftRLong (left, LSB, result, sign);
6871 shiftRLong (result, LSB, result, sign);
6875 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6876 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6877 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6882 /*-----------------------------------------------------------------*/
6883 /* genRightShiftLiteral - right shifting by known count */
6884 /*-----------------------------------------------------------------*/
6886 genRightShiftLiteral (operand * left,
6892 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6895 D(emitcode ("; genRightShiftLiteral",""));
6897 freeAsmop (right, NULL, ic, TRUE);
6899 aopOp (left, ic, FALSE);
6900 aopOp (result, ic, FALSE);
6903 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6907 size = getDataSize (left);
6908 /* test the LEFT size !!! */
6910 /* I suppose that the left size >= result size */
6913 size = getDataSize (result);
6915 movLeft2Result (left, size, result, size, 0);
6918 else if (shCount >= (size * 8))
6921 /* get sign in acc.7 */
6922 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6924 addSign (result, LSB, sign);
6931 genrshOne (result, left, shCount, sign);
6935 genrshTwo (result, left, shCount, sign);
6939 genrshFour (result, left, shCount, sign);
6945 freeAsmop (left, NULL, ic, TRUE);
6946 freeAsmop (result, NULL, ic, TRUE);
6949 /*-----------------------------------------------------------------*/
6950 /* genSignedRightShift - right shift of signed number */
6951 /*-----------------------------------------------------------------*/
6953 genSignedRightShift (iCode * ic)
6955 operand *right, *left, *result;
6958 symbol *tlbl, *tlbl1;
6960 D(emitcode ("; genSignedRightShift",""));
6962 /* we do it the hard way put the shift count in b
6963 and loop thru preserving the sign */
6965 right = IC_RIGHT (ic);
6966 left = IC_LEFT (ic);
6967 result = IC_RESULT (ic);
6969 aopOp (right, ic, FALSE);
6972 if (AOP_TYPE (right) == AOP_LIT)
6974 genRightShiftLiteral (left, right, result, ic, 1);
6977 /* shift count is unknown then we have to form
6978 a loop get the loop count in B : Note: we take
6979 only the lower order byte since shifting
6980 more that 32 bits make no sense anyway, ( the
6981 largest size of an object can be only 32 bits ) */
6983 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6984 emitcode ("inc", "b");
6985 freeAsmop (right, NULL, ic, TRUE);
6986 aopOp (left, ic, FALSE);
6987 aopOp (result, ic, FALSE);
6989 /* now move the left to the result if they are not the
6991 if (!sameRegs (AOP (left), AOP (result)) &&
6992 AOP_SIZE (result) > 1)
6995 size = AOP_SIZE (result);
6999 l = aopGet (AOP (left), offset, FALSE, TRUE);
7000 if (*l == '@' && IS_AOP_PREG (result))
7003 emitcode ("mov", "a,%s", l);
7004 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7007 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7012 /* mov the highest order bit to OVR */
7013 tlbl = newiTempLabel (NULL);
7014 tlbl1 = newiTempLabel (NULL);
7016 size = AOP_SIZE (result);
7018 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7019 emitcode ("rlc", "a");
7020 emitcode ("mov", "ov,c");
7021 /* if it is only one byte then */
7024 l = aopGet (AOP (left), 0, FALSE, FALSE);
7026 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7027 emitcode ("", "%05d$:", tlbl->key + 100);
7028 emitcode ("mov", "c,ov");
7029 emitcode ("rrc", "a");
7030 emitcode ("", "%05d$:", tlbl1->key + 100);
7031 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7032 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7036 reAdjustPreg (AOP (result));
7037 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7038 emitcode ("", "%05d$:", tlbl->key + 100);
7039 emitcode ("mov", "c,ov");
7042 l = aopGet (AOP (result), offset, FALSE, FALSE);
7044 emitcode ("rrc", "a");
7045 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7047 reAdjustPreg (AOP (result));
7048 emitcode ("", "%05d$:", tlbl1->key + 100);
7049 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7052 freeAsmop (left, NULL, ic, TRUE);
7053 freeAsmop (result, NULL, ic, TRUE);
7056 /*-----------------------------------------------------------------*/
7057 /* genRightShift - generate code for right shifting */
7058 /*-----------------------------------------------------------------*/
7060 genRightShift (iCode * ic)
7062 operand *right, *left, *result;
7066 symbol *tlbl, *tlbl1;
7068 D(emitcode ("; genRightShift",""));
7070 /* if signed then we do it the hard way preserve the
7071 sign bit moving it inwards */
7072 retype = getSpec (operandType (IC_RESULT (ic)));
7074 if (!SPEC_USIGN (retype))
7076 genSignedRightShift (ic);
7080 /* signed & unsigned types are treated the same : i.e. the
7081 signed is NOT propagated inwards : quoting from the
7082 ANSI - standard : "for E1 >> E2, is equivalent to division
7083 by 2**E2 if unsigned or if it has a non-negative value,
7084 otherwise the result is implementation defined ", MY definition
7085 is that the sign does not get propagated */
7087 right = IC_RIGHT (ic);
7088 left = IC_LEFT (ic);
7089 result = IC_RESULT (ic);
7091 aopOp (right, ic, FALSE);
7093 /* if the shift count is known then do it
7094 as efficiently as possible */
7095 if (AOP_TYPE (right) == AOP_LIT)
7097 genRightShiftLiteral (left, right, result, ic, 0);
7101 /* shift count is unknown then we have to form
7102 a loop get the loop count in B : Note: we take
7103 only the lower order byte since shifting
7104 more that 32 bits make no sense anyway, ( the
7105 largest size of an object can be only 32 bits ) */
7107 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7108 emitcode ("inc", "b");
7109 freeAsmop (right, NULL, ic, TRUE);
7110 aopOp (left, ic, FALSE);
7111 aopOp (result, ic, FALSE);
7113 /* now move the left to the result if they are not the
7115 if (!sameRegs (AOP (left), AOP (result)) &&
7116 AOP_SIZE (result) > 1)
7119 size = AOP_SIZE (result);
7123 l = aopGet (AOP (left), offset, FALSE, TRUE);
7124 if (*l == '@' && IS_AOP_PREG (result))
7127 emitcode ("mov", "a,%s", l);
7128 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7131 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7136 tlbl = newiTempLabel (NULL);
7137 tlbl1 = newiTempLabel (NULL);
7138 size = AOP_SIZE (result);
7141 /* if it is only one byte then */
7144 l = aopGet (AOP (left), 0, FALSE, FALSE);
7146 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7147 emitcode ("", "%05d$:", tlbl->key + 100);
7149 emitcode ("rrc", "a");
7150 emitcode ("", "%05d$:", tlbl1->key + 100);
7151 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7152 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7156 reAdjustPreg (AOP (result));
7157 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7158 emitcode ("", "%05d$:", tlbl->key + 100);
7162 l = aopGet (AOP (result), offset, FALSE, FALSE);
7164 emitcode ("rrc", "a");
7165 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7167 reAdjustPreg (AOP (result));
7169 emitcode ("", "%05d$:", tlbl1->key + 100);
7170 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7173 freeAsmop (left, NULL, ic, TRUE);
7174 freeAsmop (result, NULL, ic, TRUE);
7177 /*-----------------------------------------------------------------*/
7178 /* emitPtrByteGet - emits code to get a byte into A through a */
7179 /* pointer register (R0, R1, or DPTR). The */
7180 /* original value of A can be preserved in B. */
7181 /*-----------------------------------------------------------------*/
7183 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7190 emitcode ("mov", "b,a");
7191 emitcode ("mov", "a,@%s", rname);
7196 emitcode ("mov", "b,a");
7197 emitcode ("movx", "a,@%s", rname);
7202 emitcode ("mov", "b,a");
7203 emitcode ("movx", "a,@dptr");
7208 emitcode ("mov", "b,a");
7209 emitcode ("clr", "a");
7210 emitcode ("movc", "a,@a+dptr");
7216 emitcode ("push", "b");
7217 emitcode ("push", "acc");
7219 emitcode ("lcall", "__gptrget");
7221 emitcode ("pop", "b");
7226 /*-----------------------------------------------------------------*/
7227 /* emitPtrByteSet - emits code to set a byte from src through a */
7228 /* pointer register (R0, R1, or DPTR). */
7229 /*-----------------------------------------------------------------*/
7231 emitPtrByteSet (char *rname, int p_type, char *src)
7240 emitcode ("mov", "@%s,a", rname);
7243 emitcode ("mov", "@%s,%s", rname, src);
7248 emitcode ("movx", "@%s,a", rname);
7253 emitcode ("movx", "@dptr,a");
7258 emitcode ("lcall", "__gptrput");
7263 /*-----------------------------------------------------------------*/
7264 /* genUnpackBits - generates code for unpacking bits */
7265 /*-----------------------------------------------------------------*/
7267 genUnpackBits (operand * result, char *rname, int ptype)
7269 int offset = 0; /* result byte offset */
7270 int rsize; /* result size */
7271 int rlen = 0; /* remaining bitfield length */
7272 sym_link *etype; /* bitfield type information */
7273 int blen; /* bitfield length */
7274 int bstr; /* bitfield starting bit within byte */
7276 D(emitcode ("; genUnpackBits",""));
7278 etype = getSpec (operandType (result));
7279 rsize = getSize (operandType (result));
7280 blen = SPEC_BLEN (etype);
7281 bstr = SPEC_BSTR (etype);
7283 /* If the bitfield length is less than a byte */
7286 emitPtrByteGet (rname, ptype, FALSE);
7288 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7289 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7293 /* Bit field did not fit in a byte. Copy all
7294 but the partial byte at the end. */
7295 for (rlen=blen;rlen>=8;rlen-=8)
7297 emitPtrByteGet (rname, ptype, FALSE);
7298 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7300 emitcode ("inc", "%s", rname);
7303 /* Handle the partial byte at the end */
7306 emitPtrByteGet (rname, ptype, FALSE);
7307 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7308 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7316 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7321 /*-----------------------------------------------------------------*/
7322 /* genDataPointerGet - generates code when ptr offset is known */
7323 /*-----------------------------------------------------------------*/
7325 genDataPointerGet (operand * left,
7331 int size, offset = 0;
7333 D(emitcode ("; genDataPointerGet",""));
7335 aopOp (result, ic, TRUE);
7337 /* get the string representation of the name */
7338 l = aopGet (AOP (left), 0, FALSE, TRUE);
7339 size = AOP_SIZE (result);
7343 sprintf (buffer, "(%s + %d)", l + 1, offset);
7345 sprintf (buffer, "%s", l + 1);
7346 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7349 freeAsmop (left, NULL, ic, TRUE);
7350 freeAsmop (result, NULL, ic, TRUE);
7353 /*-----------------------------------------------------------------*/
7354 /* genNearPointerGet - emitcode for near pointer fetch */
7355 /*-----------------------------------------------------------------*/
7357 genNearPointerGet (operand * left,
7365 sym_link *rtype, *retype;
7366 sym_link *ltype = operandType (left);
7369 D(emitcode ("; genNearPointerGet",""));
7371 rtype = operandType (result);
7372 retype = getSpec (rtype);
7374 aopOp (left, ic, FALSE);
7376 /* if left is rematerialisable and
7377 result is not bit variable type and
7378 the left is pointer to data space i.e
7379 lower 128 bytes of space */
7380 if (AOP_TYPE (left) == AOP_IMMD &&
7381 !IS_BITVAR (retype) &&
7382 DCL_TYPE (ltype) == POINTER)
7384 genDataPointerGet (left, result, ic);
7388 /* if the value is already in a pointer register
7389 then don't need anything more */
7390 if (!AOP_INPREG (AOP (left)))
7392 if (IS_AOP_PREG (left))
7394 // Aha, it is a pointer, just in disguise.
7395 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7398 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7399 __FILE__, __LINE__);
7404 emitcode ("mov", "a%s,%s", rname + 1, rname);
7405 rname++; // skip the '@'.
7410 /* otherwise get a free pointer register */
7412 preg = getFreePtr (ic, &aop, FALSE);
7413 emitcode ("mov", "%s,%s",
7415 aopGet (AOP (left), 0, FALSE, TRUE));
7420 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7422 //aopOp (result, ic, FALSE);
7423 aopOp (result, ic, result?TRUE:FALSE);
7425 /* if bitfield then unpack the bits */
7426 if (IS_BITVAR (retype))
7427 genUnpackBits (result, rname, POINTER);
7430 /* we have can just get the values */
7431 int size = AOP_SIZE (result);
7436 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7439 emitcode ("mov", "a,@%s", rname);
7440 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7444 sprintf (buffer, "@%s", rname);
7445 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7449 emitcode ("inc", "%s", rname);
7453 /* now some housekeeping stuff */
7454 if (aop) /* we had to allocate for this iCode */
7456 if (pi) { /* post increment present */
7457 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7459 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7463 /* we did not allocate which means left
7464 already in a pointer register, then
7465 if size > 0 && this could be used again
7466 we have to point it back to where it
7468 if ((AOP_SIZE (result) > 1 &&
7469 !OP_SYMBOL (left)->remat &&
7470 (OP_SYMBOL (left)->liveTo > ic->seq ||
7474 int size = AOP_SIZE (result) - 1;
7476 emitcode ("dec", "%s", rname);
7481 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7482 freeAsmop (left, NULL, ic, TRUE);
7483 if (pi) pi->generated = 1;
7486 /*-----------------------------------------------------------------*/
7487 /* genPagedPointerGet - emitcode for paged pointer fetch */
7488 /*-----------------------------------------------------------------*/
7490 genPagedPointerGet (operand * left,
7498 sym_link *rtype, *retype;
7500 D(emitcode ("; genPagedPointerGet",""));
7502 rtype = operandType (result);
7503 retype = getSpec (rtype);
7505 aopOp (left, ic, FALSE);
7507 /* if the value is already in a pointer register
7508 then don't need anything more */
7509 if (!AOP_INPREG (AOP (left)))
7511 /* otherwise get a free pointer register */
7513 preg = getFreePtr (ic, &aop, FALSE);
7514 emitcode ("mov", "%s,%s",
7516 aopGet (AOP (left), 0, FALSE, TRUE));
7520 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7522 aopOp (result, ic, FALSE);
7524 /* if bitfield then unpack the bits */
7525 if (IS_BITVAR (retype))
7526 genUnpackBits (result, rname, PPOINTER);
7529 /* we have can just get the values */
7530 int size = AOP_SIZE (result);
7536 emitcode ("movx", "a,@%s", rname);
7537 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7542 emitcode ("inc", "%s", rname);
7546 /* now some housekeeping stuff */
7547 if (aop) /* we had to allocate for this iCode */
7549 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7550 freeAsmop (NULL, aop, ic, TRUE);
7554 /* we did not allocate which means left
7555 already in a pointer register, then
7556 if size > 0 && this could be used again
7557 we have to point it back to where it
7559 if ((AOP_SIZE (result) > 1 &&
7560 !OP_SYMBOL (left)->remat &&
7561 (OP_SYMBOL (left)->liveTo > ic->seq ||
7565 int size = AOP_SIZE (result) - 1;
7567 emitcode ("dec", "%s", rname);
7572 freeAsmop (left, NULL, ic, TRUE);
7573 freeAsmop (result, NULL, ic, TRUE);
7574 if (pi) pi->generated = 1;
7578 /*--------------------------------------------------------------------*/
7579 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7580 /*--------------------------------------------------------------------*/
7582 loadDptrFromOperand (operand *op, bool loadBToo)
7584 if (AOP_TYPE (op) != AOP_STR)
7586 /* if this is remateriazable */
7587 if (AOP_TYPE (op) == AOP_IMMD)
7589 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7592 if (AOP(op)->aopu.aop_immd.from_cast_remat)
7593 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7596 wassertl(FALSE, "need pointerCode");
7597 emitcode ("", "; mov b,???");
7598 /* genPointerGet and genPointerSet originally did different
7599 ** things for this case. Both seem wrong.
7600 ** from genPointerGet:
7601 ** emitcode ("mov", "b,#%d", pointerCode (retype));
7602 ** from genPointerSet:
7603 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7608 else if (AOP_TYPE (op) == AOP_DPTR)
7612 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7613 emitcode ("push", "acc");
7614 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7615 emitcode ("push", "acc");
7616 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7617 emitcode ("pop", "dph");
7618 emitcode ("pop", "dpl");
7622 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7623 emitcode ("push", "acc");
7624 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7625 emitcode ("pop", "dpl");
7629 { /* we need to get it byte by byte */
7630 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7631 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7633 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7638 /*-----------------------------------------------------------------*/
7639 /* genFarPointerGet - gget value from far space */
7640 /*-----------------------------------------------------------------*/
7642 genFarPointerGet (operand * left,
7643 operand * result, iCode * ic, iCode * pi)
7646 sym_link *retype = getSpec (operandType (result));
7648 D(emitcode ("; genFarPointerGet",""));
7650 aopOp (left, ic, FALSE);
7651 loadDptrFromOperand (left, FALSE);
7653 /* so dptr now contains the address */
7654 aopOp (result, ic, FALSE);
7656 /* if bit then unpack */
7657 if (IS_BITVAR (retype))
7658 genUnpackBits (result, "dptr", FPOINTER);
7661 size = AOP_SIZE (result);
7666 emitcode ("movx", "a,@dptr");
7667 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7669 emitcode ("inc", "dptr");
7673 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7674 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7675 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7678 freeAsmop (left, NULL, ic, TRUE);
7679 freeAsmop (result, NULL, ic, TRUE);
7682 /*-----------------------------------------------------------------*/
7683 /* genCodePointerGet - gget value from code space */
7684 /*-----------------------------------------------------------------*/
7686 genCodePointerGet (operand * left,
7687 operand * result, iCode * ic, iCode *pi)
7690 sym_link *retype = getSpec (operandType (result));
7692 D(emitcode ("; genCodePointerGet",""));
7694 aopOp (left, ic, FALSE);
7695 loadDptrFromOperand (left, FALSE);
7697 /* so dptr now contains the address */
7698 aopOp (result, ic, FALSE);
7700 /* if bit then unpack */
7701 if (IS_BITVAR (retype))
7702 genUnpackBits (result, "dptr", CPOINTER);
7705 size = AOP_SIZE (result);
7712 emitcode ("clr", "a");
7713 emitcode ("movc", "a,@a+dptr");
7714 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7715 emitcode ("inc", "dptr");
7719 emitcode ("mov", "a,#0x%02x", offset);
7720 emitcode ("movc", "a,@a+dptr");
7721 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7726 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7727 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7728 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7731 freeAsmop (left, NULL, ic, TRUE);
7732 freeAsmop (result, NULL, ic, TRUE);
7735 /*-----------------------------------------------------------------*/
7736 /* genGenPointerGet - gget value from generic pointer space */
7737 /*-----------------------------------------------------------------*/
7739 genGenPointerGet (operand * left,
7740 operand * result, iCode * ic, iCode *pi)
7743 sym_link *retype = getSpec (operandType (result));
7745 D(emitcode ("; genGenPointerGet",""));
7747 aopOp (left, ic, FALSE);
7748 loadDptrFromOperand (left, TRUE);
7750 /* so dptr know contains the address */
7751 aopOp (result, ic, FALSE);
7753 /* if bit then unpack */
7754 if (IS_BITVAR (retype))
7755 genUnpackBits (result, "dptr", GPOINTER);
7758 size = AOP_SIZE (result);
7763 emitcode ("lcall", "__gptrget");
7764 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7766 emitcode ("inc", "dptr");
7770 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7771 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7772 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7775 freeAsmop (left, NULL, ic, TRUE);
7776 freeAsmop (result, NULL, ic, TRUE);
7779 /*-----------------------------------------------------------------*/
7780 /* genPointerGet - generate code for pointer get */
7781 /*-----------------------------------------------------------------*/
7783 genPointerGet (iCode * ic, iCode *pi)
7785 operand *left, *result;
7786 sym_link *type, *etype;
7789 D(emitcode ("; genPointerGet",""));
7791 left = IC_LEFT (ic);
7792 result = IC_RESULT (ic);
7794 /* depending on the type of pointer we need to
7795 move it to the correct pointer register */
7796 type = operandType (left);
7797 etype = getSpec (type);
7798 /* if left is of type of pointer then it is simple */
7799 if (IS_PTR (type) && !IS_FUNC (type->next))
7800 p_type = DCL_TYPE (type);
7803 /* we have to go by the storage class */
7804 p_type = PTR_TYPE (SPEC_OCLS (etype));
7807 /* special case when cast remat */
7808 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7809 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7810 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7811 type = operandType (left);
7812 p_type = DCL_TYPE (type);
7814 /* now that we have the pointer type we assign
7815 the pointer values */
7821 genNearPointerGet (left, result, ic, pi);
7825 genPagedPointerGet (left, result, ic, pi);
7829 genFarPointerGet (left, result, ic, pi);
7833 genCodePointerGet (left, result, ic, pi);
7837 genGenPointerGet (left, result, ic, pi);
7845 /*-----------------------------------------------------------------*/
7846 /* genPackBits - generates code for packed bit storage */
7847 /*-----------------------------------------------------------------*/
7849 genPackBits (sym_link * etype,
7851 char *rname, int p_type)
7853 int offset = 0; /* source byte offset */
7854 int rlen = 0; /* remaining bitfield length */
7855 int blen; /* bitfield length */
7856 int bstr; /* bitfield starting bit within byte */
7857 int litval; /* source literal value (if AOP_LIT) */
7858 unsigned char mask; /* bitmask within current byte */
7860 D(emitcode ("; genPackBits",""));
7862 blen = SPEC_BLEN (etype);
7863 bstr = SPEC_BSTR (etype);
7865 /* If the bitfield length is less than a byte */
7868 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7869 (unsigned char) (0xFF >> (8 - bstr)));
7871 if (AOP_TYPE (right) == AOP_LIT)
7873 /* Case with a bitfield length <8 and literal source
7875 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7877 litval &= (~mask) & 0xff;
7878 emitPtrByteGet (rname, p_type, FALSE);
7879 if ((mask|litval)!=0xff)
7880 emitcode ("anl","a,#0x%02x", mask);
7882 emitcode ("orl","a,#0x%02x", litval);
7886 if ((blen==1) && (p_type!=GPOINTER))
7888 /* Case with a bitfield length == 1 and no generic pointer
7890 if (AOP_TYPE (right) == AOP_CRY)
7891 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7894 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7895 emitcode ("rrc","a");
7897 emitPtrByteGet (rname, p_type, FALSE);
7898 emitcode ("mov","acc.%d,c",bstr);
7902 /* Case with a bitfield length < 8 and arbitrary source
7904 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7905 /* shift and mask source value */
7907 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7909 /* transfer A to B and get next byte */
7910 emitPtrByteGet (rname, p_type, TRUE);
7912 emitcode ("anl", "a,#0x%02x", mask);
7913 emitcode ("orl", "a,b");
7914 if (p_type == GPOINTER)
7915 emitcode ("pop", "b");
7919 emitPtrByteSet (rname, p_type, "a");
7923 /* Bit length is greater than 7 bits. In this case, copy */
7924 /* all except the partial byte at the end */
7925 for (rlen=blen;rlen>=8;rlen-=8)
7927 emitPtrByteSet (rname, p_type,
7928 aopGet (AOP (right), offset++, FALSE, TRUE) );
7930 emitcode ("inc", "%s", rname);
7933 /* If there was a partial byte at the end */
7936 mask = (((unsigned char) -1 << rlen) & 0xff);
7938 if (AOP_TYPE (right) == AOP_LIT)
7940 /* Case with partial byte and literal source
7942 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7943 litval >>= (blen-rlen);
7944 litval &= (~mask) & 0xff;
7945 emitPtrByteGet (rname, p_type, FALSE);
7946 if ((mask|litval)!=0xff)
7947 emitcode ("anl","a,#0x%02x", mask);
7949 emitcode ("orl","a,#0x%02x", litval);
7953 /* Case with partial byte and arbitrary source
7955 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
7956 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7958 /* transfer A to B and get next byte */
7959 emitPtrByteGet (rname, p_type, TRUE);
7961 emitcode ("anl", "a,#0x%02x", mask);
7962 emitcode ("orl", "a,b");
7963 if (p_type == GPOINTER)
7964 emitcode ("pop", "b");
7966 emitPtrByteSet (rname, p_type, "a");
7972 /*-----------------------------------------------------------------*/
7973 /* genDataPointerSet - remat pointer to data space */
7974 /*-----------------------------------------------------------------*/
7976 genDataPointerSet (operand * right,
7980 int size, offset = 0;
7981 char *l, buffer[256];
7983 D(emitcode ("; genDataPointerSet",""));
7985 aopOp (right, ic, FALSE);
7987 l = aopGet (AOP (result), 0, FALSE, TRUE);
7988 size = AOP_SIZE (right);
7992 sprintf (buffer, "(%s + %d)", l + 1, offset);
7994 sprintf (buffer, "%s", l + 1);
7995 emitcode ("mov", "%s,%s", buffer,
7996 aopGet (AOP (right), offset++, FALSE, FALSE));
7999 freeAsmop (right, NULL, ic, TRUE);
8000 freeAsmop (result, NULL, ic, TRUE);
8003 /*-----------------------------------------------------------------*/
8004 /* genNearPointerSet - emitcode for near pointer put */
8005 /*-----------------------------------------------------------------*/
8007 genNearPointerSet (operand * right,
8015 sym_link *retype, *letype;
8016 sym_link *ptype = operandType (result);
8018 D(emitcode ("; genNearPointerSet",""));
8020 retype = getSpec (operandType (right));
8021 letype = getSpec (ptype);
8022 aopOp (result, ic, FALSE);
8024 /* if the result is rematerializable &
8025 in data space & not a bit variable */
8026 if (AOP_TYPE (result) == AOP_IMMD &&
8027 DCL_TYPE (ptype) == POINTER &&
8028 !IS_BITVAR (retype) &&
8029 !IS_BITVAR (letype))
8031 genDataPointerSet (right, result, ic);
8035 /* if the value is already in a pointer register
8036 then don't need anything more */
8037 if (!AOP_INPREG (AOP (result)))
8040 //AOP_TYPE (result) == AOP_STK
8044 // Aha, it is a pointer, just in disguise.
8045 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8048 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8049 __FILE__, __LINE__);
8054 emitcode ("mov", "a%s,%s", rname + 1, rname);
8055 rname++; // skip the '@'.
8060 /* otherwise get a free pointer register */
8062 preg = getFreePtr (ic, &aop, FALSE);
8063 emitcode ("mov", "%s,%s",
8065 aopGet (AOP (result), 0, FALSE, TRUE));
8071 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8074 aopOp (right, ic, FALSE);
8076 /* if bitfield then unpack the bits */
8077 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8078 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8081 /* we have can just get the values */
8082 int size = AOP_SIZE (right);
8087 l = aopGet (AOP (right), offset, FALSE, TRUE);
8091 emitcode ("mov", "@%s,a", rname);
8094 emitcode ("mov", "@%s,%s", rname, l);
8096 emitcode ("inc", "%s", rname);
8101 /* now some housekeeping stuff */
8102 if (aop) /* we had to allocate for this iCode */
8105 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8106 freeAsmop (NULL, aop, ic, TRUE);
8110 /* we did not allocate which means left
8111 already in a pointer register, then
8112 if size > 0 && this could be used again
8113 we have to point it back to where it
8115 if ((AOP_SIZE (right) > 1 &&
8116 !OP_SYMBOL (result)->remat &&
8117 (OP_SYMBOL (result)->liveTo > ic->seq ||
8121 int size = AOP_SIZE (right) - 1;
8123 emitcode ("dec", "%s", rname);
8128 if (pi) pi->generated = 1;
8129 freeAsmop (result, NULL, ic, TRUE);
8130 freeAsmop (right, NULL, ic, TRUE);
8133 /*-----------------------------------------------------------------*/
8134 /* genPagedPointerSet - emitcode for Paged pointer put */
8135 /*-----------------------------------------------------------------*/
8137 genPagedPointerSet (operand * right,
8145 sym_link *retype, *letype;
8147 D(emitcode ("; genPagedPointerSet",""));
8149 retype = getSpec (operandType (right));
8150 letype = getSpec (operandType (result));
8152 aopOp (result, ic, FALSE);
8154 /* if the value is already in a pointer register
8155 then don't need anything more */
8156 if (!AOP_INPREG (AOP (result)))
8158 /* otherwise get a free pointer register */
8160 preg = getFreePtr (ic, &aop, FALSE);
8161 emitcode ("mov", "%s,%s",
8163 aopGet (AOP (result), 0, FALSE, TRUE));
8167 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8169 aopOp (right, ic, FALSE);
8171 /* if bitfield then unpack the bits */
8172 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8173 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8176 /* we have can just get the values */
8177 int size = AOP_SIZE (right);
8182 l = aopGet (AOP (right), offset, FALSE, TRUE);
8185 emitcode ("movx", "@%s,a", rname);
8188 emitcode ("inc", "%s", rname);
8194 /* now some housekeeping stuff */
8195 if (aop) /* we had to allocate for this iCode */
8198 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8199 freeAsmop (NULL, aop, ic, TRUE);
8203 /* we did not allocate which means left
8204 already in a pointer register, then
8205 if size > 0 && this could be used again
8206 we have to point it back to where it
8208 if (AOP_SIZE (right) > 1 &&
8209 !OP_SYMBOL (result)->remat &&
8210 (OP_SYMBOL (result)->liveTo > ic->seq ||
8213 int size = AOP_SIZE (right) - 1;
8215 emitcode ("dec", "%s", rname);
8220 if (pi) pi->generated = 1;
8221 freeAsmop (result, NULL, ic, TRUE);
8222 freeAsmop (right, NULL, ic, TRUE);
8227 /*-----------------------------------------------------------------*/
8228 /* genFarPointerSet - set value from far space */
8229 /*-----------------------------------------------------------------*/
8231 genFarPointerSet (operand * right,
8232 operand * result, iCode * ic, iCode * pi)
8235 sym_link *retype = getSpec (operandType (right));
8236 sym_link *letype = getSpec (operandType (result));
8238 D(emitcode ("; genFarPointerSet",""));
8240 aopOp (result, ic, FALSE);
8241 loadDptrFromOperand (result, FALSE);
8243 /* so dptr know contains the address */
8244 aopOp (right, ic, FALSE);
8246 /* if bit then unpack */
8247 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8248 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8251 size = AOP_SIZE (right);
8256 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8258 emitcode ("movx", "@dptr,a");
8260 emitcode ("inc", "dptr");
8263 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8264 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8265 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8268 freeAsmop (result, NULL, ic, TRUE);
8269 freeAsmop (right, NULL, ic, TRUE);
8272 /*-----------------------------------------------------------------*/
8273 /* genGenPointerSet - set value from generic pointer space */
8274 /*-----------------------------------------------------------------*/
8276 genGenPointerSet (operand * right,
8277 operand * result, iCode * ic, iCode * pi)
8280 sym_link *retype = getSpec (operandType (right));
8281 sym_link *letype = getSpec (operandType (result));
8283 D(emitcode ("; genGenPointerSet",""));
8285 aopOp (result, ic, FALSE);
8286 loadDptrFromOperand (result, TRUE);
8288 /* so dptr know contains the address */
8289 aopOp (right, ic, FALSE);
8291 /* if bit then unpack */
8292 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8293 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8296 size = AOP_SIZE (right);
8301 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8303 emitcode ("lcall", "__gptrput");
8305 emitcode ("inc", "dptr");
8309 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8310 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8311 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8314 freeAsmop (result, NULL, ic, TRUE);
8315 freeAsmop (right, NULL, ic, TRUE);
8318 /*-----------------------------------------------------------------*/
8319 /* genPointerSet - stores the value into a pointer location */
8320 /*-----------------------------------------------------------------*/
8322 genPointerSet (iCode * ic, iCode *pi)
8324 operand *right, *result;
8325 sym_link *type, *etype;
8328 D(emitcode ("; genPointerSet",""));
8330 right = IC_RIGHT (ic);
8331 result = IC_RESULT (ic);
8333 /* depending on the type of pointer we need to
8334 move it to the correct pointer register */
8335 type = operandType (result);
8336 etype = getSpec (type);
8337 /* if left is of type of pointer then it is simple */
8338 if (IS_PTR (type) && !IS_FUNC (type->next))
8340 p_type = DCL_TYPE (type);
8344 /* we have to go by the storage class */
8345 p_type = PTR_TYPE (SPEC_OCLS (etype));
8348 /* special case when cast remat */
8349 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8350 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8351 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8352 type = operandType (result);
8353 p_type = DCL_TYPE (type);
8355 /* now that we have the pointer type we assign
8356 the pointer values */
8362 genNearPointerSet (right, result, ic, pi);
8366 genPagedPointerSet (right, result, ic, pi);
8370 genFarPointerSet (right, result, ic, pi);
8374 genGenPointerSet (right, result, ic, pi);
8378 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8379 "genPointerSet: illegal pointer type");
8384 /*-----------------------------------------------------------------*/
8385 /* genIfx - generate code for Ifx statement */
8386 /*-----------------------------------------------------------------*/
8388 genIfx (iCode * ic, iCode * popIc)
8390 operand *cond = IC_COND (ic);
8393 D(emitcode ("; genIfx",""));
8395 aopOp (cond, ic, FALSE);
8397 /* get the value into acc */
8398 if (AOP_TYPE (cond) != AOP_CRY)
8402 /* the result is now in the accumulator */
8403 freeAsmop (cond, NULL, ic, TRUE);
8405 /* if there was something to be popped then do it */
8409 /* if the condition is a bit variable */
8410 if (isbit && IS_ITEMP (cond) &&
8412 genIfxJump (ic, SPIL_LOC (cond)->rname);
8413 else if (isbit && !IS_ITEMP (cond))
8414 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8416 genIfxJump (ic, "a");
8421 /*-----------------------------------------------------------------*/
8422 /* genAddrOf - generates code for address of */
8423 /*-----------------------------------------------------------------*/
8425 genAddrOf (iCode * ic)
8427 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8430 D(emitcode ("; genAddrOf",""));
8432 aopOp (IC_RESULT (ic), ic, FALSE);
8434 /* if the operand is on the stack then we
8435 need to get the stack offset of this
8439 /* if it has an offset then we need to compute
8443 emitcode ("mov", "a,_bp");
8444 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8445 ((char) (sym->stack - _G.nRegsSaved)) :
8446 ((char) sym->stack)) & 0xff);
8447 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8451 /* we can just move _bp */
8452 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8454 /* fill the result with zero */
8455 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8460 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8466 /* object not on stack then we need the name */
8467 size = AOP_SIZE (IC_RESULT (ic));
8472 char s[SDCC_NAME_MAX];
8474 sprintf (s, "#(%s >> %d)",
8478 sprintf (s, "#%s", sym->rname);
8479 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8483 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8487 /*-----------------------------------------------------------------*/
8488 /* genFarFarAssign - assignment when both are in far space */
8489 /*-----------------------------------------------------------------*/
8491 genFarFarAssign (operand * result, operand * right, iCode * ic)
8493 int size = AOP_SIZE (right);
8497 D(emitcode ("; genFarFarAssign",""));
8499 /* first push the right side on to the stack */
8502 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8504 emitcode ("push", "acc");
8507 freeAsmop (right, NULL, ic, FALSE);
8508 /* now assign DPTR to result */
8509 aopOp (result, ic, FALSE);
8510 size = AOP_SIZE (result);
8513 emitcode ("pop", "acc");
8514 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8516 freeAsmop (result, NULL, ic, FALSE);
8520 /*-----------------------------------------------------------------*/
8521 /* genAssign - generate code for assignment */
8522 /*-----------------------------------------------------------------*/
8524 genAssign (iCode * ic)
8526 operand *result, *right;
8528 unsigned long lit = 0L;
8530 D(emitcode("; genAssign",""));
8532 result = IC_RESULT (ic);
8533 right = IC_RIGHT (ic);
8535 /* if they are the same */
8536 if (operandsEqu (result, right) &&
8537 !isOperandVolatile (result, FALSE) &&
8538 !isOperandVolatile (right, FALSE))
8541 aopOp (right, ic, FALSE);
8543 /* special case both in far space */
8544 if (AOP_TYPE (right) == AOP_DPTR &&
8545 IS_TRUE_SYMOP (result) &&
8546 isOperandInFarSpace (result))
8549 genFarFarAssign (result, right, ic);
8553 aopOp (result, ic, TRUE);
8555 /* if they are the same registers */
8556 if (sameRegs (AOP (right), AOP (result)) &&
8557 !isOperandVolatile (result, FALSE) &&
8558 !isOperandVolatile (right, FALSE))
8561 /* if the result is a bit */
8562 if (AOP_TYPE (result) == AOP_CRY)
8565 /* if the right size is a literal then
8566 we know what the value is */
8567 if (AOP_TYPE (right) == AOP_LIT)
8569 if (((int) operandLitValue (right)))
8570 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8572 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8576 /* the right is also a bit variable */
8577 if (AOP_TYPE (right) == AOP_CRY)
8579 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8580 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8586 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8590 /* bit variables done */
8592 size = AOP_SIZE (result);
8594 if (AOP_TYPE (right) == AOP_LIT)
8595 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8597 (AOP_TYPE (result) != AOP_REG) &&
8598 (AOP_TYPE (right) == AOP_LIT) &&
8599 !IS_FLOAT (operandType (right)) &&
8602 emitcode ("clr", "a");
8605 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8606 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8608 aopPut (AOP (result),
8609 aopGet (AOP (right), size, FALSE, FALSE),
8611 isOperandVolatile (result, FALSE));
8618 aopPut (AOP (result),
8619 aopGet (AOP (right), offset, FALSE, FALSE),
8621 isOperandVolatile (result, FALSE));
8627 freeAsmop (right, NULL, ic, TRUE);
8628 freeAsmop (result, NULL, ic, TRUE);
8631 /*-----------------------------------------------------------------*/
8632 /* genJumpTab - genrates code for jump table */
8633 /*-----------------------------------------------------------------*/
8635 genJumpTab (iCode * ic)
8640 D(emitcode ("; genJumpTab",""));
8642 aopOp (IC_JTCOND (ic), ic, FALSE);
8643 /* get the condition into accumulator */
8644 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8646 /* multiply by three */
8647 emitcode ("add", "a,acc");
8648 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8649 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8651 jtab = newiTempLabel (NULL);
8652 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8653 emitcode ("jmp", "@a+dptr");
8654 emitcode ("", "%05d$:", jtab->key + 100);
8655 /* now generate the jump labels */
8656 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8657 jtab = setNextItem (IC_JTLABELS (ic)))
8658 emitcode ("ljmp", "%05d$", jtab->key + 100);
8662 /*-----------------------------------------------------------------*/
8663 /* genCast - gen code for casting */
8664 /*-----------------------------------------------------------------*/
8666 genCast (iCode * ic)
8668 operand *result = IC_RESULT (ic);
8669 sym_link *ctype = operandType (IC_LEFT (ic));
8670 sym_link *rtype = operandType (IC_RIGHT (ic));
8671 operand *right = IC_RIGHT (ic);
8674 D(emitcode("; genCast",""));
8676 /* if they are equivalent then do nothing */
8677 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8680 aopOp (right, ic, FALSE);
8681 aopOp (result, ic, FALSE);
8683 /* if the result is a bit (and not a bitfield) */
8684 // if (AOP_TYPE (result) == AOP_CRY)
8685 if (IS_BITVAR (OP_SYMBOL (result)->type)
8686 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8688 /* if the right size is a literal then
8689 we know what the value is */
8690 if (AOP_TYPE (right) == AOP_LIT)
8692 if (((int) operandLitValue (right)))
8693 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8695 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8700 /* the right is also a bit variable */
8701 if (AOP_TYPE (right) == AOP_CRY)
8703 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8704 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8710 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8715 /* if they are the same size : or less */
8716 if (AOP_SIZE (result) <= AOP_SIZE (right))
8719 /* if they are in the same place */
8720 if (sameRegs (AOP (right), AOP (result)))
8723 /* if they in different places then copy */
8724 size = AOP_SIZE (result);
8728 aopPut (AOP (result),
8729 aopGet (AOP (right), offset, FALSE, FALSE),
8731 isOperandVolatile (result, FALSE));
8738 /* if the result is of type pointer */
8743 sym_link *type = operandType (right);
8744 sym_link *etype = getSpec (type);
8746 /* pointer to generic pointer */
8747 if (IS_GENPTR (ctype))
8750 p_type = DCL_TYPE (type);
8753 if (SPEC_SCLS(etype)==S_REGISTER) {
8754 // let's assume it is a generic pointer
8757 /* we have to go by the storage class */
8758 p_type = PTR_TYPE (SPEC_OCLS (etype));
8762 /* the first two bytes are known */
8763 size = GPTRSIZE - 1;
8767 aopPut (AOP (result),
8768 aopGet (AOP (right), offset, FALSE, FALSE),
8770 isOperandVolatile (result, FALSE));
8773 /* the last byte depending on type */
8775 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8780 // pointerTypeToGPByte will have bitched.
8784 sprintf(gpValStr, "#0x%d", gpVal);
8785 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8790 /* just copy the pointers */
8791 size = AOP_SIZE (result);
8795 aopPut (AOP (result),
8796 aopGet (AOP (right), offset, FALSE, FALSE),
8798 isOperandVolatile (result, FALSE));
8804 /* so we now know that the size of destination is greater
8805 than the size of the source */
8806 /* we move to result for the size of source */
8807 size = AOP_SIZE (right);
8811 aopPut (AOP (result),
8812 aopGet (AOP (right), offset, FALSE, FALSE),
8814 isOperandVolatile (result, FALSE));
8818 /* now depending on the sign of the source && destination */
8819 size = AOP_SIZE (result) - AOP_SIZE (right);
8820 /* if unsigned or not an integral type */
8821 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8824 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8828 /* we need to extend the sign :{ */
8829 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8832 emitcode ("rlc", "a");
8833 emitcode ("subb", "a,acc");
8835 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8838 /* we are done hurray !!!! */
8841 freeAsmop (right, NULL, ic, TRUE);
8842 freeAsmop (result, NULL, ic, TRUE);
8846 /*-----------------------------------------------------------------*/
8847 /* genDjnz - generate decrement & jump if not zero instrucion */
8848 /*-----------------------------------------------------------------*/
8850 genDjnz (iCode * ic, iCode * ifx)
8856 D(emitcode ("; genDjnz",""));
8858 /* if the if condition has a false label
8859 then we cannot save */
8863 /* if the minus is not of the form
8865 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8866 !IS_OP_LITERAL (IC_RIGHT (ic)))
8869 if (operandLitValue (IC_RIGHT (ic)) != 1)
8872 /* if the size of this greater than one then no
8874 if (getSize (operandType (IC_RESULT (ic))) > 1)
8877 /* otherwise we can save BIG */
8878 lbl = newiTempLabel (NULL);
8879 lbl1 = newiTempLabel (NULL);
8881 aopOp (IC_RESULT (ic), ic, FALSE);
8883 if (AOP_NEEDSACC(IC_RESULT(ic)))
8885 /* If the result is accessed indirectly via
8886 * the accumulator, we must explicitly write
8887 * it back after the decrement.
8889 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8891 if (strcmp(rByte, "a"))
8893 /* Something is hopelessly wrong */
8894 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8895 __FILE__, __LINE__);
8896 /* We can just give up; the generated code will be inefficient,
8899 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8902 emitcode ("dec", "%s", rByte);
8903 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8904 emitcode ("jnz", "%05d$", lbl->key + 100);
8906 else if (IS_AOP_PREG (IC_RESULT (ic)))
8908 emitcode ("dec", "%s",
8909 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8910 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8911 emitcode ("jnz", "%05d$", lbl->key + 100);
8915 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8918 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8919 emitcode ("", "%05d$:", lbl->key + 100);
8920 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8921 emitcode ("", "%05d$:", lbl1->key + 100);
8923 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8928 /*-----------------------------------------------------------------*/
8929 /* genReceive - generate code for a receive iCode */
8930 /*-----------------------------------------------------------------*/
8932 genReceive (iCode * ic)
8934 int size = getSize (operandType (IC_RESULT (ic)));
8936 D(emitcode ("; genReceive",""));
8938 if (ic->argreg == 1) { /* first parameter */
8939 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8940 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8941 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8943 offset = fReturnSizeMCS51 - size;
8945 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8946 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8949 aopOp (IC_RESULT (ic), ic, FALSE);
8950 size = AOP_SIZE (IC_RESULT (ic));
8953 emitcode ("pop", "acc");
8954 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8959 aopOp (IC_RESULT (ic), ic, FALSE);
8961 assignResultValue (IC_RESULT (ic));
8963 } else { /* second receive onwards */
8965 aopOp (IC_RESULT (ic), ic, FALSE);
8966 rb1off = ic->argreg;
8968 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8971 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8974 /*-----------------------------------------------------------------*/
8975 /* genDummyRead - generate code for dummy read of volatiles */
8976 /*-----------------------------------------------------------------*/
8978 genDummyRead (iCode * ic)
8983 D(emitcode("; genDummyRead",""));
8985 right = IC_RIGHT (ic);
8987 aopOp (right, ic, FALSE);
8989 /* if the result is a bit */
8990 if (AOP_TYPE (right) == AOP_CRY)
8992 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8996 /* bit variables done */
8998 size = AOP_SIZE (right);
9002 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
9007 freeAsmop (right, NULL, ic, TRUE);
9010 /*-----------------------------------------------------------------*/
9011 /* genCritical - generate code for start of a critical sequence */
9012 /*-----------------------------------------------------------------*/
9014 genCritical (iCode *ic)
9016 symbol *tlbl = newiTempLabel (NULL);
9018 D(emitcode("; genCritical",""));
9021 aopOp (IC_RESULT (ic), ic, TRUE);
9023 emitcode ("setb", "c");
9024 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9025 emitcode ("clr", "c");
9026 emitcode ("", "%05d$:", (tlbl->key + 100));
9029 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9031 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9034 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9037 /*-----------------------------------------------------------------*/
9038 /* genEndCritical - generate code for end of a critical sequence */
9039 /*-----------------------------------------------------------------*/
9041 genEndCritical (iCode *ic)
9043 D(emitcode("; genEndCritical",""));
9047 aopOp (IC_RIGHT (ic), ic, FALSE);
9048 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9050 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9051 emitcode ("mov", "ea,c");
9055 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9056 emitcode ("rrc", "a");
9057 emitcode ("mov", "ea,c");
9059 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9063 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9064 emitcode ("mov", "ea,c");
9069 /*-----------------------------------------------------------------*/
9070 /* gen51Code - generate code for 8051 based controllers */
9071 /*-----------------------------------------------------------------*/
9073 gen51Code (iCode * lic)
9078 lineHead = lineCurr = NULL;
9080 /* print the allocation information */
9081 if (allocInfo && currFunc)
9082 printAllocInfo (currFunc, codeOutFile);
9083 /* if debug information required */
9084 if (options.debug && currFunc)
9086 debugFile->writeFunction(currFunc);
9088 if (IS_STATIC (currFunc->etype))
9089 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9091 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9094 /* stack pointer name */
9095 if (options.useXstack)
9101 for (ic = lic; ic; ic = ic->next)
9103 _G.current_iCode = ic;
9105 if (ic->lineno && cln != ic->lineno)
9110 emitcode ("", "C$%s$%d$%d$%d ==.",
9111 FileBaseName (ic->filename), ic->lineno,
9112 ic->level, ic->block);
9115 if (!options.noCcodeInAsm) {
9116 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9117 printCLine(ic->filename, ic->lineno));
9121 if (options.iCodeInAsm) {
9125 for (i=0; i<8; i++) {
9126 sprintf (®sInUse[i],
9127 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9130 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9132 /* if the result is marked as
9133 spilt and rematerializable or code for
9134 this has already been generated then
9136 if (resultRemat (ic) || ic->generated)
9139 /* depending on the operation */
9159 /* IPOP happens only when trying to restore a
9160 spilt live range, if there is an ifx statement
9161 following this pop then the if statement might
9162 be using some of the registers being popped which
9163 would destory the contents of the register so
9164 we need to check for this condition and handle it */
9166 ic->next->op == IFX &&
9167 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9168 genIfx (ic->next, ic);
9186 genEndFunction (ic);
9206 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9223 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9227 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9234 /* note these two are xlated by algebraic equivalence
9235 during parsing SDCC.y */
9236 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9237 "got '>=' or '<=' shouldn't have come here");
9241 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9253 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9257 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9261 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9288 case GET_VALUE_AT_ADDRESS:
9289 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9293 if (POINTER_SET (ic))
9294 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9320 addSet (&_G.sendSet, ic);
9323 case DUMMY_READ_VOLATILE:
9332 genEndCritical (ic);
9340 _G.current_iCode = NULL;
9342 /* now we are ready to call the
9343 peep hole optimizer */
9344 if (!options.nopeep)
9345 peepHole (&lineHead);
9347 /* now do the actual printing */
9348 printLine (lineHead, codeOutFile);