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 emitcode ("mov", "c,ea");
2608 emitcode ("push", "psw"); /* save old ea via c in psw */
2609 emitcode ("clr", "ea");
2613 /*-----------------------------------------------------------------*/
2614 /* genEndFunction - generates epilogue for functions */
2615 /*-----------------------------------------------------------------*/
2617 genEndFunction (iCode * ic)
2619 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2621 if (IFFUNC_ISNAKED(sym->type))
2623 emitcode(";", "naked function: no epilogue.");
2627 if (IFFUNC_ISCRITICAL (sym->type))
2629 emitcode ("pop", "psw"); /* restore ea via c in psw */
2630 emitcode ("mov", "ea,c");
2633 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2635 emitcode ("mov", "%s,_bp", spname);
2638 /* if use external stack but some variables were
2639 added to the local stack then decrement the
2641 if (options.useXstack && sym->stack)
2643 emitcode ("mov", "a,sp");
2644 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2645 emitcode ("mov", "sp,a");
2649 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2651 if (options.useXstack)
2653 emitcode ("mov", "r0,%s", spname);
2654 emitcode ("movx", "a,@r0");
2655 emitcode ("mov", "_bp,a");
2656 emitcode ("dec", "%s", spname);
2660 emitcode ("pop", "_bp");
2664 /* restore the register bank */
2665 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2667 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2668 || !options.useXstack)
2670 /* Special case of ISR using non-zero bank with useXstack
2673 emitcode ("pop", "psw");
2677 if (IFFUNC_ISISR (sym->type))
2680 /* now we need to restore the registers */
2681 /* if this isr has no bank i.e. is going to
2682 run with bank 0 , then we need to save more
2684 if (!FUNC_REGBANK (sym->type))
2686 /* if this function does not call any other
2687 function then we can be economical and
2688 save only those registers that are used */
2689 if (!IFFUNC_HASFCALL(sym->type))
2693 /* if any registers used */
2696 /* save the registers used */
2697 for (i = sym->regsUsed->size; i >= 0; i--)
2699 if (bitVectBitValue (sym->regsUsed, i) ||
2700 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2701 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2708 if (options.parms_in_bank1) {
2710 for (i = 7 ; i >= 0 ; i-- ) {
2711 emitcode ("pop","%s",rb1regs[i]);
2714 /* this function has a function call cannot
2715 determines register usage so we will have to pop the
2717 unsaveRBank (0, ic, FALSE);
2722 /* This ISR uses a non-zero bank.
2724 * Restore any register banks saved by genFunction
2727 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2730 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2732 if (savedBanks & (1 << ix))
2734 unsaveRBank(ix, NULL, FALSE);
2738 if (options.useXstack)
2740 /* Restore bank AFTER calling unsaveRBank,
2741 * since it can trash r0.
2743 emitcode ("pop", "psw");
2747 if (!inExcludeList ("dph"))
2748 emitcode ("pop", "dph");
2749 if (!inExcludeList ("dpl"))
2750 emitcode ("pop", "dpl");
2751 if (!inExcludeList ("b"))
2752 emitcode ("pop", "b");
2753 if (!inExcludeList ("acc"))
2754 emitcode ("pop", "acc");
2756 /* if debug then send end of function */
2757 if (options.debug && currFunc)
2760 emitcode ("", "C$%s$%d$%d$%d ==.",
2761 FileBaseName (ic->filename), currFunc->lastLine,
2762 ic->level, ic->block);
2763 if (IS_STATIC (currFunc->etype))
2764 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2766 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2770 emitcode ("reti", "");
2774 if (IFFUNC_CALLEESAVES(sym->type))
2778 /* if any registers used */
2781 /* save the registers used */
2782 for (i = sym->regsUsed->size; i >= 0; i--)
2784 if (bitVectBitValue (sym->regsUsed, i) ||
2785 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2786 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2792 /* if debug then send end of function */
2793 if (options.debug && currFunc)
2796 emitcode ("", "C$%s$%d$%d$%d ==.",
2797 FileBaseName (ic->filename), currFunc->lastLine,
2798 ic->level, ic->block);
2799 if (IS_STATIC (currFunc->etype))
2800 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2802 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2806 emitcode ("ret", "");
2811 /*-----------------------------------------------------------------*/
2812 /* genRet - generate code for return statement */
2813 /*-----------------------------------------------------------------*/
2817 int size, offset = 0, pushed = 0;
2819 D(emitcode ("; genRet",""));
2821 /* if we have no return value then
2822 just generate the "ret" */
2826 /* we have something to return then
2827 move the return value into place */
2828 aopOp (IC_LEFT (ic), ic, FALSE);
2829 size = AOP_SIZE (IC_LEFT (ic));
2834 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2837 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2839 emitcode ("push", "%s", l);
2844 l = aopGet (AOP (IC_LEFT (ic)), offset,
2846 if (strcmp (fReturn[offset], l))
2847 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2856 if (strcmp (fReturn[pushed], "a"))
2857 emitcode ("pop", fReturn[pushed]);
2859 emitcode ("pop", "acc");
2862 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2865 /* generate a jump to the return label
2866 if the next is not the return statement */
2867 if (!(ic->next && ic->next->op == LABEL &&
2868 IC_LABEL (ic->next) == returnLabel))
2870 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2874 /*-----------------------------------------------------------------*/
2875 /* genLabel - generates a label */
2876 /*-----------------------------------------------------------------*/
2878 genLabel (iCode * ic)
2880 /* special case never generate */
2881 if (IC_LABEL (ic) == entryLabel)
2884 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2887 /*-----------------------------------------------------------------*/
2888 /* genGoto - generates a ljmp */
2889 /*-----------------------------------------------------------------*/
2891 genGoto (iCode * ic)
2893 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2896 /*-----------------------------------------------------------------*/
2897 /* findLabelBackwards: walks back through the iCode chain looking */
2898 /* for the given label. Returns number of iCode instructions */
2899 /* between that label and given ic. */
2900 /* Returns zero if label not found. */
2901 /*-----------------------------------------------------------------*/
2903 findLabelBackwards (iCode * ic, int key)
2912 /* If we have any pushes or pops, we cannot predict the distance.
2913 I don't like this at all, this should be dealt with in the
2915 if (ic->op == IPUSH || ic->op == IPOP) {
2919 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2928 /*-----------------------------------------------------------------*/
2929 /* genPlusIncr :- does addition with increment if possible */
2930 /*-----------------------------------------------------------------*/
2932 genPlusIncr (iCode * ic)
2934 unsigned int icount;
2935 unsigned int size = getDataSize (IC_RESULT (ic));
2937 /* will try to generate an increment */
2938 /* if the right side is not a literal
2940 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2943 /* if the literal value of the right hand side
2944 is greater than 4 then it is not worth it */
2945 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2948 D(emitcode ("; genPlusIncr",""));
2950 /* if increment >=16 bits in register or direct space */
2951 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2952 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2960 /* If the next instruction is a goto and the goto target
2961 * is < 10 instructions previous to this, we can generate
2962 * jumps straight to that target.
2964 if (ic->next && ic->next->op == GOTO
2965 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2966 && labelRange <= 10)
2968 emitcode (";", "tail increment optimized");
2969 tlbl = IC_LABEL (ic->next);
2974 tlbl = newiTempLabel (NULL);
2977 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2978 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2979 IS_AOP_PREG (IC_RESULT (ic)))
2980 emitcode ("cjne", "%s,#0x00,%05d$",
2981 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2985 emitcode ("clr", "a");
2986 emitcode ("cjne", "a,%s,%05d$",
2987 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2991 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2994 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2995 IS_AOP_PREG (IC_RESULT (ic)))
2996 emitcode ("cjne", "%s,#0x00,%05d$",
2997 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3000 emitcode ("cjne", "a,%s,%05d$",
3001 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3004 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3008 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3009 IS_AOP_PREG (IC_RESULT (ic)))
3010 emitcode ("cjne", "%s,#0x00,%05d$",
3011 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3015 emitcode ("cjne", "a,%s,%05d$",
3016 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3019 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3024 emitcode ("", "%05d$:", tlbl->key + 100);
3029 /* if the sizes are greater than 1 then we cannot */
3030 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3031 AOP_SIZE (IC_LEFT (ic)) > 1)
3034 /* we can if the aops of the left & result match or
3035 if they are in registers and the registers are the
3037 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3042 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3043 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3044 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3050 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3059 /*-----------------------------------------------------------------*/
3060 /* outBitAcc - output a bit in acc */
3061 /*-----------------------------------------------------------------*/
3063 outBitAcc (operand * result)
3065 symbol *tlbl = newiTempLabel (NULL);
3066 /* if the result is a bit */
3067 if (AOP_TYPE (result) == AOP_CRY)
3069 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3073 emitcode ("jz", "%05d$", tlbl->key + 100);
3074 emitcode ("mov", "a,%s", one);
3075 emitcode ("", "%05d$:", tlbl->key + 100);
3080 /*-----------------------------------------------------------------*/
3081 /* genPlusBits - generates code for addition of two bits */
3082 /*-----------------------------------------------------------------*/
3084 genPlusBits (iCode * ic)
3086 D(emitcode ("; genPlusBits",""));
3088 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3090 symbol *lbl = newiTempLabel (NULL);
3091 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3092 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3093 emitcode ("cpl", "c");
3094 emitcode ("", "%05d$:", (lbl->key + 100));
3095 outBitC (IC_RESULT (ic));
3099 emitcode ("clr", "a");
3100 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3101 emitcode ("rlc", "a");
3102 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3103 emitcode ("addc", "a,#0x00");
3104 outAcc (IC_RESULT (ic));
3109 /* This is the original version of this code.
3111 * This is being kept around for reference,
3112 * because I am not entirely sure I got it right...
3115 adjustArithmeticResult (iCode * ic)
3117 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3118 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3119 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3120 aopPut (AOP (IC_RESULT (ic)),
3121 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3123 isOperandVolatile (IC_RESULT (ic), FALSE));
3125 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3126 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3127 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3128 aopPut (AOP (IC_RESULT (ic)),
3129 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3131 isOperandVolatile (IC_RESULT (ic), FALSE));
3133 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3134 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3135 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3136 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3137 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3140 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3141 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3145 /* This is the pure and virtuous version of this code.
3146 * I'm pretty certain it's right, but not enough to toss the old
3150 adjustArithmeticResult (iCode * ic)
3152 if (opIsGptr (IC_RESULT (ic)) &&
3153 opIsGptr (IC_LEFT (ic)) &&
3154 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3156 aopPut (AOP (IC_RESULT (ic)),
3157 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3159 isOperandVolatile (IC_RESULT (ic), FALSE));
3162 if (opIsGptr (IC_RESULT (ic)) &&
3163 opIsGptr (IC_RIGHT (ic)) &&
3164 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3166 aopPut (AOP (IC_RESULT (ic)),
3167 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3169 isOperandVolatile (IC_RESULT (ic), FALSE));
3172 if (opIsGptr (IC_RESULT (ic)) &&
3173 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3174 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3175 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3176 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3179 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3180 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3185 /*-----------------------------------------------------------------*/
3186 /* genPlus - generates code for addition */
3187 /*-----------------------------------------------------------------*/
3189 genPlus (iCode * ic)
3191 int size, offset = 0;
3193 asmop *leftOp, *rightOp;
3195 /* special cases :- */
3197 D(emitcode ("; genPlus",""));
3199 aopOp (IC_LEFT (ic), ic, FALSE);
3200 aopOp (IC_RIGHT (ic), ic, FALSE);
3201 aopOp (IC_RESULT (ic), ic, TRUE);
3203 /* if literal, literal on the right or
3204 if left requires ACC or right is already
3206 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3207 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3208 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3210 operand *t = IC_RIGHT (ic);
3211 IC_RIGHT (ic) = IC_LEFT (ic);
3215 /* if both left & right are in bit
3217 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3218 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3224 /* if left in bit space & right literal */
3225 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3226 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3228 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3229 /* if result in bit space */
3230 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3232 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3233 emitcode ("cpl", "c");
3234 outBitC (IC_RESULT (ic));
3238 size = getDataSize (IC_RESULT (ic));
3241 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3242 emitcode ("addc", "a,#00");
3243 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3249 /* if I can do an increment instead
3250 of add then GOOD for ME */
3251 if (genPlusIncr (ic) == TRUE)
3254 size = getDataSize (IC_RESULT (ic));
3256 leftOp = AOP(IC_LEFT(ic));
3257 rightOp = AOP(IC_RIGHT(ic));
3262 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3264 emitcode("mov", "b,a");
3265 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3266 emitcode("xch", "a,b");
3267 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3268 emitcode (add, "a,b");
3270 else if (aopGetUsesAcc (leftOp, offset))
3272 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3273 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3277 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3278 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3280 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3281 add = "addc"; /* further adds must propagate carry */
3284 adjustArithmeticResult (ic);
3287 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3288 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3289 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3292 /*-----------------------------------------------------------------*/
3293 /* genMinusDec :- does subtraction with deccrement if possible */
3294 /*-----------------------------------------------------------------*/
3296 genMinusDec (iCode * ic)
3298 unsigned int icount;
3299 unsigned int size = getDataSize (IC_RESULT (ic));
3301 /* will try to generate an increment */
3302 /* if the right side is not a literal
3304 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3307 /* if the literal value of the right hand side
3308 is greater than 4 then it is not worth it */
3309 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3312 D(emitcode ("; genMinusDec",""));
3314 /* if decrement >=16 bits in register or direct space */
3315 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3316 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3324 /* If the next instruction is a goto and the goto target
3325 * is <= 10 instructions previous to this, we can generate
3326 * jumps straight to that target.
3328 if (ic->next && ic->next->op == GOTO
3329 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3330 && labelRange <= 10)
3332 emitcode (";", "tail decrement optimized");
3333 tlbl = IC_LABEL (ic->next);
3338 tlbl = newiTempLabel (NULL);
3342 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3343 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3344 IS_AOP_PREG (IC_RESULT (ic)))
3345 emitcode ("cjne", "%s,#0xff,%05d$"
3346 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3350 emitcode ("mov", "a,#0xff");
3351 emitcode ("cjne", "a,%s,%05d$"
3352 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3355 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3358 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3359 IS_AOP_PREG (IC_RESULT (ic)))
3360 emitcode ("cjne", "%s,#0xff,%05d$"
3361 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3365 emitcode ("cjne", "a,%s,%05d$"
3366 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3369 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3373 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3374 IS_AOP_PREG (IC_RESULT (ic)))
3375 emitcode ("cjne", "%s,#0xff,%05d$"
3376 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3380 emitcode ("cjne", "a,%s,%05d$"
3381 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3384 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3388 emitcode ("", "%05d$:", tlbl->key + 100);
3393 /* if the sizes are greater than 1 then we cannot */
3394 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3395 AOP_SIZE (IC_LEFT (ic)) > 1)
3398 /* we can if the aops of the left & result match or
3399 if they are in registers and the registers are the
3401 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3405 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3413 /*-----------------------------------------------------------------*/
3414 /* addSign - complete with sign */
3415 /*-----------------------------------------------------------------*/
3417 addSign (operand * result, int offset, int sign)
3419 int size = (getDataSize (result) - offset);
3424 emitcode ("rlc", "a");
3425 emitcode ("subb", "a,acc");
3427 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3431 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3435 /*-----------------------------------------------------------------*/
3436 /* genMinusBits - generates code for subtraction of two bits */
3437 /*-----------------------------------------------------------------*/
3439 genMinusBits (iCode * ic)
3441 symbol *lbl = newiTempLabel (NULL);
3443 D(emitcode ("; genMinusBits",""));
3445 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3447 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3448 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3449 emitcode ("cpl", "c");
3450 emitcode ("", "%05d$:", (lbl->key + 100));
3451 outBitC (IC_RESULT (ic));
3455 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3456 emitcode ("subb", "a,acc");
3457 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3458 emitcode ("inc", "a");
3459 emitcode ("", "%05d$:", (lbl->key + 100));
3460 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3461 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3465 /*-----------------------------------------------------------------*/
3466 /* genMinus - generates code for subtraction */
3467 /*-----------------------------------------------------------------*/
3469 genMinus (iCode * ic)
3471 int size, offset = 0;
3473 D(emitcode ("; genMinus",""));
3475 aopOp (IC_LEFT (ic), ic, FALSE);
3476 aopOp (IC_RIGHT (ic), ic, FALSE);
3477 aopOp (IC_RESULT (ic), ic, TRUE);
3479 /* special cases :- */
3480 /* if both left & right are in bit space */
3481 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3482 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3488 /* if I can do an decrement instead
3489 of subtract then GOOD for ME */
3490 if (genMinusDec (ic) == TRUE)
3493 size = getDataSize (IC_RESULT (ic));
3495 /* if literal, add a,#-lit, else normal subb */
3496 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3498 unsigned long lit = 0L;
3500 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3505 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3506 /* first add without previous c */
3508 if (!size && lit== (unsigned long) -1) {
3509 emitcode ("dec", "a");
3511 emitcode ("add", "a,#0x%02x",
3512 (unsigned int) (lit & 0x0FFL));
3515 emitcode ("addc", "a,#0x%02x",
3516 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3518 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3523 asmop *leftOp, *rightOp;
3525 leftOp = AOP(IC_LEFT(ic));
3526 rightOp = AOP(IC_RIGHT(ic));
3530 if (aopGetUsesAcc(rightOp, offset)) {
3531 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3532 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3534 emitcode( "setb", "c");
3536 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3537 emitcode("cpl", "a");
3539 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3542 emitcode ("subb", "a,%s",
3543 aopGet(rightOp, offset, FALSE, TRUE));
3546 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3551 adjustArithmeticResult (ic);
3554 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3555 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3556 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3560 /*-----------------------------------------------------------------*/
3561 /* genMultbits :- multiplication of bits */
3562 /*-----------------------------------------------------------------*/
3564 genMultbits (operand * left,
3568 D(emitcode ("; genMultbits",""));
3570 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3571 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3576 /*-----------------------------------------------------------------*/
3577 /* genMultOneByte : 8*8=8/16 bit multiplication */
3578 /*-----------------------------------------------------------------*/
3580 genMultOneByte (operand * left,
3584 sym_link *opetype = operandType (result);
3586 int size=AOP_SIZE(result);
3588 D(emitcode ("; genMultOneByte",""));
3590 if (size<1 || size>2) {
3591 // this should never happen
3592 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3593 AOP_SIZE(result), __FILE__, lineno);
3597 /* (if two literals: the value is computed before) */
3598 /* if one literal, literal on the right */
3599 if (AOP_TYPE (left) == AOP_LIT)
3604 //emitcode (";", "swapped left and right");
3607 if (SPEC_USIGN(opetype)
3608 // ignore the sign of left and right, what else can we do?
3609 || (SPEC_USIGN(operandType(left)) &&
3610 SPEC_USIGN(operandType(right)))) {
3611 // just an unsigned 8*8=8/16 multiply
3612 //emitcode (";","unsigned");
3613 // TODO: check for accumulator clash between left & right aops?
3614 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3615 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3616 emitcode ("mul", "ab");
3617 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3619 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3624 // we have to do a signed multiply
3626 //emitcode (";", "signed");
3627 emitcode ("clr", "F0"); // reset sign flag
3628 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3630 lbl=newiTempLabel(NULL);
3631 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3632 // left side is negative, 8-bit two's complement, this fails for -128
3633 emitcode ("setb", "F0"); // set sign flag
3634 emitcode ("cpl", "a");
3635 emitcode ("inc", "a");
3637 emitcode ("", "%05d$:", lbl->key+100);
3640 if (AOP_TYPE(right)==AOP_LIT) {
3641 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3642 /* AND literal negative */
3644 emitcode ("cpl", "F0"); // complement sign flag
3645 emitcode ("mov", "b,#0x%02x", -val);
3647 emitcode ("mov", "b,#0x%02x", val);
3650 lbl=newiTempLabel(NULL);
3651 emitcode ("mov", "b,a");
3652 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3653 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3654 // right side is negative, 8-bit two's complement
3655 emitcode ("cpl", "F0"); // complement sign flag
3656 emitcode ("cpl", "a");
3657 emitcode ("inc", "a");
3658 emitcode ("", "%05d$:", lbl->key+100);
3660 emitcode ("mul", "ab");
3662 lbl=newiTempLabel(NULL);
3663 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3664 // only ONE op was negative, we have to do a 8/16-bit two's complement
3665 emitcode ("cpl", "a"); // lsb
3667 emitcode ("inc", "a");
3669 emitcode ("add", "a,#1");
3670 emitcode ("xch", "a,b");
3671 emitcode ("cpl", "a"); // msb
3672 emitcode ("addc", "a,#0");
3673 emitcode ("xch", "a,b");
3676 emitcode ("", "%05d$:", lbl->key+100);
3677 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3679 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3683 /*-----------------------------------------------------------------*/
3684 /* genMult - generates code for multiplication */
3685 /*-----------------------------------------------------------------*/
3687 genMult (iCode * ic)
3689 operand *left = IC_LEFT (ic);
3690 operand *right = IC_RIGHT (ic);
3691 operand *result = IC_RESULT (ic);
3693 D(emitcode ("; genMult",""));
3695 /* assign the amsops */
3696 aopOp (left, ic, FALSE);
3697 aopOp (right, ic, FALSE);
3698 aopOp (result, ic, TRUE);
3700 /* special cases first */
3702 if (AOP_TYPE (left) == AOP_CRY &&
3703 AOP_TYPE (right) == AOP_CRY)
3705 genMultbits (left, right, result);
3709 /* if both are of size == 1 */
3710 #if 0 // one of them can be a sloc shared with the result
3711 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3713 if (getSize(operandType(left)) == 1 &&
3714 getSize(operandType(right)) == 1)
3717 genMultOneByte (left, right, result);
3721 /* should have been converted to function call */
3722 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3723 getSize(OP_SYMBOL(right)->type));
3727 freeAsmop (result, NULL, ic, TRUE);
3728 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3729 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3732 /*-----------------------------------------------------------------*/
3733 /* genDivbits :- division of bits */
3734 /*-----------------------------------------------------------------*/
3736 genDivbits (operand * left,
3743 D(emitcode ("; genDivbits",""));
3745 /* the result must be bit */
3746 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3747 l = aopGet (AOP (left), 0, FALSE, FALSE);
3751 emitcode ("div", "ab");
3752 emitcode ("rrc", "a");
3753 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3756 /*-----------------------------------------------------------------*/
3757 /* genDivOneByte : 8 bit division */
3758 /*-----------------------------------------------------------------*/
3760 genDivOneByte (operand * left,
3764 sym_link *opetype = operandType (result);
3769 D(emitcode ("; genDivOneByte",""));
3771 size = AOP_SIZE (result) - 1;
3773 /* signed or unsigned */
3774 if (SPEC_USIGN (opetype))
3776 /* unsigned is easy */
3777 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3778 l = aopGet (AOP (left), 0, FALSE, FALSE);
3780 emitcode ("div", "ab");
3781 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3783 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3787 /* signed is a little bit more difficult */
3789 /* save the signs of the operands */
3790 l = aopGet (AOP (left), 0, FALSE, FALSE);
3792 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3793 emitcode ("push", "acc"); /* save it on the stack */
3795 /* now sign adjust for both left & right */
3796 l = aopGet (AOP (right), 0, FALSE, FALSE);
3798 lbl = newiTempLabel (NULL);
3799 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3800 emitcode ("cpl", "a");
3801 emitcode ("inc", "a");
3802 emitcode ("", "%05d$:", (lbl->key + 100));
3803 emitcode ("mov", "b,a");
3805 /* sign adjust left side */
3806 l = aopGet (AOP (left), 0, FALSE, FALSE);
3809 lbl = newiTempLabel (NULL);
3810 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3811 emitcode ("cpl", "a");
3812 emitcode ("inc", "a");
3813 emitcode ("", "%05d$:", (lbl->key + 100));
3815 /* now the division */
3816 emitcode ("div", "ab");
3817 /* we are interested in the lower order
3819 emitcode ("mov", "b,a");
3820 lbl = newiTempLabel (NULL);
3821 emitcode ("pop", "acc");
3822 /* if there was an over flow we don't
3823 adjust the sign of the result */
3824 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3825 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3827 emitcode ("clr", "a");
3828 emitcode ("subb", "a,b");
3829 emitcode ("mov", "b,a");
3830 emitcode ("", "%05d$:", (lbl->key + 100));
3832 /* now we are done */
3833 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3836 emitcode ("mov", "c,b.7");
3837 emitcode ("subb", "a,acc");
3840 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3844 /*-----------------------------------------------------------------*/
3845 /* genDiv - generates code for division */
3846 /*-----------------------------------------------------------------*/
3850 operand *left = IC_LEFT (ic);
3851 operand *right = IC_RIGHT (ic);
3852 operand *result = IC_RESULT (ic);
3854 D(emitcode ("; genDiv",""));
3856 /* assign the amsops */
3857 aopOp (left, ic, FALSE);
3858 aopOp (right, ic, FALSE);
3859 aopOp (result, ic, TRUE);
3861 /* special cases first */
3863 if (AOP_TYPE (left) == AOP_CRY &&
3864 AOP_TYPE (right) == AOP_CRY)
3866 genDivbits (left, right, result);
3870 /* if both are of size == 1 */
3871 if (AOP_SIZE (left) == 1 &&
3872 AOP_SIZE (right) == 1)
3874 genDivOneByte (left, right, result);
3878 /* should have been converted to function call */
3881 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3882 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3883 freeAsmop (result, NULL, ic, TRUE);
3886 /*-----------------------------------------------------------------*/
3887 /* genModbits :- modulus of bits */
3888 /*-----------------------------------------------------------------*/
3890 genModbits (operand * left,
3897 D(emitcode ("; genModbits",""));
3899 /* the result must be bit */
3900 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3901 l = aopGet (AOP (left), 0, FALSE, FALSE);
3905 emitcode ("div", "ab");
3906 emitcode ("mov", "a,b");
3907 emitcode ("rrc", "a");
3908 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3911 /*-----------------------------------------------------------------*/
3912 /* genModOneByte : 8 bit modulus */
3913 /*-----------------------------------------------------------------*/
3915 genModOneByte (operand * left,
3919 sym_link *opetype = operandType (result);
3923 D(emitcode ("; genModOneByte",""));
3925 /* signed or unsigned */
3926 if (SPEC_USIGN (opetype))
3928 /* unsigned is easy */
3929 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3930 l = aopGet (AOP (left), 0, FALSE, FALSE);
3932 emitcode ("div", "ab");
3933 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3937 /* signed is a little bit more difficult */
3939 /* save the signs of the operands */
3940 l = aopGet (AOP (left), 0, FALSE, FALSE);
3943 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3944 emitcode ("push", "acc"); /* save it on the stack */
3946 /* now sign adjust for both left & right */
3947 l = aopGet (AOP (right), 0, FALSE, FALSE);
3950 lbl = newiTempLabel (NULL);
3951 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3952 emitcode ("cpl", "a");
3953 emitcode ("inc", "a");
3954 emitcode ("", "%05d$:", (lbl->key + 100));
3955 emitcode ("mov", "b,a");
3957 /* sign adjust left side */
3958 l = aopGet (AOP (left), 0, FALSE, FALSE);
3961 lbl = newiTempLabel (NULL);
3962 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3963 emitcode ("cpl", "a");
3964 emitcode ("inc", "a");
3965 emitcode ("", "%05d$:", (lbl->key + 100));
3967 /* now the multiplication */
3968 emitcode ("div", "ab");
3969 /* we are interested in the lower order
3971 lbl = newiTempLabel (NULL);
3972 emitcode ("pop", "acc");
3973 /* if there was an over flow we don't
3974 adjust the sign of the result */
3975 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3976 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3978 emitcode ("clr", "a");
3979 emitcode ("subb", "a,b");
3980 emitcode ("mov", "b,a");
3981 emitcode ("", "%05d$:", (lbl->key + 100));
3983 /* now we are done */
3984 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3988 /*-----------------------------------------------------------------*/
3989 /* genMod - generates code for division */
3990 /*-----------------------------------------------------------------*/
3994 operand *left = IC_LEFT (ic);
3995 operand *right = IC_RIGHT (ic);
3996 operand *result = IC_RESULT (ic);
3998 D(emitcode ("; genMod",""));
4000 /* assign the amsops */
4001 aopOp (left, ic, FALSE);
4002 aopOp (right, ic, FALSE);
4003 aopOp (result, ic, TRUE);
4005 /* special cases first */
4007 if (AOP_TYPE (left) == AOP_CRY &&
4008 AOP_TYPE (right) == AOP_CRY)
4010 genModbits (left, right, result);
4014 /* if both are of size == 1 */
4015 if (AOP_SIZE (left) == 1 &&
4016 AOP_SIZE (right) == 1)
4018 genModOneByte (left, right, result);
4022 /* should have been converted to function call */
4026 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4027 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4028 freeAsmop (result, NULL, ic, TRUE);
4031 /*-----------------------------------------------------------------*/
4032 /* genIfxJump :- will create a jump depending on the ifx */
4033 /*-----------------------------------------------------------------*/
4035 genIfxJump (iCode * ic, char *jval)
4038 symbol *tlbl = newiTempLabel (NULL);
4041 D(emitcode ("; genIfxJump",""));
4043 /* if true label then we jump if condition
4047 jlbl = IC_TRUE (ic);
4048 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4049 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4053 /* false label is present */
4054 jlbl = IC_FALSE (ic);
4055 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4056 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4058 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4059 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4061 emitcode (inst, "%05d$", tlbl->key + 100);
4062 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4063 emitcode ("", "%05d$:", tlbl->key + 100);
4065 /* mark the icode as generated */
4069 /*-----------------------------------------------------------------*/
4070 /* genCmp :- greater or less than comparison */
4071 /*-----------------------------------------------------------------*/
4073 genCmp (operand * left, operand * right,
4074 operand * result, iCode * ifx, int sign, iCode *ic)
4076 int size, offset = 0;
4077 unsigned long lit = 0L;
4080 D(emitcode ("; genCmp",""));
4082 /* if left & right are bit variables */
4083 if (AOP_TYPE (left) == AOP_CRY &&
4084 AOP_TYPE (right) == AOP_CRY)
4086 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4087 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4091 /* subtract right from left if at the
4092 end the carry flag is set then we know that
4093 left is greater than right */
4094 size = max (AOP_SIZE (left), AOP_SIZE (right));
4096 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4097 if ((size == 1) && !sign &&
4098 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4100 symbol *lbl = newiTempLabel (NULL);
4101 emitcode ("cjne", "%s,%s,%05d$",
4102 aopGet (AOP (left), offset, FALSE, FALSE),
4103 aopGet (AOP (right), offset, FALSE, FALSE),
4105 emitcode ("", "%05d$:", lbl->key + 100);
4109 if (AOP_TYPE (right) == AOP_LIT)
4111 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4112 /* optimize if(x < 0) or if(x >= 0) */
4121 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4122 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4124 genIfxJump (ifx, "acc.7");
4128 emitcode ("rlc", "a");
4136 rightInB = aopGetUsesAcc(AOP (right), offset);
4138 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4139 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4140 if (sign && size == 0)
4142 emitcode ("xrl", "a,#0x80");
4143 if (AOP_TYPE (right) == AOP_LIT)
4145 unsigned long lit = (unsigned long)
4146 floatFromVal (AOP (right)->aopu.aop_lit);
4147 emitcode ("subb", "a,#0x%02x",
4148 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4153 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4154 emitcode ("xrl", "b,#0x80");
4155 emitcode ("subb", "a,b");
4161 emitcode ("subb", "a,b");
4163 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4171 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4172 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4173 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4179 /* if the result is used in the next
4180 ifx conditional branch then generate
4181 code a little differently */
4183 genIfxJump (ifx, "c");
4186 /* leave the result in acc */
4190 /*-----------------------------------------------------------------*/
4191 /* genCmpGt :- greater than comparison */
4192 /*-----------------------------------------------------------------*/
4194 genCmpGt (iCode * ic, iCode * ifx)
4196 operand *left, *right, *result;
4197 sym_link *letype, *retype;
4200 D(emitcode ("; genCmpGt",""));
4202 left = IC_LEFT (ic);
4203 right = IC_RIGHT (ic);
4204 result = IC_RESULT (ic);
4206 letype = getSpec (operandType (left));
4207 retype = getSpec (operandType (right));
4208 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4209 /* assign the amsops */
4210 aopOp (left, ic, FALSE);
4211 aopOp (right, ic, FALSE);
4212 aopOp (result, ic, TRUE);
4214 genCmp (right, left, result, ifx, sign,ic);
4216 freeAsmop (result, NULL, ic, TRUE);
4219 /*-----------------------------------------------------------------*/
4220 /* genCmpLt - less than comparisons */
4221 /*-----------------------------------------------------------------*/
4223 genCmpLt (iCode * ic, iCode * ifx)
4225 operand *left, *right, *result;
4226 sym_link *letype, *retype;
4229 D(emitcode ("; genCmpLt",""));
4231 left = IC_LEFT (ic);
4232 right = IC_RIGHT (ic);
4233 result = IC_RESULT (ic);
4235 letype = getSpec (operandType (left));
4236 retype = getSpec (operandType (right));
4237 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4239 /* assign the amsops */
4240 aopOp (left, ic, FALSE);
4241 aopOp (right, ic, FALSE);
4242 aopOp (result, ic, TRUE);
4244 genCmp (left, right, result, ifx, sign,ic);
4246 freeAsmop (result, NULL, ic, TRUE);
4249 /*-----------------------------------------------------------------*/
4250 /* gencjneshort - compare and jump if not equal */
4251 /*-----------------------------------------------------------------*/
4253 gencjneshort (operand * left, operand * right, symbol * lbl)
4255 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4257 unsigned long lit = 0L;
4259 /* if the left side is a literal or
4260 if the right is in a pointer register and left
4262 if ((AOP_TYPE (left) == AOP_LIT) ||
4263 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4269 if (AOP_TYPE (right) == AOP_LIT)
4270 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4272 /* if the right side is a literal then anything goes */
4273 if (AOP_TYPE (right) == AOP_LIT &&
4274 AOP_TYPE (left) != AOP_DIR &&
4275 AOP_TYPE (left) != AOP_IMMD)
4279 emitcode ("cjne", "%s,%s,%05d$",
4280 aopGet (AOP (left), offset, FALSE, FALSE),
4281 aopGet (AOP (right), offset, FALSE, FALSE),
4287 /* if the right side is in a register or in direct space or
4288 if the left is a pointer register & right is not */
4289 else if (AOP_TYPE (right) == AOP_REG ||
4290 AOP_TYPE (right) == AOP_DIR ||
4291 AOP_TYPE (right) == AOP_LIT ||
4292 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4293 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4297 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4298 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4299 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4300 emitcode ("jnz", "%05d$", lbl->key + 100);
4302 emitcode ("cjne", "a,%s,%05d$",
4303 aopGet (AOP (right), offset, FALSE, TRUE),
4310 /* right is a pointer reg need both a & b */
4313 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4314 if (strcmp (l, "b"))
4315 emitcode ("mov", "b,%s", l);
4316 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4317 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4323 /*-----------------------------------------------------------------*/
4324 /* gencjne - compare and jump if not equal */
4325 /*-----------------------------------------------------------------*/
4327 gencjne (operand * left, operand * right, symbol * lbl)
4329 symbol *tlbl = newiTempLabel (NULL);
4331 gencjneshort (left, right, lbl);
4333 emitcode ("mov", "a,%s", one);
4334 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4335 emitcode ("", "%05d$:", lbl->key + 100);
4336 emitcode ("clr", "a");
4337 emitcode ("", "%05d$:", tlbl->key + 100);
4340 /*-----------------------------------------------------------------*/
4341 /* genCmpEq - generates code for equal to */
4342 /*-----------------------------------------------------------------*/
4344 genCmpEq (iCode * ic, iCode * ifx)
4346 operand *left, *right, *result;
4348 D(emitcode ("; genCmpEq",""));
4350 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4351 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4352 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4354 /* if literal, literal on the right or
4355 if the right is in a pointer register and left
4357 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4358 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4360 operand *t = IC_RIGHT (ic);
4361 IC_RIGHT (ic) = IC_LEFT (ic);
4365 if (ifx && !AOP_SIZE (result))
4368 /* if they are both bit variables */
4369 if (AOP_TYPE (left) == AOP_CRY &&
4370 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4372 if (AOP_TYPE (right) == AOP_LIT)
4374 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4377 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4378 emitcode ("cpl", "c");
4382 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4386 emitcode ("clr", "c");
4388 /* AOP_TYPE(right) == AOP_CRY */
4392 symbol *lbl = newiTempLabel (NULL);
4393 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4394 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4395 emitcode ("cpl", "c");
4396 emitcode ("", "%05d$:", (lbl->key + 100));
4398 /* if true label then we jump if condition
4400 tlbl = newiTempLabel (NULL);
4403 emitcode ("jnc", "%05d$", tlbl->key + 100);
4404 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4408 emitcode ("jc", "%05d$", tlbl->key + 100);
4409 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4411 emitcode ("", "%05d$:", tlbl->key + 100);
4415 tlbl = newiTempLabel (NULL);
4416 gencjneshort (left, right, tlbl);
4419 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4420 emitcode ("", "%05d$:", tlbl->key + 100);
4424 symbol *lbl = newiTempLabel (NULL);
4425 emitcode ("sjmp", "%05d$", lbl->key + 100);
4426 emitcode ("", "%05d$:", tlbl->key + 100);
4427 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4428 emitcode ("", "%05d$:", lbl->key + 100);
4431 /* mark the icode as generated */
4436 /* if they are both bit variables */
4437 if (AOP_TYPE (left) == AOP_CRY &&
4438 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4440 if (AOP_TYPE (right) == AOP_LIT)
4442 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4445 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4446 emitcode ("cpl", "c");
4450 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4454 emitcode ("clr", "c");
4456 /* AOP_TYPE(right) == AOP_CRY */
4460 symbol *lbl = newiTempLabel (NULL);
4461 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4462 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4463 emitcode ("cpl", "c");
4464 emitcode ("", "%05d$:", (lbl->key + 100));
4467 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4474 genIfxJump (ifx, "c");
4477 /* if the result is used in an arithmetic operation
4478 then put the result in place */
4483 gencjne (left, right, newiTempLabel (NULL));
4484 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4486 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4491 genIfxJump (ifx, "a");
4494 /* if the result is used in an arithmetic operation
4495 then put the result in place */
4496 if (AOP_TYPE (result) != AOP_CRY)
4498 /* leave the result in acc */
4502 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4503 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4504 freeAsmop (result, NULL, ic, TRUE);
4507 /*-----------------------------------------------------------------*/
4508 /* ifxForOp - returns the icode containing the ifx for operand */
4509 /*-----------------------------------------------------------------*/
4511 ifxForOp (operand * op, iCode * ic)
4513 /* if true symbol then needs to be assigned */
4514 if (IS_TRUE_SYMOP (op))
4517 /* if this has register type condition and
4518 the next instruction is ifx with the same operand
4519 and live to of the operand is upto the ifx only then */
4521 ic->next->op == IFX &&
4522 IC_COND (ic->next)->key == op->key &&
4523 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4529 /*-----------------------------------------------------------------*/
4530 /* hasInc - operand is incremented before any other use */
4531 /*-----------------------------------------------------------------*/
4533 hasInc (operand *op, iCode *ic,int osize)
4535 sym_link *type = operandType(op);
4536 sym_link *retype = getSpec (type);
4537 iCode *lic = ic->next;
4540 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4541 if (!IS_SYMOP(op)) return NULL;
4543 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4544 if (IS_AGGREGATE(type->next)) return NULL;
4545 if (osize != (isize = getSize(type->next))) return NULL;
4548 /* if operand of the form op = op + <sizeof *op> */
4549 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4550 isOperandEqual(IC_RESULT(lic),op) &&
4551 isOperandLiteral(IC_RIGHT(lic)) &&
4552 operandLitValue(IC_RIGHT(lic)) == isize) {
4555 /* if the operand used or deffed */
4556 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4559 /* if GOTO or IFX */
4560 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4566 /*-----------------------------------------------------------------*/
4567 /* genAndOp - for && operation */
4568 /*-----------------------------------------------------------------*/
4570 genAndOp (iCode * ic)
4572 operand *left, *right, *result;
4575 D(emitcode ("; genAndOp",""));
4577 /* note here that && operations that are in an
4578 if statement are taken away by backPatchLabels
4579 only those used in arthmetic operations remain */
4580 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4581 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4582 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4584 /* if both are bit variables */
4585 if (AOP_TYPE (left) == AOP_CRY &&
4586 AOP_TYPE (right) == AOP_CRY)
4588 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4589 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4594 tlbl = newiTempLabel (NULL);
4596 emitcode ("jz", "%05d$", tlbl->key + 100);
4598 emitcode ("", "%05d$:", tlbl->key + 100);
4602 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4603 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4604 freeAsmop (result, NULL, ic, TRUE);
4608 /*-----------------------------------------------------------------*/
4609 /* genOrOp - for || operation */
4610 /*-----------------------------------------------------------------*/
4612 genOrOp (iCode * ic)
4614 operand *left, *right, *result;
4617 D(emitcode ("; genOrOp",""));
4619 /* note here that || operations that are in an
4620 if statement are taken away by backPatchLabels
4621 only those used in arthmetic operations remain */
4622 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4623 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4624 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4626 /* if both are bit variables */
4627 if (AOP_TYPE (left) == AOP_CRY &&
4628 AOP_TYPE (right) == AOP_CRY)
4630 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4631 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4636 tlbl = newiTempLabel (NULL);
4638 emitcode ("jnz", "%05d$", tlbl->key + 100);
4640 emitcode ("", "%05d$:", tlbl->key + 100);
4644 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4645 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4646 freeAsmop (result, NULL, ic, TRUE);
4649 /*-----------------------------------------------------------------*/
4650 /* isLiteralBit - test if lit == 2^n */
4651 /*-----------------------------------------------------------------*/
4653 isLiteralBit (unsigned long lit)
4655 unsigned long pw[32] =
4656 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4657 0x100L, 0x200L, 0x400L, 0x800L,
4658 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4659 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4660 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4661 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4662 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4665 for (idx = 0; idx < 32; idx++)
4671 /*-----------------------------------------------------------------*/
4672 /* continueIfTrue - */
4673 /*-----------------------------------------------------------------*/
4675 continueIfTrue (iCode * ic)
4678 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4682 /*-----------------------------------------------------------------*/
4684 /*-----------------------------------------------------------------*/
4686 jumpIfTrue (iCode * ic)
4689 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4693 /*-----------------------------------------------------------------*/
4694 /* jmpTrueOrFalse - */
4695 /*-----------------------------------------------------------------*/
4697 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4699 // ugly but optimized by peephole
4702 symbol *nlbl = newiTempLabel (NULL);
4703 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4704 emitcode ("", "%05d$:", tlbl->key + 100);
4705 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4706 emitcode ("", "%05d$:", nlbl->key + 100);
4710 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4711 emitcode ("", "%05d$:", tlbl->key + 100);
4716 /*-----------------------------------------------------------------*/
4717 /* genAnd - code for and */
4718 /*-----------------------------------------------------------------*/
4720 genAnd (iCode * ic, iCode * ifx)
4722 operand *left, *right, *result;
4723 int size, offset = 0;
4724 unsigned long lit = 0L;
4728 D(emitcode ("; genAnd",""));
4730 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4731 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4732 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4735 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4737 AOP_TYPE (left), AOP_TYPE (right));
4738 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4740 AOP_SIZE (left), AOP_SIZE (right));
4743 /* if left is a literal & right is not then exchange them */
4744 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4745 AOP_NEEDSACC (left))
4747 operand *tmp = right;
4752 /* if result = right then exchange them */
4753 if (sameRegs (AOP (result), AOP (right)))
4755 operand *tmp = right;
4760 /* if right is bit then exchange them */
4761 if (AOP_TYPE (right) == AOP_CRY &&
4762 AOP_TYPE (left) != AOP_CRY)
4764 operand *tmp = right;
4768 if (AOP_TYPE (right) == AOP_LIT)
4769 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4771 size = AOP_SIZE (result);
4774 // result = bit & yy;
4775 if (AOP_TYPE (left) == AOP_CRY)
4777 // c = bit & literal;
4778 if (AOP_TYPE (right) == AOP_LIT)
4782 if (size && sameRegs (AOP (result), AOP (left)))
4785 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4790 if (size && (AOP_TYPE (result) == AOP_CRY))
4792 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4795 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4800 emitcode ("clr", "c");
4805 if (AOP_TYPE (right) == AOP_CRY)
4808 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4809 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4814 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4816 emitcode ("rrc", "a");
4817 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4825 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4826 genIfxJump (ifx, "c");
4830 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4831 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4832 if ((AOP_TYPE (right) == AOP_LIT) &&
4833 (AOP_TYPE (result) == AOP_CRY) &&
4834 (AOP_TYPE (left) != AOP_CRY))
4836 int posbit = isLiteralBit (lit);
4841 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4844 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4850 sprintf (buffer, "acc.%d", posbit & 0x07);
4851 genIfxJump (ifx, buffer);
4858 symbol *tlbl = newiTempLabel (NULL);
4859 int sizel = AOP_SIZE (left);
4861 emitcode ("setb", "c");
4864 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4866 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4868 if ((posbit = isLiteralBit (bytelit)) != 0)
4869 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4872 if (bytelit != 0x0FFL)
4873 emitcode ("anl", "a,%s",
4874 aopGet (AOP (right), offset, FALSE, TRUE));
4875 emitcode ("jnz", "%05d$", tlbl->key + 100);
4880 // bit = left & literal
4883 emitcode ("clr", "c");
4884 emitcode ("", "%05d$:", tlbl->key + 100);
4886 // if(left & literal)
4890 jmpTrueOrFalse (ifx, tlbl);
4898 /* if left is same as result */
4899 if (sameRegs (AOP (result), AOP (left)))
4901 for (; size--; offset++)
4903 if (AOP_TYPE (right) == AOP_LIT)
4905 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4907 else if (bytelit == 0)
4909 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4911 else if (IS_AOP_PREG (result))
4913 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4914 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4915 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4918 emitcode ("anl", "%s,%s",
4919 aopGet (AOP (left), offset, FALSE, TRUE),
4920 aopGet (AOP (right), offset, FALSE, FALSE));
4924 if (AOP_TYPE (left) == AOP_ACC)
4925 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4928 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4929 if (IS_AOP_PREG (result))
4931 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4932 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4936 emitcode ("anl", "%s,a",
4937 aopGet (AOP (left), offset, FALSE, TRUE));
4944 // left & result in different registers
4945 if (AOP_TYPE (result) == AOP_CRY)
4948 // if(size), result in bit
4949 // if(!size && ifx), conditional oper: if(left & right)
4950 symbol *tlbl = newiTempLabel (NULL);
4951 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4953 emitcode ("setb", "c");
4956 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4957 emitcode ("anl", "a,%s",
4958 aopGet (AOP (right), offset, FALSE, FALSE));
4960 if (AOP_TYPE(left)==AOP_ACC) {
4961 emitcode("mov", "b,a");
4962 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4963 emitcode("anl", "a,b");
4965 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4966 emitcode ("anl", "a,%s",
4967 aopGet (AOP (left), offset, FALSE, FALSE));
4970 emitcode ("jnz", "%05d$", tlbl->key + 100);
4976 emitcode ("", "%05d$:", tlbl->key + 100);
4980 jmpTrueOrFalse (ifx, tlbl);
4984 for (; (size--); offset++)
4987 // result = left & right
4988 if (AOP_TYPE (right) == AOP_LIT)
4990 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4992 aopPut (AOP (result),
4993 aopGet (AOP (left), offset, FALSE, FALSE),
4995 isOperandVolatile (result, FALSE));
4998 else if (bytelit == 0)
5000 /* dummy read of volatile operand */
5001 if (isOperandVolatile (left, FALSE))
5002 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5003 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5007 // faster than result <- left, anl result,right
5008 // and better if result is SFR
5009 if (AOP_TYPE (left) == AOP_ACC)
5010 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5013 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5014 emitcode ("anl", "a,%s",
5015 aopGet (AOP (left), offset, FALSE, FALSE));
5017 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5023 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5024 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5025 freeAsmop (result, NULL, ic, TRUE);
5028 /*-----------------------------------------------------------------*/
5029 /* genOr - code for or */
5030 /*-----------------------------------------------------------------*/
5032 genOr (iCode * ic, iCode * ifx)
5034 operand *left, *right, *result;
5035 int size, offset = 0;
5036 unsigned long lit = 0L;
5038 D(emitcode ("; genOr",""));
5040 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5041 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5042 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5045 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5047 AOP_TYPE (left), AOP_TYPE (right));
5048 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5050 AOP_SIZE (left), AOP_SIZE (right));
5053 /* if left is a literal & right is not then exchange them */
5054 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5055 AOP_NEEDSACC (left))
5057 operand *tmp = right;
5062 /* if result = right then exchange them */
5063 if (sameRegs (AOP (result), AOP (right)))
5065 operand *tmp = right;
5070 /* if right is bit then exchange them */
5071 if (AOP_TYPE (right) == AOP_CRY &&
5072 AOP_TYPE (left) != AOP_CRY)
5074 operand *tmp = right;
5078 if (AOP_TYPE (right) == AOP_LIT)
5079 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5081 size = AOP_SIZE (result);
5085 if (AOP_TYPE (left) == AOP_CRY)
5087 if (AOP_TYPE (right) == AOP_LIT)
5089 // c = bit | literal;
5092 // lit != 0 => result = 1
5093 if (AOP_TYPE (result) == AOP_CRY)
5096 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5098 continueIfTrue (ifx);
5101 emitcode ("setb", "c");
5105 // lit == 0 => result = left
5106 if (size && sameRegs (AOP (result), AOP (left)))
5108 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5113 if (AOP_TYPE (right) == AOP_CRY)
5116 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5117 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5122 symbol *tlbl = newiTempLabel (NULL);
5123 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5124 emitcode ("setb", "c");
5125 emitcode ("jb", "%s,%05d$",
5126 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5128 emitcode ("jnz", "%05d$", tlbl->key + 100);
5129 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5131 jmpTrueOrFalse (ifx, tlbl);
5137 emitcode ("", "%05d$:", tlbl->key + 100);
5146 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5147 genIfxJump (ifx, "c");
5151 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5152 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5153 if ((AOP_TYPE (right) == AOP_LIT) &&
5154 (AOP_TYPE (result) == AOP_CRY) &&
5155 (AOP_TYPE (left) != AOP_CRY))
5161 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5163 continueIfTrue (ifx);
5168 // lit = 0, result = boolean(left)
5170 emitcode ("setb", "c");
5174 symbol *tlbl = newiTempLabel (NULL);
5175 emitcode ("jnz", "%05d$", tlbl->key + 100);
5177 emitcode ("", "%05d$:", tlbl->key + 100);
5181 genIfxJump (ifx, "a");
5189 /* if left is same as result */
5190 if (sameRegs (AOP (result), AOP (left)))
5192 for (; size--; offset++)
5194 if (AOP_TYPE (right) == AOP_LIT)
5196 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5198 /* dummy read of volatile operand */
5199 if (isOperandVolatile (left, FALSE))
5200 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5204 else if (IS_AOP_PREG (left))
5206 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5207 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5208 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5211 emitcode ("orl", "%s,%s",
5212 aopGet (AOP (left), offset, FALSE, TRUE),
5213 aopGet (AOP (right), offset, FALSE, FALSE));
5217 if (AOP_TYPE (left) == AOP_ACC)
5218 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5221 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5222 if (IS_AOP_PREG (left))
5224 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5225 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5228 emitcode ("orl", "%s,a",
5229 aopGet (AOP (left), offset, FALSE, TRUE));
5236 // left & result in different registers
5237 if (AOP_TYPE (result) == AOP_CRY)
5240 // if(size), result in bit
5241 // if(!size && ifx), conditional oper: if(left | right)
5242 symbol *tlbl = newiTempLabel (NULL);
5243 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5245 emitcode ("setb", "c");
5248 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5249 emitcode ("orl", "a,%s",
5250 aopGet (AOP (right), offset, FALSE, FALSE));
5252 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5253 emitcode ("orl", "a,%s",
5254 aopGet (AOP (left), offset, FALSE, FALSE));
5256 emitcode ("jnz", "%05d$", tlbl->key + 100);
5262 emitcode ("", "%05d$:", tlbl->key + 100);
5266 jmpTrueOrFalse (ifx, tlbl);
5269 for (; (size--); offset++)
5272 // result = left & right
5273 if (AOP_TYPE (right) == AOP_LIT)
5275 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5277 aopPut (AOP (result),
5278 aopGet (AOP (left), offset, FALSE, FALSE),
5280 isOperandVolatile (result, FALSE));
5284 // faster than result <- left, anl result,right
5285 // and better if result is SFR
5286 if (AOP_TYPE (left) == AOP_ACC)
5287 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5290 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5291 emitcode ("orl", "a,%s",
5292 aopGet (AOP (left), offset, FALSE, FALSE));
5294 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5299 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5300 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5301 freeAsmop (result, NULL, ic, TRUE);
5304 /*-----------------------------------------------------------------*/
5305 /* genXor - code for xclusive or */
5306 /*-----------------------------------------------------------------*/
5308 genXor (iCode * ic, iCode * ifx)
5310 operand *left, *right, *result;
5311 int size, offset = 0;
5312 unsigned long lit = 0L;
5314 D(emitcode ("; genXor",""));
5316 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5317 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5318 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5321 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5323 AOP_TYPE (left), AOP_TYPE (right));
5324 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5326 AOP_SIZE (left), AOP_SIZE (right));
5329 /* if left is a literal & right is not ||
5330 if left needs acc & right does not */
5331 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5332 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5334 operand *tmp = right;
5339 /* if result = right then exchange them */
5340 if (sameRegs (AOP (result), AOP (right)))
5342 operand *tmp = right;
5347 /* if right is bit then exchange them */
5348 if (AOP_TYPE (right) == AOP_CRY &&
5349 AOP_TYPE (left) != AOP_CRY)
5351 operand *tmp = right;
5355 if (AOP_TYPE (right) == AOP_LIT)
5356 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5358 size = AOP_SIZE (result);
5362 if (AOP_TYPE (left) == AOP_CRY)
5364 if (AOP_TYPE (right) == AOP_LIT)
5366 // c = bit & literal;
5369 // lit>>1 != 0 => result = 1
5370 if (AOP_TYPE (result) == AOP_CRY)
5373 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5375 continueIfTrue (ifx);
5378 emitcode ("setb", "c");
5385 // lit == 0, result = left
5386 if (size && sameRegs (AOP (result), AOP (left)))
5388 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5392 // lit == 1, result = not(left)
5393 if (size && sameRegs (AOP (result), AOP (left)))
5395 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5400 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5401 emitcode ("cpl", "c");
5410 symbol *tlbl = newiTempLabel (NULL);
5411 if (AOP_TYPE (right) == AOP_CRY)
5414 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5418 int sizer = AOP_SIZE (right);
5420 // if val>>1 != 0, result = 1
5421 emitcode ("setb", "c");
5424 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5426 // test the msb of the lsb
5427 emitcode ("anl", "a,#0xfe");
5428 emitcode ("jnz", "%05d$", tlbl->key + 100);
5432 emitcode ("rrc", "a");
5434 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5435 emitcode ("cpl", "c");
5436 emitcode ("", "%05d$:", (tlbl->key + 100));
5443 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5444 genIfxJump (ifx, "c");
5448 if (sameRegs (AOP (result), AOP (left)))
5450 /* if left is same as result */
5451 for (; size--; offset++)
5453 if (AOP_TYPE (right) == AOP_LIT)
5455 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5457 else if (IS_AOP_PREG (left))
5459 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5460 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5461 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5464 emitcode ("xrl", "%s,%s",
5465 aopGet (AOP (left), offset, FALSE, TRUE),
5466 aopGet (AOP (right), offset, FALSE, FALSE));
5470 if (AOP_TYPE (left) == AOP_ACC)
5471 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5474 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5475 if (IS_AOP_PREG (left))
5477 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5478 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5481 emitcode ("xrl", "%s,a",
5482 aopGet (AOP (left), offset, FALSE, TRUE));
5489 // left & result in different registers
5490 if (AOP_TYPE (result) == AOP_CRY)
5493 // if(size), result in bit
5494 // if(!size && ifx), conditional oper: if(left ^ right)
5495 symbol *tlbl = newiTempLabel (NULL);
5496 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5498 emitcode ("setb", "c");
5501 if ((AOP_TYPE (right) == AOP_LIT) &&
5502 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5504 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5508 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5509 emitcode ("xrl", "a,%s",
5510 aopGet (AOP (right), offset, FALSE, FALSE));
5512 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5513 emitcode ("xrl", "a,%s",
5514 aopGet (AOP (left), offset, FALSE, FALSE));
5517 emitcode ("jnz", "%05d$", tlbl->key + 100);
5523 emitcode ("", "%05d$:", tlbl->key + 100);
5527 jmpTrueOrFalse (ifx, tlbl);
5530 for (; (size--); offset++)
5533 // result = left & right
5534 if (AOP_TYPE (right) == AOP_LIT)
5536 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5538 aopPut (AOP (result),
5539 aopGet (AOP (left), offset, FALSE, FALSE),
5541 isOperandVolatile (result, FALSE));
5545 // faster than result <- left, anl result,right
5546 // and better if result is SFR
5547 if (AOP_TYPE (left) == AOP_ACC)
5548 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5551 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5552 emitcode ("xrl", "a,%s",
5553 aopGet (AOP (left), offset, FALSE, TRUE));
5555 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5560 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5561 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5562 freeAsmop (result, NULL, ic, TRUE);
5565 /*-----------------------------------------------------------------*/
5566 /* genInline - write the inline code out */
5567 /*-----------------------------------------------------------------*/
5569 genInline (iCode * ic)
5571 char *buffer, *bp, *bp1;
5573 D(emitcode ("; genInline",""));
5575 _G.inLine += (!options.asmpeep);
5577 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5578 strcpy (buffer, IC_INLINE (ic));
5580 /* emit each line as a code */
5605 /* emitcode("",buffer); */
5606 _G.inLine -= (!options.asmpeep);
5609 /*-----------------------------------------------------------------*/
5610 /* genRRC - rotate right with carry */
5611 /*-----------------------------------------------------------------*/
5615 operand *left, *result;
5616 int size, offset = 0;
5619 D(emitcode ("; genRRC",""));
5621 /* rotate right with carry */
5622 left = IC_LEFT (ic);
5623 result = IC_RESULT (ic);
5624 aopOp (left, ic, FALSE);
5625 aopOp (result, ic, FALSE);
5627 /* move it to the result */
5628 size = AOP_SIZE (result);
5630 if (size == 1) { /* special case for 1 byte */
5631 l = aopGet (AOP (left), offset, FALSE, FALSE);
5633 emitcode ("rr", "a");
5639 l = aopGet (AOP (left), offset, FALSE, FALSE);
5641 emitcode ("rrc", "a");
5642 if (AOP_SIZE (result) > 1)
5643 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5645 /* now we need to put the carry into the
5646 highest order byte of the result */
5647 if (AOP_SIZE (result) > 1)
5649 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5652 emitcode ("mov", "acc.7,c");
5654 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5655 freeAsmop (left, NULL, ic, TRUE);
5656 freeAsmop (result, NULL, ic, TRUE);
5659 /*-----------------------------------------------------------------*/
5660 /* genRLC - generate code for rotate left with carry */
5661 /*-----------------------------------------------------------------*/
5665 operand *left, *result;
5666 int size, offset = 0;
5669 D(emitcode ("; genRLC",""));
5671 /* rotate right with carry */
5672 left = IC_LEFT (ic);
5673 result = IC_RESULT (ic);
5674 aopOp (left, ic, FALSE);
5675 aopOp (result, ic, FALSE);
5677 /* move it to the result */
5678 size = AOP_SIZE (result);
5682 l = aopGet (AOP (left), offset, FALSE, FALSE);
5684 if (size == 0) { /* special case for 1 byte */
5688 emitcode ("add", "a,acc");
5689 if (AOP_SIZE (result) > 1)
5690 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5693 l = aopGet (AOP (left), offset, FALSE, FALSE);
5695 emitcode ("rlc", "a");
5696 if (AOP_SIZE (result) > 1)
5697 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5700 /* now we need to put the carry into the
5701 highest order byte of the result */
5702 if (AOP_SIZE (result) > 1)
5704 l = aopGet (AOP (result), 0, FALSE, FALSE);
5707 emitcode ("mov", "acc.0,c");
5709 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5710 freeAsmop (left, NULL, ic, TRUE);
5711 freeAsmop (result, NULL, ic, TRUE);
5714 /*-----------------------------------------------------------------*/
5715 /* genGetHbit - generates code get highest order bit */
5716 /*-----------------------------------------------------------------*/
5718 genGetHbit (iCode * ic)
5720 operand *left, *result;
5722 D(emitcode ("; genGetHbit",""));
5724 left = IC_LEFT (ic);
5725 result = IC_RESULT (ic);
5726 aopOp (left, ic, FALSE);
5727 aopOp (result, ic, FALSE);
5729 /* get the highest order byte into a */
5730 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5731 if (AOP_TYPE (result) == AOP_CRY)
5733 emitcode ("rlc", "a");
5738 emitcode ("rl", "a");
5739 emitcode ("anl", "a,#0x01");
5744 freeAsmop (left, NULL, ic, TRUE);
5745 freeAsmop (result, NULL, ic, TRUE);
5748 /*-----------------------------------------------------------------*/
5749 /* AccRol - rotate left accumulator by known count */
5750 /*-----------------------------------------------------------------*/
5752 AccRol (int shCount)
5754 shCount &= 0x0007; // shCount : 0..7
5761 emitcode ("rl", "a");
5764 emitcode ("rl", "a");
5765 emitcode ("rl", "a");
5768 emitcode ("swap", "a");
5769 emitcode ("rr", "a");
5772 emitcode ("swap", "a");
5775 emitcode ("swap", "a");
5776 emitcode ("rl", "a");
5779 emitcode ("rr", "a");
5780 emitcode ("rr", "a");
5783 emitcode ("rr", "a");
5788 /*-----------------------------------------------------------------*/
5789 /* AccLsh - left shift accumulator by known count */
5790 /*-----------------------------------------------------------------*/
5792 AccLsh (int shCount)
5797 emitcode ("add", "a,acc");
5798 else if (shCount == 2)
5800 emitcode ("add", "a,acc");
5801 emitcode ("add", "a,acc");
5805 /* rotate left accumulator */
5807 /* and kill the lower order bits */
5808 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5813 /*-----------------------------------------------------------------*/
5814 /* AccRsh - right shift accumulator by known count */
5815 /*-----------------------------------------------------------------*/
5817 AccRsh (int shCount)
5824 emitcode ("rrc", "a");
5828 /* rotate right accumulator */
5829 AccRol (8 - shCount);
5830 /* and kill the higher order bits */
5831 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5836 /*-----------------------------------------------------------------*/
5837 /* AccSRsh - signed right shift accumulator by known count */
5838 /*-----------------------------------------------------------------*/
5840 AccSRsh (int shCount)
5847 emitcode ("mov", "c,acc.7");
5848 emitcode ("rrc", "a");
5850 else if (shCount == 2)
5852 emitcode ("mov", "c,acc.7");
5853 emitcode ("rrc", "a");
5854 emitcode ("mov", "c,acc.7");
5855 emitcode ("rrc", "a");
5859 tlbl = newiTempLabel (NULL);
5860 /* rotate right accumulator */
5861 AccRol (8 - shCount);
5862 /* and kill the higher order bits */
5863 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5864 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5865 emitcode ("orl", "a,#0x%02x",
5866 (unsigned char) ~SRMask[shCount]);
5867 emitcode ("", "%05d$:", tlbl->key + 100);
5872 /*-----------------------------------------------------------------*/
5873 /* shiftR1Left2Result - shift right one byte from left to result */
5874 /*-----------------------------------------------------------------*/
5876 shiftR1Left2Result (operand * left, int offl,
5877 operand * result, int offr,
5878 int shCount, int sign)
5880 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5881 /* shift right accumulator */
5886 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5889 /*-----------------------------------------------------------------*/
5890 /* shiftL1Left2Result - shift left one byte from left to result */
5891 /*-----------------------------------------------------------------*/
5893 shiftL1Left2Result (operand * left, int offl,
5894 operand * result, int offr, int shCount)
5897 l = aopGet (AOP (left), offl, FALSE, FALSE);
5899 /* shift left accumulator */
5901 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5904 /*-----------------------------------------------------------------*/
5905 /* movLeft2Result - move byte from left to result */
5906 /*-----------------------------------------------------------------*/
5908 movLeft2Result (operand * left, int offl,
5909 operand * result, int offr, int sign)
5912 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5914 l = aopGet (AOP (left), offl, FALSE, FALSE);
5916 if (*l == '@' && (IS_AOP_PREG (result)))
5918 emitcode ("mov", "a,%s", l);
5919 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5924 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
5927 /* MSB sign in acc.7 ! */
5928 if (getDataSize (left) == offl + 1)
5930 emitcode ("mov", "a,%s", l);
5931 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5938 /*-----------------------------------------------------------------*/
5939 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5940 /*-----------------------------------------------------------------*/
5944 emitcode ("rrc", "a");
5945 emitcode ("xch", "a,%s", x);
5946 emitcode ("rrc", "a");
5947 emitcode ("xch", "a,%s", x);
5950 /*-----------------------------------------------------------------*/
5951 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5952 /*-----------------------------------------------------------------*/
5956 emitcode ("xch", "a,%s", x);
5957 emitcode ("rlc", "a");
5958 emitcode ("xch", "a,%s", x);
5959 emitcode ("rlc", "a");
5962 /*-----------------------------------------------------------------*/
5963 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5964 /*-----------------------------------------------------------------*/
5968 emitcode ("xch", "a,%s", x);
5969 emitcode ("add", "a,acc");
5970 emitcode ("xch", "a,%s", x);
5971 emitcode ("rlc", "a");
5974 /*-----------------------------------------------------------------*/
5975 /* AccAXLsh - left shift a:x by known count (0..7) */
5976 /*-----------------------------------------------------------------*/
5978 AccAXLsh (char *x, int shCount)
5993 case 5: // AAAAABBB:CCCCCDDD
5995 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5997 emitcode ("anl", "a,#0x%02x",
5998 SLMask[shCount]); // BBB00000:CCCCCDDD
6000 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6002 AccRol (shCount); // DDDCCCCC:BBB00000
6004 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6006 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6008 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6010 emitcode ("anl", "a,#0x%02x",
6011 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6013 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6015 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6018 case 6: // AAAAAABB:CCCCCCDD
6019 emitcode ("anl", "a,#0x%02x",
6020 SRMask[shCount]); // 000000BB:CCCCCCDD
6021 emitcode ("mov", "c,acc.0"); // c = B
6022 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6024 AccAXRrl1 (x); // BCCCCCCD:D000000B
6025 AccAXRrl1 (x); // BBCCCCCC:DD000000
6027 emitcode("rrc","a");
6028 emitcode("xch","a,%s", x);
6029 emitcode("rrc","a");
6030 emitcode("mov","c,acc.0"); //<< get correct bit
6031 emitcode("xch","a,%s", x);
6033 emitcode("rrc","a");
6034 emitcode("xch","a,%s", x);
6035 emitcode("rrc","a");
6036 emitcode("xch","a,%s", x);
6039 case 7: // a:x <<= 7
6041 emitcode ("anl", "a,#0x%02x",
6042 SRMask[shCount]); // 0000000B:CCCCCCCD
6044 emitcode ("mov", "c,acc.0"); // c = B
6046 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6048 AccAXRrl1 (x); // BCCCCCCC:D0000000
6056 /*-----------------------------------------------------------------*/
6057 /* AccAXRsh - right shift a:x known count (0..7) */
6058 /*-----------------------------------------------------------------*/
6060 AccAXRsh (char *x, int shCount)
6068 AccAXRrl1 (x); // 0->a:x
6073 AccAXRrl1 (x); // 0->a:x
6076 AccAXRrl1 (x); // 0->a:x
6081 case 5: // AAAAABBB:CCCCCDDD = a:x
6083 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6085 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6087 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6089 emitcode ("anl", "a,#0x%02x",
6090 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6092 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6094 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6096 emitcode ("anl", "a,#0x%02x",
6097 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6099 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6101 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6103 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6106 case 6: // AABBBBBB:CCDDDDDD
6108 emitcode ("mov", "c,acc.7");
6109 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6111 emitcode ("mov", "c,acc.7");
6112 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6114 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6116 emitcode ("anl", "a,#0x%02x",
6117 SRMask[shCount]); // 000000AA:BBBBBBCC
6120 case 7: // ABBBBBBB:CDDDDDDD
6122 emitcode ("mov", "c,acc.7"); // c = A
6124 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6126 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6128 emitcode ("anl", "a,#0x%02x",
6129 SRMask[shCount]); // 0000000A:BBBBBBBC
6137 /*-----------------------------------------------------------------*/
6138 /* AccAXRshS - right shift signed a:x known count (0..7) */
6139 /*-----------------------------------------------------------------*/
6141 AccAXRshS (char *x, int shCount)
6149 emitcode ("mov", "c,acc.7");
6150 AccAXRrl1 (x); // s->a:x
6154 emitcode ("mov", "c,acc.7");
6155 AccAXRrl1 (x); // s->a:x
6157 emitcode ("mov", "c,acc.7");
6158 AccAXRrl1 (x); // s->a:x
6163 case 5: // AAAAABBB:CCCCCDDD = a:x
6165 tlbl = newiTempLabel (NULL);
6166 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6168 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6170 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6172 emitcode ("anl", "a,#0x%02x",
6173 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6175 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6177 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6179 emitcode ("anl", "a,#0x%02x",
6180 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6182 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6184 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6186 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6188 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6189 emitcode ("orl", "a,#0x%02x",
6190 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6192 emitcode ("", "%05d$:", tlbl->key + 100);
6193 break; // SSSSAAAA:BBBCCCCC
6195 case 6: // AABBBBBB:CCDDDDDD
6197 tlbl = newiTempLabel (NULL);
6198 emitcode ("mov", "c,acc.7");
6199 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6201 emitcode ("mov", "c,acc.7");
6202 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6204 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6206 emitcode ("anl", "a,#0x%02x",
6207 SRMask[shCount]); // 000000AA:BBBBBBCC
6209 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6210 emitcode ("orl", "a,#0x%02x",
6211 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6213 emitcode ("", "%05d$:", tlbl->key + 100);
6215 case 7: // ABBBBBBB:CDDDDDDD
6217 tlbl = newiTempLabel (NULL);
6218 emitcode ("mov", "c,acc.7"); // c = A
6220 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6222 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6224 emitcode ("anl", "a,#0x%02x",
6225 SRMask[shCount]); // 0000000A:BBBBBBBC
6227 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6228 emitcode ("orl", "a,#0x%02x",
6229 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6231 emitcode ("", "%05d$:", tlbl->key + 100);
6238 /*-----------------------------------------------------------------*/
6239 /* shiftL2Left2Result - shift left two bytes from left to result */
6240 /*-----------------------------------------------------------------*/
6242 shiftL2Left2Result (operand * left, int offl,
6243 operand * result, int offr, int shCount)
6245 if (sameRegs (AOP (result), AOP (left)) &&
6246 ((offl + MSB16) == offr))
6248 /* don't crash result[offr] */
6249 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6250 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6254 movLeft2Result (left, offl, result, offr, 0);
6255 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6257 /* ax << shCount (x = lsb(result)) */
6258 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6259 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6263 /*-----------------------------------------------------------------*/
6264 /* shiftR2Left2Result - shift right two bytes from left to result */
6265 /*-----------------------------------------------------------------*/
6267 shiftR2Left2Result (operand * left, int offl,
6268 operand * result, int offr,
6269 int shCount, int sign)
6271 if (sameRegs (AOP (result), AOP (left)) &&
6272 ((offl + MSB16) == offr))
6274 /* don't crash result[offr] */
6275 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6276 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6280 movLeft2Result (left, offl, result, offr, 0);
6281 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6283 /* a:x >> shCount (x = lsb(result)) */
6285 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6287 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6288 if (getDataSize (result) > 1)
6289 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6292 /*-----------------------------------------------------------------*/
6293 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6294 /*-----------------------------------------------------------------*/
6296 shiftLLeftOrResult (operand * left, int offl,
6297 operand * result, int offr, int shCount)
6299 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6300 /* shift left accumulator */
6302 /* or with result */
6303 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6304 /* back to result */
6305 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6308 /*-----------------------------------------------------------------*/
6309 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6310 /*-----------------------------------------------------------------*/
6312 shiftRLeftOrResult (operand * left, int offl,
6313 operand * result, int offr, int shCount)
6315 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6316 /* shift right accumulator */
6318 /* or with result */
6319 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6320 /* back to result */
6321 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6324 /*-----------------------------------------------------------------*/
6325 /* genlshOne - left shift a one byte quantity by known count */
6326 /*-----------------------------------------------------------------*/
6328 genlshOne (operand * result, operand * left, int shCount)
6330 D(emitcode ("; genlshOne",""));
6332 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6335 /*-----------------------------------------------------------------*/
6336 /* genlshTwo - left shift two bytes by known amount != 0 */
6337 /*-----------------------------------------------------------------*/
6339 genlshTwo (operand * result, operand * left, int shCount)
6343 D(emitcode ("; genlshTwo",""));
6345 size = getDataSize (result);
6347 /* if shCount >= 8 */
6355 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6357 movLeft2Result (left, LSB, result, MSB16, 0);
6359 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6362 /* 1 <= shCount <= 7 */
6366 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6368 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6372 /*-----------------------------------------------------------------*/
6373 /* shiftLLong - shift left one long from left to result */
6374 /* offl = LSB or MSB16 */
6375 /*-----------------------------------------------------------------*/
6377 shiftLLong (operand * left, operand * result, int offr)
6380 int size = AOP_SIZE (result);
6382 if (size >= LSB + offr)
6384 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6386 emitcode ("add", "a,acc");
6387 if (sameRegs (AOP (left), AOP (result)) &&
6388 size >= MSB16 + offr && offr != LSB)
6389 emitcode ("xch", "a,%s",
6390 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6392 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6395 if (size >= MSB16 + offr)
6397 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6399 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6402 emitcode ("rlc", "a");
6403 if (sameRegs (AOP (left), AOP (result)) &&
6404 size >= MSB24 + offr && offr != LSB)
6405 emitcode ("xch", "a,%s",
6406 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6408 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6411 if (size >= MSB24 + offr)
6413 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6415 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6418 emitcode ("rlc", "a");
6419 if (sameRegs (AOP (left), AOP (result)) &&
6420 size >= MSB32 + offr && offr != LSB)
6421 emitcode ("xch", "a,%s",
6422 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6424 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6427 if (size > MSB32 + offr)
6429 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6431 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6434 emitcode ("rlc", "a");
6435 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6438 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6441 /*-----------------------------------------------------------------*/
6442 /* genlshFour - shift four byte by a known amount != 0 */
6443 /*-----------------------------------------------------------------*/
6445 genlshFour (operand * result, operand * left, int shCount)
6449 D(emitcode ("; genlshFour",""));
6451 size = AOP_SIZE (result);
6453 /* if shifting more that 3 bytes */
6458 /* lowest order of left goes to the highest
6459 order of the destination */
6460 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6462 movLeft2Result (left, LSB, result, MSB32, 0);
6463 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6464 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6465 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6469 /* more than two bytes */
6470 else if (shCount >= 16)
6472 /* lower order two bytes goes to higher order two bytes */
6474 /* if some more remaining */
6476 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6479 movLeft2Result (left, MSB16, result, MSB32, 0);
6480 movLeft2Result (left, LSB, result, MSB24, 0);
6482 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6483 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6487 /* if more than 1 byte */
6488 else if (shCount >= 8)
6490 /* lower order three bytes goes to higher order three bytes */
6495 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6497 movLeft2Result (left, LSB, result, MSB16, 0);
6503 movLeft2Result (left, MSB24, result, MSB32, 0);
6504 movLeft2Result (left, MSB16, result, MSB24, 0);
6505 movLeft2Result (left, LSB, result, MSB16, 0);
6506 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6508 else if (shCount == 1)
6509 shiftLLong (left, result, MSB16);
6512 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6513 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6514 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6515 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6520 /* 1 <= shCount <= 7 */
6521 else if (shCount <= 2)
6523 shiftLLong (left, result, LSB);
6525 shiftLLong (result, result, LSB);
6527 /* 3 <= shCount <= 7, optimize */
6530 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6531 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6532 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6536 /*-----------------------------------------------------------------*/
6537 /* genLeftShiftLiteral - left shifting by known count */
6538 /*-----------------------------------------------------------------*/
6540 genLeftShiftLiteral (operand * left,
6545 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6548 D(emitcode ("; genLeftShiftLiteral",""));
6550 freeAsmop (right, NULL, ic, TRUE);
6552 aopOp (left, ic, FALSE);
6553 aopOp (result, ic, FALSE);
6555 size = getSize (operandType (result));
6558 emitcode ("; shift left ", "result %d, left %d", size,
6562 /* I suppose that the left size >= result size */
6567 movLeft2Result (left, size, result, size, 0);
6571 else if (shCount >= (size * 8))
6573 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6579 genlshOne (result, left, shCount);
6583 genlshTwo (result, left, shCount);
6587 genlshFour (result, left, shCount);
6590 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6591 "*** ack! mystery literal shift!\n");
6595 freeAsmop (left, NULL, ic, TRUE);
6596 freeAsmop (result, NULL, ic, TRUE);
6599 /*-----------------------------------------------------------------*/
6600 /* genLeftShift - generates code for left shifting */
6601 /*-----------------------------------------------------------------*/
6603 genLeftShift (iCode * ic)
6605 operand *left, *right, *result;
6608 symbol *tlbl, *tlbl1;
6610 D(emitcode ("; genLeftShift",""));
6612 right = IC_RIGHT (ic);
6613 left = IC_LEFT (ic);
6614 result = IC_RESULT (ic);
6616 aopOp (right, ic, FALSE);
6618 /* if the shift count is known then do it
6619 as efficiently as possible */
6620 if (AOP_TYPE (right) == AOP_LIT)
6622 genLeftShiftLiteral (left, right, result, ic);
6626 /* shift count is unknown then we have to form
6627 a loop get the loop count in B : Note: we take
6628 only the lower order byte since shifting
6629 more that 32 bits make no sense anyway, ( the
6630 largest size of an object can be only 32 bits ) */
6632 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6633 emitcode ("inc", "b");
6634 freeAsmop (right, NULL, ic, TRUE);
6635 aopOp (left, ic, FALSE);
6636 aopOp (result, ic, FALSE);
6638 /* now move the left to the result if they are not the
6640 if (!sameRegs (AOP (left), AOP (result)) &&
6641 AOP_SIZE (result) > 1)
6644 size = AOP_SIZE (result);
6648 l = aopGet (AOP (left), offset, FALSE, TRUE);
6649 if (*l == '@' && (IS_AOP_PREG (result)))
6652 emitcode ("mov", "a,%s", l);
6653 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6656 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6661 tlbl = newiTempLabel (NULL);
6662 size = AOP_SIZE (result);
6664 tlbl1 = newiTempLabel (NULL);
6666 /* if it is only one byte then */
6669 symbol *tlbl1 = newiTempLabel (NULL);
6671 l = aopGet (AOP (left), 0, FALSE, FALSE);
6673 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6674 emitcode ("", "%05d$:", tlbl->key + 100);
6675 emitcode ("add", "a,acc");
6676 emitcode ("", "%05d$:", tlbl1->key + 100);
6677 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6678 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6682 reAdjustPreg (AOP (result));
6684 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6685 emitcode ("", "%05d$:", tlbl->key + 100);
6686 l = aopGet (AOP (result), offset, FALSE, FALSE);
6688 emitcode ("add", "a,acc");
6689 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6692 l = aopGet (AOP (result), offset, FALSE, FALSE);
6694 emitcode ("rlc", "a");
6695 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6697 reAdjustPreg (AOP (result));
6699 emitcode ("", "%05d$:", tlbl1->key + 100);
6700 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6702 freeAsmop (left, NULL, ic, TRUE);
6703 freeAsmop (result, NULL, ic, TRUE);
6706 /*-----------------------------------------------------------------*/
6707 /* genrshOne - right shift a one byte quantity by known count */
6708 /*-----------------------------------------------------------------*/
6710 genrshOne (operand * result, operand * left,
6711 int shCount, int sign)
6713 D(emitcode ("; genrshOne",""));
6715 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6718 /*-----------------------------------------------------------------*/
6719 /* genrshTwo - right shift two bytes by known amount != 0 */
6720 /*-----------------------------------------------------------------*/
6722 genrshTwo (operand * result, operand * left,
6723 int shCount, int sign)
6725 D(emitcode ("; genrshTwo",""));
6727 /* if shCount >= 8 */
6732 shiftR1Left2Result (left, MSB16, result, LSB,
6735 movLeft2Result (left, MSB16, result, LSB, sign);
6736 addSign (result, MSB16, sign);
6739 /* 1 <= shCount <= 7 */
6741 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6744 /*-----------------------------------------------------------------*/
6745 /* shiftRLong - shift right one long from left to result */
6746 /* offl = LSB or MSB16 */
6747 /*-----------------------------------------------------------------*/
6749 shiftRLong (operand * left, int offl,
6750 operand * result, int sign)
6752 int isSameRegs=sameRegs(AOP(left),AOP(result));
6754 if (isSameRegs && offl>1) {
6755 // we are in big trouble, but this shouldn't happen
6756 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6759 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6764 emitcode ("rlc", "a");
6765 emitcode ("subb", "a,acc");
6767 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6769 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6770 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6773 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6778 emitcode ("clr", "c");
6780 emitcode ("mov", "c,acc.7");
6783 emitcode ("rrc", "a");
6785 if (isSameRegs && offl==MSB16) {
6786 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6788 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6789 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6792 emitcode ("rrc", "a");
6793 if (isSameRegs && offl==1) {
6794 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6796 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6797 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6799 emitcode ("rrc", "a");
6800 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6804 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6805 emitcode ("rrc", "a");
6806 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6810 /*-----------------------------------------------------------------*/
6811 /* genrshFour - shift four byte by a known amount != 0 */
6812 /*-----------------------------------------------------------------*/
6814 genrshFour (operand * result, operand * left,
6815 int shCount, int sign)
6817 D(emitcode ("; genrshFour",""));
6819 /* if shifting more that 3 bytes */
6824 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6826 movLeft2Result (left, MSB32, result, LSB, sign);
6827 addSign (result, MSB16, sign);
6829 else if (shCount >= 16)
6833 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6836 movLeft2Result (left, MSB24, result, LSB, 0);
6837 movLeft2Result (left, MSB32, result, MSB16, sign);
6839 addSign (result, MSB24, sign);
6841 else if (shCount >= 8)
6845 shiftRLong (left, MSB16, result, sign);
6846 else if (shCount == 0)
6848 movLeft2Result (left, MSB16, result, LSB, 0);
6849 movLeft2Result (left, MSB24, result, MSB16, 0);
6850 movLeft2Result (left, MSB32, result, MSB24, sign);
6851 addSign (result, MSB32, sign);
6855 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6856 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6857 /* the last shift is signed */
6858 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6859 addSign (result, MSB32, sign);
6863 { /* 1 <= shCount <= 7 */
6866 shiftRLong (left, LSB, result, sign);
6868 shiftRLong (result, LSB, result, sign);
6872 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6873 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6874 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6879 /*-----------------------------------------------------------------*/
6880 /* genRightShiftLiteral - right shifting by known count */
6881 /*-----------------------------------------------------------------*/
6883 genRightShiftLiteral (operand * left,
6889 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6892 D(emitcode ("; genRightShiftLiteral",""));
6894 freeAsmop (right, NULL, ic, TRUE);
6896 aopOp (left, ic, FALSE);
6897 aopOp (result, ic, FALSE);
6900 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6904 size = getDataSize (left);
6905 /* test the LEFT size !!! */
6907 /* I suppose that the left size >= result size */
6910 size = getDataSize (result);
6912 movLeft2Result (left, size, result, size, 0);
6915 else if (shCount >= (size * 8))
6918 /* get sign in acc.7 */
6919 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6921 addSign (result, LSB, sign);
6928 genrshOne (result, left, shCount, sign);
6932 genrshTwo (result, left, shCount, sign);
6936 genrshFour (result, left, shCount, sign);
6942 freeAsmop (left, NULL, ic, TRUE);
6943 freeAsmop (result, NULL, ic, TRUE);
6946 /*-----------------------------------------------------------------*/
6947 /* genSignedRightShift - right shift of signed number */
6948 /*-----------------------------------------------------------------*/
6950 genSignedRightShift (iCode * ic)
6952 operand *right, *left, *result;
6955 symbol *tlbl, *tlbl1;
6957 D(emitcode ("; genSignedRightShift",""));
6959 /* we do it the hard way put the shift count in b
6960 and loop thru preserving the sign */
6962 right = IC_RIGHT (ic);
6963 left = IC_LEFT (ic);
6964 result = IC_RESULT (ic);
6966 aopOp (right, ic, FALSE);
6969 if (AOP_TYPE (right) == AOP_LIT)
6971 genRightShiftLiteral (left, right, result, ic, 1);
6974 /* shift count is unknown then we have to form
6975 a loop get the loop count in B : Note: we take
6976 only the lower order byte since shifting
6977 more that 32 bits make no sense anyway, ( the
6978 largest size of an object can be only 32 bits ) */
6980 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6981 emitcode ("inc", "b");
6982 freeAsmop (right, NULL, ic, TRUE);
6983 aopOp (left, ic, FALSE);
6984 aopOp (result, ic, FALSE);
6986 /* now move the left to the result if they are not the
6988 if (!sameRegs (AOP (left), AOP (result)) &&
6989 AOP_SIZE (result) > 1)
6992 size = AOP_SIZE (result);
6996 l = aopGet (AOP (left), offset, FALSE, TRUE);
6997 if (*l == '@' && IS_AOP_PREG (result))
7000 emitcode ("mov", "a,%s", l);
7001 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7004 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7009 /* mov the highest order bit to OVR */
7010 tlbl = newiTempLabel (NULL);
7011 tlbl1 = newiTempLabel (NULL);
7013 size = AOP_SIZE (result);
7015 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7016 emitcode ("rlc", "a");
7017 emitcode ("mov", "ov,c");
7018 /* if it is only one byte then */
7021 l = aopGet (AOP (left), 0, FALSE, FALSE);
7023 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7024 emitcode ("", "%05d$:", tlbl->key + 100);
7025 emitcode ("mov", "c,ov");
7026 emitcode ("rrc", "a");
7027 emitcode ("", "%05d$:", tlbl1->key + 100);
7028 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7029 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7033 reAdjustPreg (AOP (result));
7034 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7035 emitcode ("", "%05d$:", tlbl->key + 100);
7036 emitcode ("mov", "c,ov");
7039 l = aopGet (AOP (result), offset, FALSE, FALSE);
7041 emitcode ("rrc", "a");
7042 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7044 reAdjustPreg (AOP (result));
7045 emitcode ("", "%05d$:", tlbl1->key + 100);
7046 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7049 freeAsmop (left, NULL, ic, TRUE);
7050 freeAsmop (result, NULL, ic, TRUE);
7053 /*-----------------------------------------------------------------*/
7054 /* genRightShift - generate code for right shifting */
7055 /*-----------------------------------------------------------------*/
7057 genRightShift (iCode * ic)
7059 operand *right, *left, *result;
7063 symbol *tlbl, *tlbl1;
7065 D(emitcode ("; genRightShift",""));
7067 /* if signed then we do it the hard way preserve the
7068 sign bit moving it inwards */
7069 retype = getSpec (operandType (IC_RESULT (ic)));
7071 if (!SPEC_USIGN (retype))
7073 genSignedRightShift (ic);
7077 /* signed & unsigned types are treated the same : i.e. the
7078 signed is NOT propagated inwards : quoting from the
7079 ANSI - standard : "for E1 >> E2, is equivalent to division
7080 by 2**E2 if unsigned or if it has a non-negative value,
7081 otherwise the result is implementation defined ", MY definition
7082 is that the sign does not get propagated */
7084 right = IC_RIGHT (ic);
7085 left = IC_LEFT (ic);
7086 result = IC_RESULT (ic);
7088 aopOp (right, ic, FALSE);
7090 /* if the shift count is known then do it
7091 as efficiently as possible */
7092 if (AOP_TYPE (right) == AOP_LIT)
7094 genRightShiftLiteral (left, right, result, ic, 0);
7098 /* shift count is unknown then we have to form
7099 a loop get the loop count in B : Note: we take
7100 only the lower order byte since shifting
7101 more that 32 bits make no sense anyway, ( the
7102 largest size of an object can be only 32 bits ) */
7104 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7105 emitcode ("inc", "b");
7106 freeAsmop (right, NULL, ic, TRUE);
7107 aopOp (left, ic, FALSE);
7108 aopOp (result, ic, FALSE);
7110 /* now move the left to the result if they are not the
7112 if (!sameRegs (AOP (left), AOP (result)) &&
7113 AOP_SIZE (result) > 1)
7116 size = AOP_SIZE (result);
7120 l = aopGet (AOP (left), offset, FALSE, TRUE);
7121 if (*l == '@' && IS_AOP_PREG (result))
7124 emitcode ("mov", "a,%s", l);
7125 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7128 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7133 tlbl = newiTempLabel (NULL);
7134 tlbl1 = newiTempLabel (NULL);
7135 size = AOP_SIZE (result);
7138 /* if it is only one byte then */
7141 l = aopGet (AOP (left), 0, FALSE, FALSE);
7143 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7144 emitcode ("", "%05d$:", tlbl->key + 100);
7146 emitcode ("rrc", "a");
7147 emitcode ("", "%05d$:", tlbl1->key + 100);
7148 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7149 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7153 reAdjustPreg (AOP (result));
7154 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7155 emitcode ("", "%05d$:", tlbl->key + 100);
7159 l = aopGet (AOP (result), offset, FALSE, FALSE);
7161 emitcode ("rrc", "a");
7162 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7164 reAdjustPreg (AOP (result));
7166 emitcode ("", "%05d$:", tlbl1->key + 100);
7167 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7170 freeAsmop (left, NULL, ic, TRUE);
7171 freeAsmop (result, NULL, ic, TRUE);
7174 /*-----------------------------------------------------------------*/
7175 /* emitPtrByteGet - emits code to get a byte into A through a */
7176 /* pointer register (R0, R1, or DPTR). The */
7177 /* original value of A can be preserved in B. */
7178 /*-----------------------------------------------------------------*/
7180 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7187 emitcode ("mov", "b,a");
7188 emitcode ("mov", "a,@%s", rname);
7193 emitcode ("mov", "b,a");
7194 emitcode ("movx", "a,@%s", rname);
7199 emitcode ("mov", "b,a");
7200 emitcode ("movx", "a,@dptr");
7205 emitcode ("mov", "b,a");
7206 emitcode ("clr", "a");
7207 emitcode ("movc", "a,@a+dptr");
7213 emitcode ("push", "b");
7214 emitcode ("push", "acc");
7216 emitcode ("lcall", "__gptrget");
7218 emitcode ("pop", "b");
7223 /*-----------------------------------------------------------------*/
7224 /* emitPtrByteSet - emits code to set a byte from src through a */
7225 /* pointer register (R0, R1, or DPTR). */
7226 /*-----------------------------------------------------------------*/
7228 emitPtrByteSet (char *rname, int p_type, char *src)
7237 emitcode ("mov", "@%s,a", rname);
7240 emitcode ("mov", "@%s,%s", rname, src);
7245 emitcode ("movx", "@%s,a", rname);
7250 emitcode ("movx", "@dptr,a");
7255 emitcode ("lcall", "__gptrput");
7260 /*-----------------------------------------------------------------*/
7261 /* genUnpackBits - generates code for unpacking bits */
7262 /*-----------------------------------------------------------------*/
7264 genUnpackBits (operand * result, char *rname, int ptype)
7266 int offset = 0; /* result byte offset */
7267 int rsize; /* result size */
7268 int rlen = 0; /* remaining bitfield length */
7269 sym_link *etype; /* bitfield type information */
7270 int blen; /* bitfield length */
7271 int bstr; /* bitfield starting bit within byte */
7273 D(emitcode ("; genUnpackBits",""));
7275 etype = getSpec (operandType (result));
7276 rsize = getSize (operandType (result));
7277 blen = SPEC_BLEN (etype);
7278 bstr = SPEC_BSTR (etype);
7280 /* If the bitfield length is less than a byte */
7283 emitPtrByteGet (rname, ptype, FALSE);
7285 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7286 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7290 /* Bit field did not fit in a byte. Copy all
7291 but the partial byte at the end. */
7292 for (rlen=blen;rlen>=8;rlen-=8)
7294 emitPtrByteGet (rname, ptype, FALSE);
7295 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7297 emitcode ("inc", "%s", rname);
7300 /* Handle the partial byte at the end */
7303 emitPtrByteGet (rname, ptype, FALSE);
7304 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7305 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7313 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7318 /*-----------------------------------------------------------------*/
7319 /* genDataPointerGet - generates code when ptr offset is known */
7320 /*-----------------------------------------------------------------*/
7322 genDataPointerGet (operand * left,
7328 int size, offset = 0;
7330 D(emitcode ("; genDataPointerGet",""));
7332 aopOp (result, ic, TRUE);
7334 /* get the string representation of the name */
7335 l = aopGet (AOP (left), 0, FALSE, TRUE);
7336 size = AOP_SIZE (result);
7340 sprintf (buffer, "(%s + %d)", l + 1, offset);
7342 sprintf (buffer, "%s", l + 1);
7343 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7346 freeAsmop (left, NULL, ic, TRUE);
7347 freeAsmop (result, NULL, ic, TRUE);
7350 /*-----------------------------------------------------------------*/
7351 /* genNearPointerGet - emitcode for near pointer fetch */
7352 /*-----------------------------------------------------------------*/
7354 genNearPointerGet (operand * left,
7362 sym_link *rtype, *retype;
7363 sym_link *ltype = operandType (left);
7366 D(emitcode ("; genNearPointerGet",""));
7368 rtype = operandType (result);
7369 retype = getSpec (rtype);
7371 aopOp (left, ic, FALSE);
7373 /* if left is rematerialisable and
7374 result is not bit variable type and
7375 the left is pointer to data space i.e
7376 lower 128 bytes of space */
7377 if (AOP_TYPE (left) == AOP_IMMD &&
7378 !IS_BITVAR (retype) &&
7379 DCL_TYPE (ltype) == POINTER)
7381 genDataPointerGet (left, result, ic);
7385 /* if the value is already in a pointer register
7386 then don't need anything more */
7387 if (!AOP_INPREG (AOP (left)))
7389 if (IS_AOP_PREG (left))
7391 // Aha, it is a pointer, just in disguise.
7392 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7395 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7396 __FILE__, __LINE__);
7401 emitcode ("mov", "a%s,%s", rname + 1, rname);
7402 rname++; // skip the '@'.
7407 /* otherwise get a free pointer register */
7409 preg = getFreePtr (ic, &aop, FALSE);
7410 emitcode ("mov", "%s,%s",
7412 aopGet (AOP (left), 0, FALSE, TRUE));
7417 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7419 //aopOp (result, ic, FALSE);
7420 aopOp (result, ic, result?TRUE:FALSE);
7422 /* if bitfield then unpack the bits */
7423 if (IS_BITVAR (retype))
7424 genUnpackBits (result, rname, POINTER);
7427 /* we have can just get the values */
7428 int size = AOP_SIZE (result);
7433 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7436 emitcode ("mov", "a,@%s", rname);
7437 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7441 sprintf (buffer, "@%s", rname);
7442 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7446 emitcode ("inc", "%s", rname);
7450 /* now some housekeeping stuff */
7451 if (aop) /* we had to allocate for this iCode */
7453 if (pi) { /* post increment present */
7454 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7456 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7460 /* we did not allocate which means left
7461 already in a pointer register, then
7462 if size > 0 && this could be used again
7463 we have to point it back to where it
7465 if ((AOP_SIZE (result) > 1 &&
7466 !OP_SYMBOL (left)->remat &&
7467 (OP_SYMBOL (left)->liveTo > ic->seq ||
7471 int size = AOP_SIZE (result) - 1;
7473 emitcode ("dec", "%s", rname);
7478 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7479 freeAsmop (left, NULL, ic, TRUE);
7480 if (pi) pi->generated = 1;
7483 /*-----------------------------------------------------------------*/
7484 /* genPagedPointerGet - emitcode for paged pointer fetch */
7485 /*-----------------------------------------------------------------*/
7487 genPagedPointerGet (operand * left,
7495 sym_link *rtype, *retype;
7497 D(emitcode ("; genPagedPointerGet",""));
7499 rtype = operandType (result);
7500 retype = getSpec (rtype);
7502 aopOp (left, ic, FALSE);
7504 /* if the value is already in a pointer register
7505 then don't need anything more */
7506 if (!AOP_INPREG (AOP (left)))
7508 /* otherwise get a free pointer register */
7510 preg = getFreePtr (ic, &aop, FALSE);
7511 emitcode ("mov", "%s,%s",
7513 aopGet (AOP (left), 0, FALSE, TRUE));
7517 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7519 aopOp (result, ic, FALSE);
7521 /* if bitfield then unpack the bits */
7522 if (IS_BITVAR (retype))
7523 genUnpackBits (result, rname, PPOINTER);
7526 /* we have can just get the values */
7527 int size = AOP_SIZE (result);
7533 emitcode ("movx", "a,@%s", rname);
7534 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7539 emitcode ("inc", "%s", rname);
7543 /* now some housekeeping stuff */
7544 if (aop) /* we had to allocate for this iCode */
7546 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7547 freeAsmop (NULL, aop, ic, TRUE);
7551 /* we did not allocate which means left
7552 already in a pointer register, then
7553 if size > 0 && this could be used again
7554 we have to point it back to where it
7556 if ((AOP_SIZE (result) > 1 &&
7557 !OP_SYMBOL (left)->remat &&
7558 (OP_SYMBOL (left)->liveTo > ic->seq ||
7562 int size = AOP_SIZE (result) - 1;
7564 emitcode ("dec", "%s", rname);
7569 freeAsmop (left, NULL, ic, TRUE);
7570 freeAsmop (result, NULL, ic, TRUE);
7571 if (pi) pi->generated = 1;
7575 /*--------------------------------------------------------------------*/
7576 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7577 /*--------------------------------------------------------------------*/
7579 loadDptrFromOperand (operand *op, bool loadBToo)
7581 if (AOP_TYPE (op) != AOP_STR)
7583 /* if this is remateriazable */
7584 if (AOP_TYPE (op) == AOP_IMMD)
7586 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7589 if (AOP(op)->aopu.aop_immd.from_cast_remat)
7590 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7593 wassertl(FALSE, "need pointerCode");
7594 emitcode ("", "; mov b,???");
7595 /* genPointerGet and genPointerSet originally did different
7596 ** things for this case. Both seem wrong.
7597 ** from genPointerGet:
7598 ** emitcode ("mov", "b,#%d", pointerCode (retype));
7599 ** from genPointerSet:
7600 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7605 else if (AOP_TYPE (op) == AOP_DPTR)
7609 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7610 emitcode ("push", "acc");
7611 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7612 emitcode ("push", "acc");
7613 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7614 emitcode ("pop", "dph");
7615 emitcode ("pop", "dpl");
7619 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7620 emitcode ("push", "acc");
7621 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7622 emitcode ("pop", "dpl");
7626 { /* we need to get it byte by byte */
7627 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7628 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7630 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7635 /*-----------------------------------------------------------------*/
7636 /* genFarPointerGet - gget value from far space */
7637 /*-----------------------------------------------------------------*/
7639 genFarPointerGet (operand * left,
7640 operand * result, iCode * ic, iCode * pi)
7643 sym_link *retype = getSpec (operandType (result));
7645 D(emitcode ("; genFarPointerGet",""));
7647 aopOp (left, ic, FALSE);
7648 loadDptrFromOperand (left, FALSE);
7650 /* so dptr now contains the address */
7651 aopOp (result, ic, FALSE);
7653 /* if bit then unpack */
7654 if (IS_BITVAR (retype))
7655 genUnpackBits (result, "dptr", FPOINTER);
7658 size = AOP_SIZE (result);
7663 emitcode ("movx", "a,@dptr");
7664 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7666 emitcode ("inc", "dptr");
7670 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7671 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7672 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7675 freeAsmop (left, NULL, ic, TRUE);
7676 freeAsmop (result, NULL, ic, TRUE);
7679 /*-----------------------------------------------------------------*/
7680 /* genCodePointerGet - gget value from code space */
7681 /*-----------------------------------------------------------------*/
7683 genCodePointerGet (operand * left,
7684 operand * result, iCode * ic, iCode *pi)
7687 sym_link *retype = getSpec (operandType (result));
7689 D(emitcode ("; genCodePointerGet",""));
7691 aopOp (left, ic, FALSE);
7692 loadDptrFromOperand (left, FALSE);
7694 /* so dptr now contains the address */
7695 aopOp (result, ic, FALSE);
7697 /* if bit then unpack */
7698 if (IS_BITVAR (retype))
7699 genUnpackBits (result, "dptr", CPOINTER);
7702 size = AOP_SIZE (result);
7709 emitcode ("clr", "a");
7710 emitcode ("movc", "a,@a+dptr");
7711 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7712 emitcode ("inc", "dptr");
7716 emitcode ("mov", "a,#0x%02x", offset);
7717 emitcode ("movc", "a,@a+dptr");
7718 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7723 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7724 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7725 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7728 freeAsmop (left, NULL, ic, TRUE);
7729 freeAsmop (result, NULL, ic, TRUE);
7732 /*-----------------------------------------------------------------*/
7733 /* genGenPointerGet - gget value from generic pointer space */
7734 /*-----------------------------------------------------------------*/
7736 genGenPointerGet (operand * left,
7737 operand * result, iCode * ic, iCode *pi)
7740 sym_link *retype = getSpec (operandType (result));
7742 D(emitcode ("; genGenPointerGet",""));
7744 aopOp (left, ic, FALSE);
7745 loadDptrFromOperand (left, TRUE);
7747 /* so dptr know contains the address */
7748 aopOp (result, ic, FALSE);
7750 /* if bit then unpack */
7751 if (IS_BITVAR (retype))
7752 genUnpackBits (result, "dptr", GPOINTER);
7755 size = AOP_SIZE (result);
7760 emitcode ("lcall", "__gptrget");
7761 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7763 emitcode ("inc", "dptr");
7767 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7768 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7769 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7772 freeAsmop (left, NULL, ic, TRUE);
7773 freeAsmop (result, NULL, ic, TRUE);
7776 /*-----------------------------------------------------------------*/
7777 /* genPointerGet - generate code for pointer get */
7778 /*-----------------------------------------------------------------*/
7780 genPointerGet (iCode * ic, iCode *pi)
7782 operand *left, *result;
7783 sym_link *type, *etype;
7786 D(emitcode ("; genPointerGet",""));
7788 left = IC_LEFT (ic);
7789 result = IC_RESULT (ic);
7791 /* depending on the type of pointer we need to
7792 move it to the correct pointer register */
7793 type = operandType (left);
7794 etype = getSpec (type);
7795 /* if left is of type of pointer then it is simple */
7796 if (IS_PTR (type) && !IS_FUNC (type->next))
7797 p_type = DCL_TYPE (type);
7800 /* we have to go by the storage class */
7801 p_type = PTR_TYPE (SPEC_OCLS (etype));
7804 /* special case when cast remat */
7805 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7806 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7807 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7808 type = operandType (left);
7809 p_type = DCL_TYPE (type);
7811 /* now that we have the pointer type we assign
7812 the pointer values */
7818 genNearPointerGet (left, result, ic, pi);
7822 genPagedPointerGet (left, result, ic, pi);
7826 genFarPointerGet (left, result, ic, pi);
7830 genCodePointerGet (left, result, ic, pi);
7834 genGenPointerGet (left, result, ic, pi);
7842 /*-----------------------------------------------------------------*/
7843 /* genPackBits - generates code for packed bit storage */
7844 /*-----------------------------------------------------------------*/
7846 genPackBits (sym_link * etype,
7848 char *rname, int p_type)
7850 int offset = 0; /* source byte offset */
7851 int rlen = 0; /* remaining bitfield length */
7852 int blen; /* bitfield length */
7853 int bstr; /* bitfield starting bit within byte */
7854 int litval; /* source literal value (if AOP_LIT) */
7855 unsigned char mask; /* bitmask within current byte */
7857 D(emitcode ("; genPackBits",""));
7859 blen = SPEC_BLEN (etype);
7860 bstr = SPEC_BSTR (etype);
7862 /* If the bitfield length is less than a byte */
7865 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7866 (unsigned char) (0xFF >> (8 - bstr)));
7868 if (AOP_TYPE (right) == AOP_LIT)
7870 /* Case with a bitfield length <8 and literal source
7872 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7874 litval &= (~mask) & 0xff;
7875 emitPtrByteGet (rname, p_type, FALSE);
7876 if ((mask|litval)!=0xff)
7877 emitcode ("anl","a,#0x%02x", mask);
7879 emitcode ("orl","a,#0x%02x", litval);
7883 if ((blen==1) && (p_type!=GPOINTER))
7885 /* Case with a bitfield length == 1 and no generic pointer
7887 if (AOP_TYPE (right) == AOP_CRY)
7888 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7891 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7892 emitcode ("rrc","a");
7894 emitPtrByteGet (rname, p_type, FALSE);
7895 emitcode ("mov","acc.%d,c",bstr);
7899 /* Case with a bitfield length < 8 and arbitrary source
7901 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7902 /* shift and mask source value */
7904 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7906 /* transfer A to B and get next byte */
7907 emitPtrByteGet (rname, p_type, TRUE);
7909 emitcode ("anl", "a,#0x%02x", mask);
7910 emitcode ("orl", "a,b");
7911 if (p_type == GPOINTER)
7912 emitcode ("pop", "b");
7916 emitPtrByteSet (rname, p_type, "a");
7920 /* Bit length is greater than 7 bits. In this case, copy */
7921 /* all except the partial byte at the end */
7922 for (rlen=blen;rlen>=8;rlen-=8)
7924 emitPtrByteSet (rname, p_type,
7925 aopGet (AOP (right), offset++, FALSE, TRUE) );
7927 emitcode ("inc", "%s", rname);
7930 /* If there was a partial byte at the end */
7933 mask = (((unsigned char) -1 << rlen) & 0xff);
7935 if (AOP_TYPE (right) == AOP_LIT)
7937 /* Case with partial byte and literal source
7939 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7940 litval >>= (blen-rlen);
7941 litval &= (~mask) & 0xff;
7942 emitPtrByteGet (rname, p_type, FALSE);
7943 if ((mask|litval)!=0xff)
7944 emitcode ("anl","a,#0x%02x", mask);
7946 emitcode ("orl","a,#0x%02x", litval);
7950 /* Case with partial byte and arbitrary source
7952 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
7953 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7955 /* transfer A to B and get next byte */
7956 emitPtrByteGet (rname, p_type, TRUE);
7958 emitcode ("anl", "a,#0x%02x", mask);
7959 emitcode ("orl", "a,b");
7960 if (p_type == GPOINTER)
7961 emitcode ("pop", "b");
7963 emitPtrByteSet (rname, p_type, "a");
7969 /*-----------------------------------------------------------------*/
7970 /* genDataPointerSet - remat pointer to data space */
7971 /*-----------------------------------------------------------------*/
7973 genDataPointerSet (operand * right,
7977 int size, offset = 0;
7978 char *l, buffer[256];
7980 D(emitcode ("; genDataPointerSet",""));
7982 aopOp (right, ic, FALSE);
7984 l = aopGet (AOP (result), 0, FALSE, TRUE);
7985 size = AOP_SIZE (right);
7989 sprintf (buffer, "(%s + %d)", l + 1, offset);
7991 sprintf (buffer, "%s", l + 1);
7992 emitcode ("mov", "%s,%s", buffer,
7993 aopGet (AOP (right), offset++, FALSE, FALSE));
7996 freeAsmop (right, NULL, ic, TRUE);
7997 freeAsmop (result, NULL, ic, TRUE);
8000 /*-----------------------------------------------------------------*/
8001 /* genNearPointerSet - emitcode for near pointer put */
8002 /*-----------------------------------------------------------------*/
8004 genNearPointerSet (operand * right,
8012 sym_link *retype, *letype;
8013 sym_link *ptype = operandType (result);
8015 D(emitcode ("; genNearPointerSet",""));
8017 retype = getSpec (operandType (right));
8018 letype = getSpec (ptype);
8019 aopOp (result, ic, FALSE);
8021 /* if the result is rematerializable &
8022 in data space & not a bit variable */
8023 if (AOP_TYPE (result) == AOP_IMMD &&
8024 DCL_TYPE (ptype) == POINTER &&
8025 !IS_BITVAR (retype) &&
8026 !IS_BITVAR (letype))
8028 genDataPointerSet (right, result, ic);
8032 /* if the value is already in a pointer register
8033 then don't need anything more */
8034 if (!AOP_INPREG (AOP (result)))
8037 //AOP_TYPE (result) == AOP_STK
8041 // Aha, it is a pointer, just in disguise.
8042 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8045 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8046 __FILE__, __LINE__);
8051 emitcode ("mov", "a%s,%s", rname + 1, rname);
8052 rname++; // skip the '@'.
8057 /* otherwise get a free pointer register */
8059 preg = getFreePtr (ic, &aop, FALSE);
8060 emitcode ("mov", "%s,%s",
8062 aopGet (AOP (result), 0, FALSE, TRUE));
8068 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8071 aopOp (right, ic, FALSE);
8073 /* if bitfield then unpack the bits */
8074 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8075 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8078 /* we have can just get the values */
8079 int size = AOP_SIZE (right);
8084 l = aopGet (AOP (right), offset, FALSE, TRUE);
8088 emitcode ("mov", "@%s,a", rname);
8091 emitcode ("mov", "@%s,%s", rname, l);
8093 emitcode ("inc", "%s", rname);
8098 /* now some housekeeping stuff */
8099 if (aop) /* we had to allocate for this iCode */
8102 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8103 freeAsmop (NULL, aop, ic, TRUE);
8107 /* we did not allocate which means left
8108 already in a pointer register, then
8109 if size > 0 && this could be used again
8110 we have to point it back to where it
8112 if ((AOP_SIZE (right) > 1 &&
8113 !OP_SYMBOL (result)->remat &&
8114 (OP_SYMBOL (result)->liveTo > ic->seq ||
8118 int size = AOP_SIZE (right) - 1;
8120 emitcode ("dec", "%s", rname);
8125 if (pi) pi->generated = 1;
8126 freeAsmop (result, NULL, ic, TRUE);
8127 freeAsmop (right, NULL, ic, TRUE);
8130 /*-----------------------------------------------------------------*/
8131 /* genPagedPointerSet - emitcode for Paged pointer put */
8132 /*-----------------------------------------------------------------*/
8134 genPagedPointerSet (operand * right,
8142 sym_link *retype, *letype;
8144 D(emitcode ("; genPagedPointerSet",""));
8146 retype = getSpec (operandType (right));
8147 letype = getSpec (operandType (result));
8149 aopOp (result, ic, FALSE);
8151 /* if the value is already in a pointer register
8152 then don't need anything more */
8153 if (!AOP_INPREG (AOP (result)))
8155 /* otherwise get a free pointer register */
8157 preg = getFreePtr (ic, &aop, FALSE);
8158 emitcode ("mov", "%s,%s",
8160 aopGet (AOP (result), 0, FALSE, TRUE));
8164 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8166 aopOp (right, ic, FALSE);
8168 /* if bitfield then unpack the bits */
8169 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8170 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8173 /* we have can just get the values */
8174 int size = AOP_SIZE (right);
8179 l = aopGet (AOP (right), offset, FALSE, TRUE);
8182 emitcode ("movx", "@%s,a", rname);
8185 emitcode ("inc", "%s", rname);
8191 /* now some housekeeping stuff */
8192 if (aop) /* we had to allocate for this iCode */
8195 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8196 freeAsmop (NULL, aop, ic, TRUE);
8200 /* we did not allocate which means left
8201 already in a pointer register, then
8202 if size > 0 && this could be used again
8203 we have to point it back to where it
8205 if (AOP_SIZE (right) > 1 &&
8206 !OP_SYMBOL (result)->remat &&
8207 (OP_SYMBOL (result)->liveTo > ic->seq ||
8210 int size = AOP_SIZE (right) - 1;
8212 emitcode ("dec", "%s", rname);
8217 if (pi) pi->generated = 1;
8218 freeAsmop (result, NULL, ic, TRUE);
8219 freeAsmop (right, NULL, ic, TRUE);
8224 /*-----------------------------------------------------------------*/
8225 /* genFarPointerSet - set value from far space */
8226 /*-----------------------------------------------------------------*/
8228 genFarPointerSet (operand * right,
8229 operand * result, iCode * ic, iCode * pi)
8232 sym_link *retype = getSpec (operandType (right));
8233 sym_link *letype = getSpec (operandType (result));
8235 D(emitcode ("; genFarPointerSet",""));
8237 aopOp (result, ic, FALSE);
8238 loadDptrFromOperand (result, FALSE);
8240 /* so dptr know contains the address */
8241 aopOp (right, ic, FALSE);
8243 /* if bit then unpack */
8244 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8245 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8248 size = AOP_SIZE (right);
8253 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8255 emitcode ("movx", "@dptr,a");
8257 emitcode ("inc", "dptr");
8260 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8261 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8262 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8265 freeAsmop (result, NULL, ic, TRUE);
8266 freeAsmop (right, NULL, ic, TRUE);
8269 /*-----------------------------------------------------------------*/
8270 /* genGenPointerSet - set value from generic pointer space */
8271 /*-----------------------------------------------------------------*/
8273 genGenPointerSet (operand * right,
8274 operand * result, iCode * ic, iCode * pi)
8277 sym_link *retype = getSpec (operandType (right));
8278 sym_link *letype = getSpec (operandType (result));
8280 D(emitcode ("; genGenPointerSet",""));
8282 aopOp (result, ic, FALSE);
8283 loadDptrFromOperand (result, TRUE);
8285 /* so dptr know contains the address */
8286 aopOp (right, ic, FALSE);
8288 /* if bit then unpack */
8289 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8290 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8293 size = AOP_SIZE (right);
8298 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8300 emitcode ("lcall", "__gptrput");
8302 emitcode ("inc", "dptr");
8306 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8307 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8308 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8311 freeAsmop (result, NULL, ic, TRUE);
8312 freeAsmop (right, NULL, ic, TRUE);
8315 /*-----------------------------------------------------------------*/
8316 /* genPointerSet - stores the value into a pointer location */
8317 /*-----------------------------------------------------------------*/
8319 genPointerSet (iCode * ic, iCode *pi)
8321 operand *right, *result;
8322 sym_link *type, *etype;
8325 D(emitcode ("; genPointerSet",""));
8327 right = IC_RIGHT (ic);
8328 result = IC_RESULT (ic);
8330 /* depending on the type of pointer we need to
8331 move it to the correct pointer register */
8332 type = operandType (result);
8333 etype = getSpec (type);
8334 /* if left is of type of pointer then it is simple */
8335 if (IS_PTR (type) && !IS_FUNC (type->next))
8337 p_type = DCL_TYPE (type);
8341 /* we have to go by the storage class */
8342 p_type = PTR_TYPE (SPEC_OCLS (etype));
8345 /* special case when cast remat */
8346 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8347 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8348 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8349 type = operandType (result);
8350 p_type = DCL_TYPE (type);
8352 /* now that we have the pointer type we assign
8353 the pointer values */
8359 genNearPointerSet (right, result, ic, pi);
8363 genPagedPointerSet (right, result, ic, pi);
8367 genFarPointerSet (right, result, ic, pi);
8371 genGenPointerSet (right, result, ic, pi);
8375 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8376 "genPointerSet: illegal pointer type");
8381 /*-----------------------------------------------------------------*/
8382 /* genIfx - generate code for Ifx statement */
8383 /*-----------------------------------------------------------------*/
8385 genIfx (iCode * ic, iCode * popIc)
8387 operand *cond = IC_COND (ic);
8390 D(emitcode ("; genIfx",""));
8392 aopOp (cond, ic, FALSE);
8394 /* get the value into acc */
8395 if (AOP_TYPE (cond) != AOP_CRY)
8399 /* the result is now in the accumulator */
8400 freeAsmop (cond, NULL, ic, TRUE);
8402 /* if there was something to be popped then do it */
8406 /* if the condition is a bit variable */
8407 if (isbit && IS_ITEMP (cond) &&
8409 genIfxJump (ic, SPIL_LOC (cond)->rname);
8410 else if (isbit && !IS_ITEMP (cond))
8411 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8413 genIfxJump (ic, "a");
8418 /*-----------------------------------------------------------------*/
8419 /* genAddrOf - generates code for address of */
8420 /*-----------------------------------------------------------------*/
8422 genAddrOf (iCode * ic)
8424 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8427 D(emitcode ("; genAddrOf",""));
8429 aopOp (IC_RESULT (ic), ic, FALSE);
8431 /* if the operand is on the stack then we
8432 need to get the stack offset of this
8436 /* if it has an offset then we need to compute
8440 emitcode ("mov", "a,_bp");
8441 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8442 ((char) (sym->stack - _G.nRegsSaved)) :
8443 ((char) sym->stack)) & 0xff);
8444 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8448 /* we can just move _bp */
8449 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8451 /* fill the result with zero */
8452 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8457 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8463 /* object not on stack then we need the name */
8464 size = AOP_SIZE (IC_RESULT (ic));
8469 char s[SDCC_NAME_MAX];
8471 sprintf (s, "#(%s >> %d)",
8475 sprintf (s, "#%s", sym->rname);
8476 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8480 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8484 /*-----------------------------------------------------------------*/
8485 /* genFarFarAssign - assignment when both are in far space */
8486 /*-----------------------------------------------------------------*/
8488 genFarFarAssign (operand * result, operand * right, iCode * ic)
8490 int size = AOP_SIZE (right);
8494 D(emitcode ("; genFarFarAssign",""));
8496 /* first push the right side on to the stack */
8499 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8501 emitcode ("push", "acc");
8504 freeAsmop (right, NULL, ic, FALSE);
8505 /* now assign DPTR to result */
8506 aopOp (result, ic, FALSE);
8507 size = AOP_SIZE (result);
8510 emitcode ("pop", "acc");
8511 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8513 freeAsmop (result, NULL, ic, FALSE);
8517 /*-----------------------------------------------------------------*/
8518 /* genAssign - generate code for assignment */
8519 /*-----------------------------------------------------------------*/
8521 genAssign (iCode * ic)
8523 operand *result, *right;
8525 unsigned long lit = 0L;
8527 D(emitcode("; genAssign",""));
8529 result = IC_RESULT (ic);
8530 right = IC_RIGHT (ic);
8532 /* if they are the same */
8533 if (operandsEqu (result, right) &&
8534 !isOperandVolatile (result, FALSE) &&
8535 !isOperandVolatile (right, FALSE))
8538 aopOp (right, ic, FALSE);
8540 /* special case both in far space */
8541 if (AOP_TYPE (right) == AOP_DPTR &&
8542 IS_TRUE_SYMOP (result) &&
8543 isOperandInFarSpace (result))
8546 genFarFarAssign (result, right, ic);
8550 aopOp (result, ic, TRUE);
8552 /* if they are the same registers */
8553 if (sameRegs (AOP (right), AOP (result)) &&
8554 !isOperandVolatile (result, FALSE) &&
8555 !isOperandVolatile (right, FALSE))
8558 /* if the result is a bit */
8559 if (AOP_TYPE (result) == AOP_CRY)
8562 /* if the right size is a literal then
8563 we know what the value is */
8564 if (AOP_TYPE (right) == AOP_LIT)
8566 if (((int) operandLitValue (right)))
8567 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8569 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8573 /* the right is also a bit variable */
8574 if (AOP_TYPE (right) == AOP_CRY)
8576 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8577 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8583 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8587 /* bit variables done */
8589 size = AOP_SIZE (result);
8591 if (AOP_TYPE (right) == AOP_LIT)
8592 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8594 (AOP_TYPE (result) != AOP_REG) &&
8595 (AOP_TYPE (right) == AOP_LIT) &&
8596 !IS_FLOAT (operandType (right)) &&
8599 emitcode ("clr", "a");
8602 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8603 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8605 aopPut (AOP (result),
8606 aopGet (AOP (right), size, FALSE, FALSE),
8608 isOperandVolatile (result, FALSE));
8615 aopPut (AOP (result),
8616 aopGet (AOP (right), offset, FALSE, FALSE),
8618 isOperandVolatile (result, FALSE));
8624 freeAsmop (right, NULL, ic, TRUE);
8625 freeAsmop (result, NULL, ic, TRUE);
8628 /*-----------------------------------------------------------------*/
8629 /* genJumpTab - genrates code for jump table */
8630 /*-----------------------------------------------------------------*/
8632 genJumpTab (iCode * ic)
8637 D(emitcode ("; genJumpTab",""));
8639 aopOp (IC_JTCOND (ic), ic, FALSE);
8640 /* get the condition into accumulator */
8641 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8643 /* multiply by three */
8644 emitcode ("add", "a,acc");
8645 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8646 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8648 jtab = newiTempLabel (NULL);
8649 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8650 emitcode ("jmp", "@a+dptr");
8651 emitcode ("", "%05d$:", jtab->key + 100);
8652 /* now generate the jump labels */
8653 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8654 jtab = setNextItem (IC_JTLABELS (ic)))
8655 emitcode ("ljmp", "%05d$", jtab->key + 100);
8659 /*-----------------------------------------------------------------*/
8660 /* genCast - gen code for casting */
8661 /*-----------------------------------------------------------------*/
8663 genCast (iCode * ic)
8665 operand *result = IC_RESULT (ic);
8666 sym_link *ctype = operandType (IC_LEFT (ic));
8667 sym_link *rtype = operandType (IC_RIGHT (ic));
8668 operand *right = IC_RIGHT (ic);
8671 D(emitcode("; genCast",""));
8673 /* if they are equivalent then do nothing */
8674 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8677 aopOp (right, ic, FALSE);
8678 aopOp (result, ic, FALSE);
8680 /* if the result is a bit (and not a bitfield) */
8681 // if (AOP_TYPE (result) == AOP_CRY)
8682 if (IS_BITVAR (OP_SYMBOL (result)->type)
8683 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8685 /* if the right size is a literal then
8686 we know what the value is */
8687 if (AOP_TYPE (right) == AOP_LIT)
8689 if (((int) operandLitValue (right)))
8690 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8692 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8697 /* the right is also a bit variable */
8698 if (AOP_TYPE (right) == AOP_CRY)
8700 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8701 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8707 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8712 /* if they are the same size : or less */
8713 if (AOP_SIZE (result) <= AOP_SIZE (right))
8716 /* if they are in the same place */
8717 if (sameRegs (AOP (right), AOP (result)))
8720 /* if they in different places then copy */
8721 size = AOP_SIZE (result);
8725 aopPut (AOP (result),
8726 aopGet (AOP (right), offset, FALSE, FALSE),
8728 isOperandVolatile (result, FALSE));
8735 /* if the result is of type pointer */
8740 sym_link *type = operandType (right);
8741 sym_link *etype = getSpec (type);
8743 /* pointer to generic pointer */
8744 if (IS_GENPTR (ctype))
8747 p_type = DCL_TYPE (type);
8750 if (SPEC_SCLS(etype)==S_REGISTER) {
8751 // let's assume it is a generic pointer
8754 /* we have to go by the storage class */
8755 p_type = PTR_TYPE (SPEC_OCLS (etype));
8759 /* the first two bytes are known */
8760 size = GPTRSIZE - 1;
8764 aopPut (AOP (result),
8765 aopGet (AOP (right), offset, FALSE, FALSE),
8767 isOperandVolatile (result, FALSE));
8770 /* the last byte depending on type */
8772 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8777 // pointerTypeToGPByte will have bitched.
8781 sprintf(gpValStr, "#0x%d", gpVal);
8782 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8787 /* just copy the pointers */
8788 size = AOP_SIZE (result);
8792 aopPut (AOP (result),
8793 aopGet (AOP (right), offset, FALSE, FALSE),
8795 isOperandVolatile (result, FALSE));
8801 /* so we now know that the size of destination is greater
8802 than the size of the source */
8803 /* we move to result for the size of source */
8804 size = AOP_SIZE (right);
8808 aopPut (AOP (result),
8809 aopGet (AOP (right), offset, FALSE, FALSE),
8811 isOperandVolatile (result, FALSE));
8815 /* now depending on the sign of the source && destination */
8816 size = AOP_SIZE (result) - AOP_SIZE (right);
8817 /* if unsigned or not an integral type */
8818 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8821 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8825 /* we need to extend the sign :{ */
8826 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8829 emitcode ("rlc", "a");
8830 emitcode ("subb", "a,acc");
8832 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8835 /* we are done hurray !!!! */
8838 freeAsmop (right, NULL, ic, TRUE);
8839 freeAsmop (result, NULL, ic, TRUE);
8843 /*-----------------------------------------------------------------*/
8844 /* genDjnz - generate decrement & jump if not zero instrucion */
8845 /*-----------------------------------------------------------------*/
8847 genDjnz (iCode * ic, iCode * ifx)
8853 D(emitcode ("; genDjnz",""));
8855 /* if the if condition has a false label
8856 then we cannot save */
8860 /* if the minus is not of the form
8862 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8863 !IS_OP_LITERAL (IC_RIGHT (ic)))
8866 if (operandLitValue (IC_RIGHT (ic)) != 1)
8869 /* if the size of this greater than one then no
8871 if (getSize (operandType (IC_RESULT (ic))) > 1)
8874 /* otherwise we can save BIG */
8875 lbl = newiTempLabel (NULL);
8876 lbl1 = newiTempLabel (NULL);
8878 aopOp (IC_RESULT (ic), ic, FALSE);
8880 if (AOP_NEEDSACC(IC_RESULT(ic)))
8882 /* If the result is accessed indirectly via
8883 * the accumulator, we must explicitly write
8884 * it back after the decrement.
8886 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8888 if (strcmp(rByte, "a"))
8890 /* Something is hopelessly wrong */
8891 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8892 __FILE__, __LINE__);
8893 /* We can just give up; the generated code will be inefficient,
8896 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8899 emitcode ("dec", "%s", rByte);
8900 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8901 emitcode ("jnz", "%05d$", lbl->key + 100);
8903 else if (IS_AOP_PREG (IC_RESULT (ic)))
8905 emitcode ("dec", "%s",
8906 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8907 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8908 emitcode ("jnz", "%05d$", lbl->key + 100);
8912 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8915 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8916 emitcode ("", "%05d$:", lbl->key + 100);
8917 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8918 emitcode ("", "%05d$:", lbl1->key + 100);
8920 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8925 /*-----------------------------------------------------------------*/
8926 /* genReceive - generate code for a receive iCode */
8927 /*-----------------------------------------------------------------*/
8929 genReceive (iCode * ic)
8931 int size = getSize (operandType (IC_RESULT (ic)));
8933 D(emitcode ("; genReceive",""));
8935 if (ic->argreg == 1) { /* first parameter */
8936 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8937 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8938 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8940 offset = fReturnSizeMCS51 - size;
8942 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8943 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8946 aopOp (IC_RESULT (ic), ic, FALSE);
8947 size = AOP_SIZE (IC_RESULT (ic));
8950 emitcode ("pop", "acc");
8951 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8956 aopOp (IC_RESULT (ic), ic, FALSE);
8958 assignResultValue (IC_RESULT (ic));
8960 } else { /* second receive onwards */
8962 aopOp (IC_RESULT (ic), ic, FALSE);
8963 rb1off = ic->argreg;
8965 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8968 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8971 /*-----------------------------------------------------------------*/
8972 /* genDummyRead - generate code for dummy read of volatiles */
8973 /*-----------------------------------------------------------------*/
8975 genDummyRead (iCode * ic)
8980 D(emitcode("; genDummyRead",""));
8982 right = IC_RIGHT (ic);
8984 aopOp (right, ic, FALSE);
8986 /* if the result is a bit */
8987 if (AOP_TYPE (right) == AOP_CRY)
8989 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8993 /* bit variables done */
8995 size = AOP_SIZE (right);
8999 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
9004 freeAsmop (right, NULL, ic, TRUE);
9007 /*-----------------------------------------------------------------*/
9008 /* gen51Code - generate code for 8051 based controllers */
9009 /*-----------------------------------------------------------------*/
9011 gen51Code (iCode * lic)
9016 lineHead = lineCurr = NULL;
9018 /* print the allocation information */
9019 if (allocInfo && currFunc)
9020 printAllocInfo (currFunc, codeOutFile);
9021 /* if debug information required */
9022 if (options.debug && currFunc)
9024 debugFile->writeFunction(currFunc);
9026 if (IS_STATIC (currFunc->etype))
9027 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9029 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9032 /* stack pointer name */
9033 if (options.useXstack)
9039 for (ic = lic; ic; ic = ic->next)
9041 _G.current_iCode = ic;
9043 if (ic->lineno && cln != ic->lineno)
9048 emitcode ("", "C$%s$%d$%d$%d ==.",
9049 FileBaseName (ic->filename), ic->lineno,
9050 ic->level, ic->block);
9053 if (!options.noCcodeInAsm) {
9054 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9055 printCLine(ic->filename, ic->lineno));
9059 if (options.iCodeInAsm) {
9063 for (i=0; i<8; i++) {
9064 sprintf (®sInUse[i],
9065 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9068 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9070 /* if the result is marked as
9071 spilt and rematerializable or code for
9072 this has already been generated then
9074 if (resultRemat (ic) || ic->generated)
9077 /* depending on the operation */
9097 /* IPOP happens only when trying to restore a
9098 spilt live range, if there is an ifx statement
9099 following this pop then the if statement might
9100 be using some of the registers being popped which
9101 would destory the contents of the register so
9102 we need to check for this condition and handle it */
9104 ic->next->op == IFX &&
9105 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9106 genIfx (ic->next, ic);
9124 genEndFunction (ic);
9144 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9161 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9165 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9172 /* note these two are xlated by algebraic equivalence
9173 during parsing SDCC.y */
9174 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9175 "got '>=' or '<=' shouldn't have come here");
9179 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9191 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9195 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9199 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9226 case GET_VALUE_AT_ADDRESS:
9227 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9231 if (POINTER_SET (ic))
9232 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9258 addSet (&_G.sendSet, ic);
9261 case DUMMY_READ_VOLATILE:
9270 _G.current_iCode = NULL;
9272 /* now we are ready to call the
9273 peep hole optimizer */
9274 if (!options.nopeep)
9275 peepHole (&lineHead);
9277 /* now do the actual printing */
9278 printLine (lineHead, codeOutFile);