1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
80 static char *rb1regs[] = {
81 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
84 extern int mcs51_ptrRegReq;
85 extern int mcs51_nRegs;
86 extern FILE *codeOutFile;
87 static void saveRBank (int, iCode *, bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
93 #define CLRC emitcode("clr","c")
94 #define SETC emitcode("setb","c")
96 static lineNode *lineHead = NULL;
97 static lineNode *lineCurr = NULL;
99 static unsigned char SLMask[] =
100 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
101 0xE0, 0xC0, 0x80, 0x00};
102 static unsigned char SRMask[] =
103 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
104 0x07, 0x03, 0x01, 0x00};
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple */
113 /*-----------------------------------------------------------------*/
115 emitcode (char *inst, const char *fmt,...)
118 char lb[INITIAL_INLINEASM];
126 sprintf (lb, "%s\t", inst);
128 sprintf (lb, "%s", inst);
129 vsprintf (lb + (strlen (lb)), fmt, ap);
132 vsprintf (lb, fmt, ap);
134 while (isspace (*lbp))
138 lineCurr = (lineCurr ?
139 connectLine (lineCurr, newLineNode (lb)) :
140 (lineHead = newLineNode (lb)));
141 lineCurr->isInline = _G.inLine;
142 lineCurr->isDebug = _G.debugLine;
143 lineCurr->ic = _G.current_iCode;
144 lineCurr->isComment = (*lbp==';');
148 /*-----------------------------------------------------------------*/
149 /* mova - moves specified value into accumulator */
150 /*-----------------------------------------------------------------*/
154 /* do some early peephole optimization */
155 if (!strcmp(x, "a") || !strcmp(x, "acc"))
158 emitcode("mov","a,%s", x);
161 /*-----------------------------------------------------------------*/
162 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
163 /*-----------------------------------------------------------------*/
165 getFreePtr (iCode * ic, asmop ** aopp, bool result)
167 bool r0iu = FALSE, r1iu = FALSE;
168 bool r0ou = FALSE, r1ou = FALSE;
170 /* the logic: if r0 & r1 used in the instruction
171 then we are in trouble otherwise */
173 /* first check if r0 & r1 are used by this
174 instruction, in which case we are in trouble */
175 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
176 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
181 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
182 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
184 /* if no usage of r0 then return it */
187 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
188 (*aopp)->type = AOP_R0;
190 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
193 /* if no usage of r1 then return it */
196 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
197 (*aopp)->type = AOP_R1;
199 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
202 /* now we know they both have usage */
203 /* if r0 not used in this instruction */
206 /* push it if not already pushed */
209 emitcode ("push", "%s",
210 mcs51_regWithIdx (R0_IDX)->dname);
214 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
215 (*aopp)->type = AOP_R0;
217 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
220 /* if r1 not used then */
224 /* push it if not already pushed */
227 emitcode ("push", "%s",
228 mcs51_regWithIdx (R1_IDX)->dname);
232 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
233 (*aopp)->type = AOP_R1;
234 return mcs51_regWithIdx (R1_IDX);
237 /* I said end of world, but not quite end of world yet */
239 /* we can push it on the stack */
240 (*aopp)->type = AOP_STK;
243 /* in the case that result AND left AND right needs a pointer reg
244 we can safely use the result's */
245 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
246 (*aopp)->type = AOP_R0;
247 return mcs51_regWithIdx (R0_IDX);
249 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
250 (*aopp)->type = AOP_R1;
251 return mcs51_regWithIdx (R1_IDX);
255 /* now this is REALLY the end of the world */
256 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
257 "getFreePtr should never reach here");
261 /*-----------------------------------------------------------------*/
262 /* newAsmop - creates a new asmOp */
263 /*-----------------------------------------------------------------*/
265 newAsmop (short type)
269 aop = Safe_calloc (1, sizeof (asmop));
274 /*-----------------------------------------------------------------*/
275 /* pointerCode - returns the code for a pointer type */
276 /*-----------------------------------------------------------------*/
278 pointerCode (sym_link * etype)
281 return PTR_TYPE (SPEC_OCLS (etype));
286 /*-----------------------------------------------------------------*/
287 /* leftRightUseAcc - returns size of accumulator use by operands */
288 /*-----------------------------------------------------------------*/
290 leftRightUseAcc(iCode *ic)
299 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
300 "null iCode pointer");
307 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
310 size = getSize (OP_SYMBOL (op)->type);
315 else if (ic->op == JUMPTABLE)
318 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
321 size = getSize (OP_SYMBOL (op)->type);
329 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
332 size = getSize (OP_SYMBOL (op)->type);
337 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
340 size = getSize (OP_SYMBOL (op)->type);
353 /*-----------------------------------------------------------------*/
354 /* aopForSym - for a true symbol */
355 /*-----------------------------------------------------------------*/
357 aopForSym (iCode * ic, symbol * sym, bool result)
362 wassertl (ic != NULL, "Got a null iCode");
363 wassertl (sym != NULL, "Got a null symbol");
365 space = SPEC_OCLS (sym->etype);
367 /* if already has one */
371 /* assign depending on the storage class */
372 /* if it is on the stack or indirectly addressable */
373 /* space we need to assign either r0 or r1 to it */
374 if (sym->onStack || sym->iaccess)
376 sym->aop = aop = newAsmop (0);
377 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
378 aop->size = getSize (sym->type);
380 /* now assign the address of the variable to
381 the pointer register */
382 if (aop->type != AOP_STK)
387 if (_G.accInUse || leftRightUseAcc (ic))
388 emitcode ("push", "acc");
390 emitcode ("mov", "a,_bp");
391 emitcode ("add", "a,#0x%02x",
393 ((char) (sym->stack - _G.nRegsSaved)) :
394 ((char) sym->stack)) & 0xff);
395 emitcode ("mov", "%s,a",
396 aop->aopu.aop_ptr->name);
398 if (_G.accInUse || leftRightUseAcc (ic))
399 emitcode ("pop", "acc");
402 emitcode ("mov", "%s,#%s",
403 aop->aopu.aop_ptr->name,
405 aop->paged = space->paged;
408 aop->aopu.aop_stk = sym->stack;
412 /* if in bit space */
413 if (IN_BITSPACE (space))
415 sym->aop = aop = newAsmop (AOP_CRY);
416 aop->aopu.aop_dir = sym->rname;
417 aop->size = getSize (sym->type);
420 /* if it is in direct space */
421 if (IN_DIRSPACE (space))
423 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
424 //printTypeChainRaw(sym->type, NULL);
425 //printf("space = %s\n", space ? space->sname : "NULL");
426 sym->aop = aop = newAsmop (AOP_DIR);
427 aop->aopu.aop_dir = sym->rname;
428 aop->size = getSize (sym->type);
432 /* special case for a function */
433 if (IS_FUNC (sym->type))
435 sym->aop = aop = newAsmop (AOP_IMMD);
436 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
437 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
438 aop->size = FPTRSIZE;
442 /* only remaining is far space */
443 /* in which case DPTR gets the address */
444 sym->aop = aop = newAsmop (AOP_DPTR);
445 emitcode ("mov", "dptr,#%s", sym->rname);
446 aop->size = getSize (sym->type);
448 /* if it is in code space */
449 if (IN_CODESPACE (space))
455 /*-----------------------------------------------------------------*/
456 /* aopForRemat - rematerialzes an object */
457 /*-----------------------------------------------------------------*/
459 aopForRemat (symbol * sym)
461 iCode *ic = sym->rematiCode;
462 asmop *aop = newAsmop (AOP_IMMD);
469 val += (int) operandLitValue (IC_RIGHT (ic));
470 else if (ic->op == '-')
471 val -= (int) operandLitValue (IC_RIGHT (ic));
472 else if (IS_CAST_ICODE(ic)) {
473 sym_link *from_type = operandType(IC_RIGHT(ic));
474 aop->aopu.aop_immd.from_cast_remat = 1;
475 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
476 ptr_type = DCL_TYPE(from_type);
477 if (ptr_type == IPOINTER) {
484 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
488 sprintf (buffer, "(%s %c 0x%04x)",
489 OP_SYMBOL (IC_LEFT (ic))->rname,
490 val >= 0 ? '+' : '-',
493 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
495 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
496 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
497 /* set immd2 field if required */
498 if (aop->aopu.aop_immd.from_cast_remat) {
499 sprintf(buffer,"#0x%02x",ptr_type);
500 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
501 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
507 /*-----------------------------------------------------------------*/
508 /* regsInCommon - two operands have some registers in common */
509 /*-----------------------------------------------------------------*/
511 regsInCommon (operand * op1, operand * op2)
516 /* if they have registers in common */
517 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
520 sym1 = OP_SYMBOL (op1);
521 sym2 = OP_SYMBOL (op2);
523 if (sym1->nRegs == 0 || sym2->nRegs == 0)
526 for (i = 0; i < sym1->nRegs; i++)
532 for (j = 0; j < sym2->nRegs; j++)
537 if (sym2->regs[j] == sym1->regs[i])
545 /*-----------------------------------------------------------------*/
546 /* operandsEqu - equivalent */
547 /*-----------------------------------------------------------------*/
549 operandsEqu (operand * op1, operand * op2)
553 /* if they not symbols */
554 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
557 sym1 = OP_SYMBOL (op1);
558 sym2 = OP_SYMBOL (op2);
560 /* if both are itemps & one is spilt
561 and the other is not then false */
562 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
563 sym1->isspilt != sym2->isspilt)
566 /* if they are the same */
570 if (strcmp (sym1->rname, sym2->rname) == 0)
574 /* if left is a tmp & right is not */
575 if (IS_ITEMP (op1) &&
578 (sym1->usl.spillLoc == sym2))
581 if (IS_ITEMP (op2) &&
585 (sym2->usl.spillLoc == sym1))
591 /*-----------------------------------------------------------------*/
592 /* sameRegs - two asmops have the same registers */
593 /*-----------------------------------------------------------------*/
595 sameRegs (asmop * aop1, asmop * aop2)
602 if (aop1->type != AOP_REG ||
603 aop2->type != AOP_REG)
606 if (aop1->size != aop2->size)
609 for (i = 0; i < aop1->size; i++)
610 if (aop1->aopu.aop_reg[i] !=
611 aop2->aopu.aop_reg[i])
617 /*-----------------------------------------------------------------*/
618 /* aopOp - allocates an asmop for an operand : */
619 /*-----------------------------------------------------------------*/
621 aopOp (operand * op, iCode * ic, bool result)
630 /* if this a literal */
631 if (IS_OP_LITERAL (op))
633 op->aop = aop = newAsmop (AOP_LIT);
634 aop->aopu.aop_lit = op->operand.valOperand;
635 aop->size = getSize (operandType (op));
639 /* if already has a asmop then continue */
643 /* if the underlying symbol has a aop */
644 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
646 op->aop = OP_SYMBOL (op)->aop;
650 /* if this is a true symbol */
651 if (IS_TRUE_SYMOP (op))
653 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
657 /* this is a temporary : this has
663 e) can be a return use only */
665 sym = OP_SYMBOL (op);
667 /* if the type is a conditional */
668 if (sym->regType == REG_CND)
670 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
675 /* if it is spilt then two situations
677 b) has a spill location */
678 if (sym->isspilt || sym->nRegs == 0)
681 /* rematerialize it NOW */
684 sym->aop = op->aop = aop =
686 aop->size = getSize (sym->type);
693 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
694 aop->size = getSize (sym->type);
695 for (i = 0; i < 2; i++)
696 aop->aopu.aop_str[i] = accUse[i];
704 aop = op->aop = sym->aop = newAsmop (AOP_STR);
705 aop->size = getSize (sym->type);
706 for (i = 0; i < fReturnSizeMCS51; i++)
707 aop->aopu.aop_str[i] = fReturn[i];
711 if (sym->usl.spillLoc)
713 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
715 /* force a new aop if sizes differ */
716 sym->usl.spillLoc->aop = NULL;
718 sym->aop = op->aop = aop =
719 aopForSym (ic, sym->usl.spillLoc, result);
720 aop->size = getSize (sym->type);
724 /* else must be a dummy iTemp */
725 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
726 aop->size = getSize (sym->type);
730 /* must be in a register */
731 sym->aop = op->aop = aop = newAsmop (AOP_REG);
732 aop->size = sym->nRegs;
733 for (i = 0; i < sym->nRegs; i++)
734 aop->aopu.aop_reg[i] = sym->regs[i];
737 /*-----------------------------------------------------------------*/
738 /* freeAsmop - free up the asmop given to an operand */
739 /*----------------------------------------------------------------*/
741 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
758 /* depending on the asmop type only three cases need work AOP_RO
759 , AOP_R1 && AOP_STK */
767 emitcode ("pop", "ar0");
771 bitVectUnSetBit (ic->rUsed, R0_IDX);
779 emitcode ("pop", "ar1");
783 bitVectUnSetBit (ic->rUsed, R1_IDX);
789 int stk = aop->aopu.aop_stk + aop->size - 1;
790 bitVectUnSetBit (ic->rUsed, R0_IDX);
791 bitVectUnSetBit (ic->rUsed, R1_IDX);
793 getFreePtr (ic, &aop, FALSE);
797 emitcode ("mov", "a,_bp");
798 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
799 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
803 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
808 emitcode ("pop", "acc");
809 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
812 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
815 freeAsmop (op, NULL, ic, TRUE);
818 emitcode ("pop", "ar1");
824 emitcode ("pop", "ar0");
831 /* all other cases just dealloc */
837 OP_SYMBOL (op)->aop = NULL;
838 /* if the symbol has a spill */
840 SPIL_LOC (op)->aop = NULL;
845 /*-----------------------------------------------------------------*/
846 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
847 /* clobber the accumulator */
848 /*-----------------------------------------------------------------*/
850 aopGetUsesAcc (asmop *aop, int offset)
852 if (offset > (aop->size - 1))
870 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
879 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
885 /* Error case --- will have been caught already */
891 /*-----------------------------------------------------------------*/
892 /* aopGet - for fetching value of the aop */
893 /*-----------------------------------------------------------------*/
895 aopGet (asmop * aop, int offset, bool bit16, bool dname)
900 /* offset is greater than
902 if (offset > (aop->size - 1) &&
903 aop->type != AOP_LIT)
906 /* depending on type */
914 /* if we need to increment it */
915 while (offset > aop->coff)
917 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
921 while (offset < aop->coff)
923 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
930 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
931 return (dname ? "acc" : "a");
933 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
934 rs = Safe_calloc (1, strlen (s) + 1);
939 if (aop->code && aop->coff==0 && offset>=1) {
940 emitcode ("mov", "a,#0x%02x", offset);
941 emitcode ("movc", "a,@a+dptr");
942 return (dname ? "acc" : "a");
945 while (offset > aop->coff)
947 emitcode ("inc", "dptr");
951 while (offset < aop->coff)
953 emitcode ("lcall", "__decdptr");
960 emitcode ("clr", "a");
961 emitcode ("movc", "a,@a+dptr");
965 emitcode ("movx", "a,@dptr");
967 return (dname ? "acc" : "a");
971 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
972 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
974 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
976 sprintf (s, "#(%s >> %d)",
977 aop->aopu.aop_immd.aop_immd1,
981 aop->aopu.aop_immd.aop_immd1);
982 rs = Safe_calloc (1, strlen (s) + 1);
988 sprintf (s, "(%s + %d)",
992 sprintf (s, "%s", aop->aopu.aop_dir);
993 rs = Safe_calloc (1, strlen (s) + 1);
999 return aop->aopu.aop_reg[offset]->dname;
1001 return aop->aopu.aop_reg[offset]->name;
1004 emitcode ("clr", "a");
1005 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1006 emitcode ("rlc", "a");
1007 return (dname ? "acc" : "a");
1010 if (!offset && dname)
1012 return aop->aopu.aop_str[offset];
1015 return aopLiteral (aop->aopu.aop_lit, offset);
1019 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1023 return aop->aopu.aop_str[offset];
1027 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1028 "aopget got unsupported aop->type");
1031 /*-----------------------------------------------------------------*/
1032 /* aopPut - puts a string for a aop */
1033 /*-----------------------------------------------------------------*/
1035 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1039 if (aop->size && offset > (aop->size - 1))
1041 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1042 "aopPut got offset > aop->size");
1046 /* will assign value to value */
1047 /* depending on where it is ofcourse */
1051 MOVA (s); /* read s in case it was volatile */
1056 sprintf (d, "(%s + %d)",
1057 aop->aopu.aop_dir, offset);
1059 sprintf (d, "%s", aop->aopu.aop_dir);
1061 if (strcmp (d, s) ||
1063 emitcode ("mov", "%s,%s", d, s);
1068 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1069 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1072 strcmp (s, "r0") == 0 ||
1073 strcmp (s, "r1") == 0 ||
1074 strcmp (s, "r2") == 0 ||
1075 strcmp (s, "r3") == 0 ||
1076 strcmp (s, "r4") == 0 ||
1077 strcmp (s, "r5") == 0 ||
1078 strcmp (s, "r6") == 0 ||
1079 strcmp (s, "r7") == 0)
1080 emitcode ("mov", "%s,%s",
1081 aop->aopu.aop_reg[offset]->dname, s);
1083 emitcode ("mov", "%s,%s",
1084 aop->aopu.aop_reg[offset]->name, s);
1091 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1092 "aopPut writing to code space");
1096 while (offset > aop->coff)
1099 emitcode ("inc", "dptr");
1102 while (offset < aop->coff)
1105 emitcode ("lcall", "__decdptr");
1110 /* if not in accumulater */
1113 emitcode ("movx", "@dptr,a");
1118 while (offset > aop->coff)
1121 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1123 while (offset < aop->coff)
1126 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1133 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1139 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1141 else if (strcmp (s, "r0") == 0 ||
1142 strcmp (s, "r1") == 0 ||
1143 strcmp (s, "r2") == 0 ||
1144 strcmp (s, "r3") == 0 ||
1145 strcmp (s, "r4") == 0 ||
1146 strcmp (s, "r5") == 0 ||
1147 strcmp (s, "r6") == 0 ||
1148 strcmp (s, "r7") == 0)
1151 sprintf (buffer, "a%s", s);
1152 emitcode ("mov", "@%s,%s",
1153 aop->aopu.aop_ptr->name, buffer);
1156 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1161 if (strcmp (s, "a") == 0)
1162 emitcode ("push", "acc");
1166 emitcode ("push", "acc");
1168 emitcode ("push", s);
1174 /* if bit variable */
1175 if (!aop->aopu.aop_dir)
1177 emitcode ("clr", "a");
1178 emitcode ("rlc", "a");
1183 emitcode ("clr", "%s", aop->aopu.aop_dir);
1185 emitcode ("setb", "%s", aop->aopu.aop_dir);
1186 else if (!strcmp (s, "c"))
1187 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1190 if (strcmp (s, "a"))
1195 /* set C, if a >= 1 */
1196 emitcode ("add", "a,#0xff");
1197 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1205 if (strcmp (aop->aopu.aop_str[offset], s) ||
1207 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1212 if (!offset && (strcmp (s, "acc") == 0) &&
1216 if (strcmp (aop->aopu.aop_str[offset], s) &&
1218 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1222 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1223 "aopPut got unsupported aop->type");
1231 /*-----------------------------------------------------------------*/
1232 /* pointToEnd :- points to the last byte of the operand */
1233 /*-----------------------------------------------------------------*/
1235 pointToEnd (asmop * aop)
1241 aop->coff = count = (aop->size - 1);
1247 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1251 emitcode ("inc", "dptr");
1258 /*-----------------------------------------------------------------*/
1259 /* reAdjustPreg - points a register back to where it should */
1260 /*-----------------------------------------------------------------*/
1262 reAdjustPreg (asmop * aop)
1264 if ((aop->coff==0) || aop->size <= 1)
1272 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1277 emitcode ("lcall", "__decdptr");
1284 #define AOP(op) op->aop
1285 #define AOP_TYPE(op) AOP(op)->type
1286 #define AOP_SIZE(op) AOP(op)->size
1287 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1288 AOP_TYPE(x) == AOP_R0))
1290 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1291 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1293 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1294 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1295 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1298 /*-----------------------------------------------------------------*/
1299 /* opIsGptr: returns non-zero if the passed operand is */
1300 /* a generic pointer type. */
1301 /*-----------------------------------------------------------------*/
1303 opIsGptr (operand * op)
1305 sym_link *type = operandType (op);
1307 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1314 /*-----------------------------------------------------------------*/
1315 /* getDataSize - get the operand data size */
1316 /*-----------------------------------------------------------------*/
1318 getDataSize (operand * op)
1321 size = AOP_SIZE (op);
1322 if (size == GPTRSIZE)
1324 sym_link *type = operandType (op);
1325 if (IS_GENPTR (type))
1327 /* generic pointer; arithmetic operations
1328 * should ignore the high byte (pointer type).
1336 /*-----------------------------------------------------------------*/
1337 /* outAcc - output Acc */
1338 /*-----------------------------------------------------------------*/
1340 outAcc (operand * result)
1343 size = getDataSize (result);
1346 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1349 /* unsigned or positive */
1352 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1357 /*-----------------------------------------------------------------*/
1358 /* outBitC - output a bit C */
1359 /*-----------------------------------------------------------------*/
1361 outBitC (operand * result)
1363 /* if the result is bit */
1364 if (AOP_TYPE (result) == AOP_CRY)
1365 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1368 emitcode ("clr", "a");
1369 emitcode ("rlc", "a");
1374 /*-----------------------------------------------------------------*/
1375 /* toBoolean - emit code for orl a,operator(sizeop) */
1376 /*-----------------------------------------------------------------*/
1378 toBoolean (operand * oper)
1380 int size = AOP_SIZE (oper) - 1;
1382 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1384 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1388 /*-----------------------------------------------------------------*/
1389 /* genNot - generate code for ! operation */
1390 /*-----------------------------------------------------------------*/
1396 D(emitcode ("; genNot",""));
1398 /* assign asmOps to operand & result */
1399 aopOp (IC_LEFT (ic), ic, FALSE);
1400 aopOp (IC_RESULT (ic), ic, TRUE);
1402 /* if in bit space then a special case */
1403 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1405 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1406 emitcode ("cpl", "c");
1407 outBitC (IC_RESULT (ic));
1411 toBoolean (IC_LEFT (ic));
1413 tlbl = newiTempLabel (NULL);
1414 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1415 emitcode ("", "%05d$:", tlbl->key + 100);
1416 outBitC (IC_RESULT (ic));
1419 /* release the aops */
1420 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1421 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1425 /*-----------------------------------------------------------------*/
1426 /* genCpl - generate code for complement */
1427 /*-----------------------------------------------------------------*/
1435 D(emitcode ("; genCpl",""));
1437 /* assign asmOps to operand & result */
1438 aopOp (IC_LEFT (ic), ic, FALSE);
1439 aopOp (IC_RESULT (ic), ic, TRUE);
1441 /* special case if in bit space */
1442 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1444 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1446 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1447 emitcode ("cpl", "c");
1448 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1452 tlbl=newiTempLabel(NULL);
1453 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1454 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1455 IS_AOP_PREG (IC_LEFT (ic)))
1457 emitcode ("cjne", "%s,#0x01,%05d$",
1458 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1463 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1465 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1467 emitcode ("", "%05d$:", tlbl->key + 100);
1468 outBitC (IC_RESULT(ic));
1472 size = AOP_SIZE (IC_RESULT (ic));
1475 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1477 emitcode ("cpl", "a");
1478 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1483 /* release the aops */
1484 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1485 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1488 /*-----------------------------------------------------------------*/
1489 /* genUminusFloat - unary minus for floating points */
1490 /*-----------------------------------------------------------------*/
1492 genUminusFloat (operand * op, operand * result)
1494 int size, offset = 0;
1497 D(emitcode ("; genUminusFloat",""));
1499 /* for this we just copy and then flip the bit */
1501 size = AOP_SIZE (op) - 1;
1505 aopPut (AOP (result),
1506 aopGet (AOP (op), offset, FALSE, FALSE),
1508 isOperandVolatile (result, FALSE));
1512 l = aopGet (AOP (op), offset, FALSE, FALSE);
1516 emitcode ("cpl", "acc.7");
1517 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1520 /*-----------------------------------------------------------------*/
1521 /* genUminus - unary minus code generation */
1522 /*-----------------------------------------------------------------*/
1524 genUminus (iCode * ic)
1527 sym_link *optype, *rtype;
1530 D(emitcode ("; genUminus",""));
1533 aopOp (IC_LEFT (ic), ic, FALSE);
1534 aopOp (IC_RESULT (ic), ic, TRUE);
1536 /* if both in bit space then special
1538 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1539 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1542 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1543 emitcode ("cpl", "c");
1544 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1548 optype = operandType (IC_LEFT (ic));
1549 rtype = operandType (IC_RESULT (ic));
1551 /* if float then do float stuff */
1552 if (IS_FLOAT (optype))
1554 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1558 /* otherwise subtract from zero */
1559 size = AOP_SIZE (IC_LEFT (ic));
1564 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1565 if (!strcmp (l, "a"))
1569 emitcode ("cpl", "a");
1570 emitcode ("addc", "a,#0");
1576 emitcode ("clr", "a");
1577 emitcode ("subb", "a,%s", l);
1579 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1582 /* if any remaining bytes in the result */
1583 /* we just need to propagate the sign */
1584 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1586 emitcode ("rlc", "a");
1587 emitcode ("subb", "a,acc");
1589 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1593 /* release the aops */
1594 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1595 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1598 /*-----------------------------------------------------------------*/
1599 /* saveRegisters - will look for a call and save the registers */
1600 /*-----------------------------------------------------------------*/
1602 saveRegisters (iCode * lic)
1609 for (ic = lic; ic; ic = ic->next)
1610 if (ic->op == CALL || ic->op == PCALL)
1615 fprintf (stderr, "found parameter push with no function call\n");
1619 /* if the registers have been saved already or don't need to be then
1623 if (IS_SYMOP(IC_LEFT(ic)) &&
1624 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1625 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1628 /* safe the registers in use at this time but skip the
1629 ones for the result */
1630 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1631 mcs51_rUmaskForOp (IC_RESULT(ic)));
1634 if (options.useXstack)
1636 if (bitVectBitValue (rsave, R0_IDX))
1637 emitcode ("mov", "b,r0");
1638 emitcode ("mov", "r0,%s", spname);
1639 for (i = 0; i < mcs51_nRegs; i++)
1641 if (bitVectBitValue (rsave, i))
1644 emitcode ("mov", "a,b");
1646 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1647 emitcode ("movx", "@r0,a");
1648 emitcode ("inc", "r0");
1651 emitcode ("mov", "%s,r0", spname);
1652 if (bitVectBitValue (rsave, R0_IDX))
1653 emitcode ("mov", "r0,b");
1656 for (i = 0; i < mcs51_nRegs; i++)
1658 if (bitVectBitValue (rsave, i))
1659 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1663 /*-----------------------------------------------------------------*/
1664 /* unsaveRegisters - pop the pushed registers */
1665 /*-----------------------------------------------------------------*/
1667 unsaveRegisters (iCode * ic)
1672 /* restore the registers in use at this time but skip the
1673 ones for the result */
1674 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1675 mcs51_rUmaskForOp (IC_RESULT(ic)));
1677 if (options.useXstack)
1679 emitcode ("mov", "r0,%s", spname);
1680 for (i = mcs51_nRegs; i >= 0; i--)
1682 if (bitVectBitValue (rsave, i))
1684 emitcode ("dec", "r0");
1685 emitcode ("movx", "a,@r0");
1687 emitcode ("mov", "b,a");
1689 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1693 emitcode ("mov", "%s,r0", spname);
1694 if (bitVectBitValue (rsave, R0_IDX))
1695 emitcode ("mov", "r0,b");
1698 for (i = mcs51_nRegs; i >= 0; i--)
1700 if (bitVectBitValue (rsave, i))
1701 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1707 /*-----------------------------------------------------------------*/
1709 /*-----------------------------------------------------------------*/
1711 pushSide (operand * oper, int size)
1716 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1717 if (AOP_TYPE (oper) != AOP_REG &&
1718 AOP_TYPE (oper) != AOP_DIR &&
1721 emitcode ("mov", "a,%s", l);
1722 emitcode ("push", "acc");
1725 emitcode ("push", "%s", l);
1729 /*-----------------------------------------------------------------*/
1730 /* assignResultValue - */
1731 /*-----------------------------------------------------------------*/
1733 assignResultValue (operand * oper)
1736 int size = AOP_SIZE (oper);
1739 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1745 /*-----------------------------------------------------------------*/
1746 /* genXpush - pushes onto the external stack */
1747 /*-----------------------------------------------------------------*/
1749 genXpush (iCode * ic)
1751 asmop *aop = newAsmop (0);
1753 int size, offset = 0;
1755 D(emitcode ("; genXpush",""));
1757 aopOp (IC_LEFT (ic), ic, FALSE);
1758 r = getFreePtr (ic, &aop, FALSE);
1761 emitcode ("mov", "%s,_spx", r->name);
1763 size = AOP_SIZE (IC_LEFT (ic));
1767 char *l = aopGet (AOP (IC_LEFT (ic)),
1768 offset++, FALSE, FALSE);
1770 emitcode ("movx", "@%s,a", r->name);
1771 emitcode ("inc", "%s", r->name);
1776 emitcode ("mov", "_spx,%s", r->name);
1778 freeAsmop (NULL, aop, ic, TRUE);
1779 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1782 /*-----------------------------------------------------------------*/
1783 /* genIpush - genrate code for pushing this gets a little complex */
1784 /*-----------------------------------------------------------------*/
1786 genIpush (iCode * ic)
1788 int size, offset = 0;
1791 D(emitcode ("; genIpush",""));
1793 /* if this is not a parm push : ie. it is spill push
1794 and spill push is always done on the local stack */
1798 /* and the item is spilt then do nothing */
1799 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1802 aopOp (IC_LEFT (ic), ic, FALSE);
1803 size = AOP_SIZE (IC_LEFT (ic));
1804 /* push it on the stack */
1807 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1813 emitcode ("push", "%s", l);
1818 /* this is a paramter push: in this case we call
1819 the routine to find the call and save those
1820 registers that need to be saved */
1823 /* if use external stack then call the external
1824 stack pushing routine */
1825 if (options.useXstack)
1831 /* then do the push */
1832 aopOp (IC_LEFT (ic), ic, FALSE);
1835 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1836 size = AOP_SIZE (IC_LEFT (ic));
1840 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1841 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1842 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1845 emitcode ("mov", "a,%s", l);
1846 emitcode ("push", "acc");
1849 emitcode ("push", "%s", l);
1852 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1855 /*-----------------------------------------------------------------*/
1856 /* genIpop - recover the registers: can happen only for spilling */
1857 /*-----------------------------------------------------------------*/
1859 genIpop (iCode * ic)
1863 D(emitcode ("; genIpop",""));
1865 /* if the temp was not pushed then */
1866 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1869 aopOp (IC_LEFT (ic), ic, FALSE);
1870 size = AOP_SIZE (IC_LEFT (ic));
1871 offset = (size - 1);
1873 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1876 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1879 /*-----------------------------------------------------------------*/
1880 /* unsaveRBank - restores the resgister bank from stack */
1881 /*-----------------------------------------------------------------*/
1883 unsaveRBank (int bank, iCode * ic, bool popPsw)
1889 if (options.useXstack)
1893 /* Assume r0 is available for use. */
1894 r = mcs51_regWithIdx (R0_IDX);;
1899 r = getFreePtr (ic, &aop, FALSE);
1901 emitcode ("mov", "%s,_spx", r->name);
1906 if (options.useXstack)
1908 emitcode ("movx", "a,@%s", r->name);
1909 emitcode ("mov", "psw,a");
1910 emitcode ("dec", "%s", r->name);
1914 emitcode ("pop", "psw");
1918 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1920 if (options.useXstack)
1922 emitcode ("movx", "a,@%s", r->name);
1923 emitcode ("mov", "(%s+%d),a",
1924 regs8051[i].base, 8 * bank + regs8051[i].offset);
1925 emitcode ("dec", "%s", r->name);
1929 emitcode ("pop", "(%s+%d)",
1930 regs8051[i].base, 8 * bank + regs8051[i].offset);
1933 if (options.useXstack)
1935 emitcode ("mov", "_spx,%s", r->name);
1940 freeAsmop (NULL, aop, ic, TRUE);
1944 /*-----------------------------------------------------------------*/
1945 /* saveRBank - saves an entire register bank on the stack */
1946 /*-----------------------------------------------------------------*/
1948 saveRBank (int bank, iCode * ic, bool pushPsw)
1954 if (options.useXstack)
1958 /* Assume r0 is available for use. */
1959 r = mcs51_regWithIdx (R0_IDX);;
1964 r = getFreePtr (ic, &aop, FALSE);
1966 emitcode ("mov", "%s,_spx", r->name);
1969 for (i = 0; i < mcs51_nRegs; i++)
1971 if (options.useXstack)
1973 emitcode ("inc", "%s", r->name);
1974 emitcode ("mov", "a,(%s+%d)",
1975 regs8051[i].base, 8 * bank + regs8051[i].offset);
1976 emitcode ("movx", "@%s,a", r->name);
1979 emitcode ("push", "(%s+%d)",
1980 regs8051[i].base, 8 * bank + regs8051[i].offset);
1985 if (options.useXstack)
1987 emitcode ("mov", "a,psw");
1988 emitcode ("movx", "@%s,a", r->name);
1989 emitcode ("inc", "%s", r->name);
1990 emitcode ("mov", "_spx,%s", r->name);
1995 emitcode ("push", "psw");
1998 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2003 freeAsmop (NULL, aop, ic, TRUE);
2012 /*-----------------------------------------------------------------*/
2013 /* genSend - gen code for SEND */
2014 /*-----------------------------------------------------------------*/
2015 static void genSend(set *sendSet)
2020 for (sic = setFirstItem (_G.sendSet); sic;
2021 sic = setNextItem (_G.sendSet)) {
2022 int size, offset = 0;
2023 aopOp (IC_LEFT (sic), sic, FALSE);
2024 size = AOP_SIZE (IC_LEFT (sic));
2026 if (sic->argreg == 1) {
2028 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2030 if (strcmp (l, fReturn[offset]))
2031 emitcode ("mov", "%s,%s", fReturn[offset], l);
2037 emitcode ("mov","b1_%d,%s",rb1_count++,
2038 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2041 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2045 /*-----------------------------------------------------------------*/
2046 /* genCall - generates a call statement */
2047 /*-----------------------------------------------------------------*/
2049 genCall (iCode * ic)
2052 // bool restoreBank = FALSE;
2053 bool swapBanks = FALSE;
2055 D(emitcode("; genCall",""));
2057 dtype = operandType (IC_LEFT (ic));
2058 /* if send set is not empty the assign */
2061 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2062 genSend(reverseSet(_G.sendSet));
2064 genSend(_G.sendSet);
2070 /* if we are calling a not _naked function that is not using
2071 the same register bank then we need to save the
2072 destination registers on the stack */
2073 dtype = operandType (IC_LEFT (ic));
2074 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2075 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2076 !IFFUNC_ISISR (dtype))
2081 /* if caller saves & we have not saved then */
2087 emitcode ("mov", "psw,#0x%02x",
2088 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2092 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2093 OP_SYMBOL (IC_LEFT (ic))->rname :
2094 OP_SYMBOL (IC_LEFT (ic))->name));
2098 emitcode ("mov", "psw,#0x%02x",
2099 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2102 /* if we need assign a result value */
2103 if ((IS_ITEMP (IC_RESULT (ic)) &&
2104 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2105 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2106 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2107 IS_TRUE_SYMOP (IC_RESULT (ic)))
2111 aopOp (IC_RESULT (ic), ic, FALSE);
2114 assignResultValue (IC_RESULT (ic));
2116 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2119 /* adjust the stack for parameters if
2124 if (ic->parmBytes > 3)
2126 emitcode ("mov", "a,%s", spname);
2127 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2128 emitcode ("mov", "%s,a", spname);
2131 for (i = 0; i < ic->parmBytes; i++)
2132 emitcode ("dec", "%s", spname);
2135 /* if we hade saved some registers then unsave them */
2136 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2137 unsaveRegisters (ic);
2139 // /* if register bank was saved then pop them */
2141 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2144 /*-----------------------------------------------------------------*/
2145 /* -10l - generates a call by pointer statement */
2146 /*-----------------------------------------------------------------*/
2148 genPcall (iCode * ic)
2151 symbol *rlbl = newiTempLabel (NULL);
2152 // bool restoreBank=FALSE;
2153 bool swapBanks = FALSE;
2155 D(emitcode("; genPCall",""));
2157 /* if caller saves & we have not saved then */
2161 /* if we are calling a not _naked function that is not using
2162 the same register bank then we need to save the
2163 destination registers on the stack */
2164 dtype = operandType (IC_LEFT (ic))->next;
2165 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2166 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2167 !IFFUNC_ISISR (dtype))
2169 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2170 // restoreBank=TRUE;
2172 // need caution message to user here
2175 /* push the return address on to the stack */
2176 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2177 emitcode ("push", "acc");
2178 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2179 emitcode ("push", "acc");
2181 /* now push the calling address */
2182 aopOp (IC_LEFT (ic), ic, FALSE);
2184 pushSide (IC_LEFT (ic), FPTRSIZE);
2186 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2188 /* if send set is not empty the assign */
2191 genSend(reverseSet(_G.sendSet));
2197 emitcode ("mov", "psw,#0x%02x",
2198 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2202 emitcode ("ret", "");
2203 emitcode ("", "%05d$:", (rlbl->key + 100));
2208 emitcode ("mov", "psw,#0x%02x",
2209 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2212 /* if we need assign a result value */
2213 if ((IS_ITEMP (IC_RESULT (ic)) &&
2214 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2215 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2216 IS_TRUE_SYMOP (IC_RESULT (ic)))
2220 aopOp (IC_RESULT (ic), ic, FALSE);
2223 assignResultValue (IC_RESULT (ic));
2225 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2228 /* adjust the stack for parameters if
2233 if (ic->parmBytes > 3)
2235 emitcode ("mov", "a,%s", spname);
2236 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2237 emitcode ("mov", "%s,a", spname);
2240 for (i = 0; i < ic->parmBytes; i++)
2241 emitcode ("dec", "%s", spname);
2245 // /* if register bank was saved then unsave them */
2247 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2249 /* if we hade saved some registers then
2251 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2252 unsaveRegisters (ic);
2255 /*-----------------------------------------------------------------*/
2256 /* resultRemat - result is rematerializable */
2257 /*-----------------------------------------------------------------*/
2259 resultRemat (iCode * ic)
2261 if (SKIP_IC (ic) || ic->op == IFX)
2264 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2266 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2267 if (sym->remat && !POINTER_SET (ic))
2274 #if defined(__BORLANDC__) || defined(_MSC_VER)
2275 #define STRCASECMP stricmp
2277 #define STRCASECMP strcasecmp
2280 /*-----------------------------------------------------------------*/
2281 /* inExcludeList - return 1 if the string is in exclude Reg list */
2282 /*-----------------------------------------------------------------*/
2284 regsCmp(void *p1, void *p2)
2286 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2290 inExcludeList (char *s)
2292 const char *p = setFirstItem(options.excludeRegsSet);
2294 if (p == NULL || STRCASECMP(p, "none") == 0)
2298 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2301 /*-----------------------------------------------------------------*/
2302 /* genFunction - generated code for function entry */
2303 /*-----------------------------------------------------------------*/
2305 genFunction (iCode * ic)
2309 bool switchedPSW = FALSE;
2310 int calleesaves_saved_register = -1;
2313 /* create the function header */
2314 emitcode (";", "-----------------------------------------");
2315 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2316 emitcode (";", "-----------------------------------------");
2318 emitcode ("", "%s:", sym->rname);
2319 ftype = operandType (IC_LEFT (ic));
2321 if (IFFUNC_ISNAKED(ftype))
2323 emitcode(";", "naked function: no prologue.");
2327 /* here we need to generate the equates for the
2328 register bank if required */
2329 if (FUNC_REGBANK (ftype) != rbank)
2333 rbank = FUNC_REGBANK (ftype);
2334 for (i = 0; i < mcs51_nRegs; i++)
2336 if (strcmp (regs8051[i].base, "0") == 0)
2337 emitcode ("", "%s = 0x%02x",
2339 8 * rbank + regs8051[i].offset);
2341 emitcode ("", "%s = %s + 0x%02x",
2344 8 * rbank + regs8051[i].offset);
2348 /* if this is an interrupt service routine then
2349 save acc, b, dpl, dph */
2350 if (IFFUNC_ISISR (sym->type))
2353 if (!inExcludeList ("acc"))
2354 emitcode ("push", "acc");
2355 if (!inExcludeList ("b"))
2356 emitcode ("push", "b");
2357 if (!inExcludeList ("dpl"))
2358 emitcode ("push", "dpl");
2359 if (!inExcludeList ("dph"))
2360 emitcode ("push", "dph");
2361 /* if this isr has no bank i.e. is going to
2362 run with bank 0 , then we need to save more
2364 if (!FUNC_REGBANK (sym->type))
2367 /* if this function does not call any other
2368 function then we can be economical and
2369 save only those registers that are used */
2370 if (!IFFUNC_HASFCALL(sym->type))
2374 /* if any registers used */
2377 /* save the registers used */
2378 for (i = 0; i < sym->regsUsed->size; i++)
2380 if (bitVectBitValue (sym->regsUsed, i) ||
2381 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2382 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2390 /* this function has a function call cannot
2391 determines register usage so we will have to push the
2393 saveRBank (0, ic, FALSE);
2394 if (options.parms_in_bank1) {
2396 for (i=0; i < 8 ; i++ ) {
2397 emitcode ("push","%s",rb1regs[i]);
2404 /* This ISR uses a non-zero bank.
2406 * We assume that the bank is available for our
2409 * However, if this ISR calls a function which uses some
2410 * other bank, we must save that bank entirely.
2412 unsigned long banksToSave = 0;
2414 if (IFFUNC_HASFCALL(sym->type))
2417 #define MAX_REGISTER_BANKS 4
2422 for (i = ic; i; i = i->next)
2424 if (i->op == ENDFUNCTION)
2426 /* we got to the end OK. */
2434 dtype = operandType (IC_LEFT(i));
2436 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2438 /* Mark this bank for saving. */
2439 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2441 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2445 banksToSave |= (1 << FUNC_REGBANK(dtype));
2448 /* And note that we don't need to do it in
2456 /* This is a mess; we have no idea what
2457 * register bank the called function might
2460 * The only thing I can think of to do is
2461 * throw a warning and hope.
2463 werror(W_FUNCPTR_IN_USING_ISR);
2467 if (banksToSave && options.useXstack)
2469 /* Since we aren't passing it an ic,
2470 * saveRBank will assume r0 is available to abuse.
2472 * So switch to our (trashable) bank now, so
2473 * the caller's R0 isn't trashed.
2475 emitcode ("push", "psw");
2476 emitcode ("mov", "psw,#0x%02x",
2477 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2481 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2483 if (banksToSave & (1 << ix))
2485 saveRBank(ix, NULL, FALSE);
2489 // TODO: this needs a closer look
2490 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2495 /* if callee-save to be used for this function
2496 then save the registers being used in this function */
2497 if (IFFUNC_CALLEESAVES(sym->type))
2501 /* if any registers used */
2504 /* save the registers used */
2505 for (i = 0; i < sym->regsUsed->size; i++)
2507 if (bitVectBitValue (sym->regsUsed, i) ||
2508 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2510 /* remember one saved register for later usage */
2511 if (calleesaves_saved_register < 0)
2512 calleesaves_saved_register = i;
2513 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2521 /* set the register bank to the desired value */
2522 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2525 emitcode ("push", "psw");
2526 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2529 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2532 if (options.useXstack)
2534 emitcode ("mov", "r0,%s", spname);
2535 emitcode ("mov", "a,_bp");
2536 emitcode ("movx", "@r0,a");
2537 emitcode ("inc", "%s", spname);
2541 /* set up the stack */
2542 emitcode ("push", "_bp"); /* save the callers stack */
2544 emitcode ("mov", "_bp,%s", spname);
2547 /* adjust the stack for the function */
2553 werror (W_STACK_OVERFLOW, sym->name);
2555 if (i > 3 && sym->recvSize < 4)
2558 emitcode ("mov", "a,sp");
2559 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2560 emitcode ("mov", "sp,a");
2565 if (IFFUNC_CALLEESAVES(sym->type))
2567 /* if it's a callee-saves function we need a saved register */
2568 if (calleesaves_saved_register >= 0)
2570 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2571 emitcode ("mov", "a,sp");
2572 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2573 emitcode ("mov", "sp,a");
2574 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2577 /* do it the hard way */
2579 emitcode ("inc", "sp");
2583 /* not callee-saves, we can clobber r0 */
2584 emitcode ("mov", "r0,a");
2585 emitcode ("mov", "a,sp");
2586 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2587 emitcode ("mov", "sp,a");
2588 emitcode ("mov", "a,r0");
2593 emitcode ("inc", "sp");
2599 emitcode ("mov", "a,_spx");
2600 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2601 emitcode ("mov", "_spx,a");
2604 /* if critical function then turn interrupts off */
2605 if (IFFUNC_ISCRITICAL (ftype))
2607 symbol *tlbl = newiTempLabel (NULL);
2608 emitcode ("setb", "c");
2609 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2610 emitcode ("clr", "c");
2611 emitcode ("", "%05d$:", (tlbl->key + 100));
2612 emitcode ("push", "psw"); /* save old ea via c in psw */
2616 /*-----------------------------------------------------------------*/
2617 /* genEndFunction - generates epilogue for functions */
2618 /*-----------------------------------------------------------------*/
2620 genEndFunction (iCode * ic)
2622 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2624 if (IFFUNC_ISNAKED(sym->type))
2626 emitcode(";", "naked function: no epilogue.");
2630 if (IFFUNC_ISCRITICAL (sym->type))
2632 emitcode ("pop", "psw"); /* restore ea via c in psw */
2633 emitcode ("mov", "ea,c");
2636 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2638 emitcode ("mov", "%s,_bp", spname);
2641 /* if use external stack but some variables were
2642 added to the local stack then decrement the
2644 if (options.useXstack && sym->stack)
2646 emitcode ("mov", "a,sp");
2647 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2648 emitcode ("mov", "sp,a");
2652 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2654 if (options.useXstack)
2656 emitcode ("mov", "r0,%s", spname);
2657 emitcode ("movx", "a,@r0");
2658 emitcode ("mov", "_bp,a");
2659 emitcode ("dec", "%s", spname);
2663 emitcode ("pop", "_bp");
2667 /* restore the register bank */
2668 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2670 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2671 || !options.useXstack)
2673 /* Special case of ISR using non-zero bank with useXstack
2676 emitcode ("pop", "psw");
2680 if (IFFUNC_ISISR (sym->type))
2683 /* now we need to restore the registers */
2684 /* if this isr has no bank i.e. is going to
2685 run with bank 0 , then we need to save more
2687 if (!FUNC_REGBANK (sym->type))
2689 /* if this function does not call any other
2690 function then we can be economical and
2691 save only those registers that are used */
2692 if (!IFFUNC_HASFCALL(sym->type))
2696 /* if any registers used */
2699 /* save the registers used */
2700 for (i = sym->regsUsed->size; i >= 0; i--)
2702 if (bitVectBitValue (sym->regsUsed, i) ||
2703 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2704 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2711 if (options.parms_in_bank1) {
2713 for (i = 7 ; i >= 0 ; i-- ) {
2714 emitcode ("pop","%s",rb1regs[i]);
2717 /* this function has a function call cannot
2718 determines register usage so we will have to pop the
2720 unsaveRBank (0, ic, FALSE);
2725 /* This ISR uses a non-zero bank.
2727 * Restore any register banks saved by genFunction
2730 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2733 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2735 if (savedBanks & (1 << ix))
2737 unsaveRBank(ix, NULL, FALSE);
2741 if (options.useXstack)
2743 /* Restore bank AFTER calling unsaveRBank,
2744 * since it can trash r0.
2746 emitcode ("pop", "psw");
2750 if (!inExcludeList ("dph"))
2751 emitcode ("pop", "dph");
2752 if (!inExcludeList ("dpl"))
2753 emitcode ("pop", "dpl");
2754 if (!inExcludeList ("b"))
2755 emitcode ("pop", "b");
2756 if (!inExcludeList ("acc"))
2757 emitcode ("pop", "acc");
2759 /* if debug then send end of function */
2760 if (options.debug && currFunc)
2763 emitcode ("", "C$%s$%d$%d$%d ==.",
2764 FileBaseName (ic->filename), currFunc->lastLine,
2765 ic->level, ic->block);
2766 if (IS_STATIC (currFunc->etype))
2767 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2769 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2773 emitcode ("reti", "");
2777 if (IFFUNC_CALLEESAVES(sym->type))
2781 /* if any registers used */
2784 /* save the registers used */
2785 for (i = sym->regsUsed->size; i >= 0; i--)
2787 if (bitVectBitValue (sym->regsUsed, i) ||
2788 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2789 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2795 /* if debug then send end of function */
2796 if (options.debug && currFunc)
2799 emitcode ("", "C$%s$%d$%d$%d ==.",
2800 FileBaseName (ic->filename), currFunc->lastLine,
2801 ic->level, ic->block);
2802 if (IS_STATIC (currFunc->etype))
2803 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2805 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2809 emitcode ("ret", "");
2814 /*-----------------------------------------------------------------*/
2815 /* genRet - generate code for return statement */
2816 /*-----------------------------------------------------------------*/
2820 int size, offset = 0, pushed = 0;
2822 D(emitcode ("; genRet",""));
2824 /* if we have no return value then
2825 just generate the "ret" */
2829 /* we have something to return then
2830 move the return value into place */
2831 aopOp (IC_LEFT (ic), ic, FALSE);
2832 size = AOP_SIZE (IC_LEFT (ic));
2837 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2840 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2842 emitcode ("push", "%s", l);
2847 l = aopGet (AOP (IC_LEFT (ic)), offset,
2849 if (strcmp (fReturn[offset], l))
2850 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2859 if (strcmp (fReturn[pushed], "a"))
2860 emitcode ("pop", fReturn[pushed]);
2862 emitcode ("pop", "acc");
2865 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2868 /* generate a jump to the return label
2869 if the next is not the return statement */
2870 if (!(ic->next && ic->next->op == LABEL &&
2871 IC_LABEL (ic->next) == returnLabel))
2873 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2877 /*-----------------------------------------------------------------*/
2878 /* genLabel - generates a label */
2879 /*-----------------------------------------------------------------*/
2881 genLabel (iCode * ic)
2883 /* special case never generate */
2884 if (IC_LABEL (ic) == entryLabel)
2887 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2890 /*-----------------------------------------------------------------*/
2891 /* genGoto - generates a ljmp */
2892 /*-----------------------------------------------------------------*/
2894 genGoto (iCode * ic)
2896 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2899 /*-----------------------------------------------------------------*/
2900 /* findLabelBackwards: walks back through the iCode chain looking */
2901 /* for the given label. Returns number of iCode instructions */
2902 /* between that label and given ic. */
2903 /* Returns zero if label not found. */
2904 /*-----------------------------------------------------------------*/
2906 findLabelBackwards (iCode * ic, int key)
2915 /* If we have any pushes or pops, we cannot predict the distance.
2916 I don't like this at all, this should be dealt with in the
2918 if (ic->op == IPUSH || ic->op == IPOP) {
2922 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2931 /*-----------------------------------------------------------------*/
2932 /* genPlusIncr :- does addition with increment if possible */
2933 /*-----------------------------------------------------------------*/
2935 genPlusIncr (iCode * ic)
2937 unsigned int icount;
2938 unsigned int size = getDataSize (IC_RESULT (ic));
2940 /* will try to generate an increment */
2941 /* if the right side is not a literal
2943 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2946 /* if the literal value of the right hand side
2947 is greater than 4 then it is not worth it */
2948 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2951 D(emitcode ("; genPlusIncr",""));
2953 /* if increment >=16 bits in register or direct space */
2954 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2955 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2963 /* If the next instruction is a goto and the goto target
2964 * is < 10 instructions previous to this, we can generate
2965 * jumps straight to that target.
2967 if (ic->next && ic->next->op == GOTO
2968 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2969 && labelRange <= 10)
2971 emitcode (";", "tail increment optimized");
2972 tlbl = IC_LABEL (ic->next);
2977 tlbl = newiTempLabel (NULL);
2980 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2981 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2982 IS_AOP_PREG (IC_RESULT (ic)))
2983 emitcode ("cjne", "%s,#0x00,%05d$",
2984 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2988 emitcode ("clr", "a");
2989 emitcode ("cjne", "a,%s,%05d$",
2990 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2994 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2997 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2998 IS_AOP_PREG (IC_RESULT (ic)))
2999 emitcode ("cjne", "%s,#0x00,%05d$",
3000 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3003 emitcode ("cjne", "a,%s,%05d$",
3004 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3007 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3011 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3012 IS_AOP_PREG (IC_RESULT (ic)))
3013 emitcode ("cjne", "%s,#0x00,%05d$",
3014 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3018 emitcode ("cjne", "a,%s,%05d$",
3019 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3022 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3027 emitcode ("", "%05d$:", tlbl->key + 100);
3032 /* if the sizes are greater than 1 then we cannot */
3033 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3034 AOP_SIZE (IC_LEFT (ic)) > 1)
3037 /* we can if the aops of the left & result match or
3038 if they are in registers and the registers are the
3040 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3045 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3046 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3047 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3053 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3062 /*-----------------------------------------------------------------*/
3063 /* outBitAcc - output a bit in acc */
3064 /*-----------------------------------------------------------------*/
3066 outBitAcc (operand * result)
3068 symbol *tlbl = newiTempLabel (NULL);
3069 /* if the result is a bit */
3070 if (AOP_TYPE (result) == AOP_CRY)
3072 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3076 emitcode ("jz", "%05d$", tlbl->key + 100);
3077 emitcode ("mov", "a,%s", one);
3078 emitcode ("", "%05d$:", tlbl->key + 100);
3083 /*-----------------------------------------------------------------*/
3084 /* genPlusBits - generates code for addition of two bits */
3085 /*-----------------------------------------------------------------*/
3087 genPlusBits (iCode * ic)
3089 D(emitcode ("; genPlusBits",""));
3091 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3093 symbol *lbl = newiTempLabel (NULL);
3094 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3095 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3096 emitcode ("cpl", "c");
3097 emitcode ("", "%05d$:", (lbl->key + 100));
3098 outBitC (IC_RESULT (ic));
3102 emitcode ("clr", "a");
3103 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3104 emitcode ("rlc", "a");
3105 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3106 emitcode ("addc", "a,#0x00");
3107 outAcc (IC_RESULT (ic));
3112 /* This is the original version of this code.
3114 * This is being kept around for reference,
3115 * because I am not entirely sure I got it right...
3118 adjustArithmeticResult (iCode * ic)
3120 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3121 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3122 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3123 aopPut (AOP (IC_RESULT (ic)),
3124 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3126 isOperandVolatile (IC_RESULT (ic), FALSE));
3128 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3129 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3130 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3131 aopPut (AOP (IC_RESULT (ic)),
3132 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3134 isOperandVolatile (IC_RESULT (ic), FALSE));
3136 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3137 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3138 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3139 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3140 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3143 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3144 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3148 /* This is the pure and virtuous version of this code.
3149 * I'm pretty certain it's right, but not enough to toss the old
3153 adjustArithmeticResult (iCode * ic)
3155 if (opIsGptr (IC_RESULT (ic)) &&
3156 opIsGptr (IC_LEFT (ic)) &&
3157 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3159 aopPut (AOP (IC_RESULT (ic)),
3160 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3162 isOperandVolatile (IC_RESULT (ic), FALSE));
3165 if (opIsGptr (IC_RESULT (ic)) &&
3166 opIsGptr (IC_RIGHT (ic)) &&
3167 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3169 aopPut (AOP (IC_RESULT (ic)),
3170 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3172 isOperandVolatile (IC_RESULT (ic), FALSE));
3175 if (opIsGptr (IC_RESULT (ic)) &&
3176 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3177 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3178 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3179 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3182 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3183 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3188 /*-----------------------------------------------------------------*/
3189 /* genPlus - generates code for addition */
3190 /*-----------------------------------------------------------------*/
3192 genPlus (iCode * ic)
3194 int size, offset = 0;
3196 asmop *leftOp, *rightOp;
3198 /* special cases :- */
3200 D(emitcode ("; genPlus",""));
3202 aopOp (IC_LEFT (ic), ic, FALSE);
3203 aopOp (IC_RIGHT (ic), ic, FALSE);
3204 aopOp (IC_RESULT (ic), ic, TRUE);
3206 /* if literal, literal on the right or
3207 if left requires ACC or right is already
3209 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3210 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3211 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3213 operand *t = IC_RIGHT (ic);
3214 IC_RIGHT (ic) = IC_LEFT (ic);
3218 /* if both left & right are in bit
3220 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3221 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3227 /* if left in bit space & right literal */
3228 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3229 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3231 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3232 /* if result in bit space */
3233 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3235 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3236 emitcode ("cpl", "c");
3237 outBitC (IC_RESULT (ic));
3241 size = getDataSize (IC_RESULT (ic));
3244 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3245 emitcode ("addc", "a,#00");
3246 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3252 /* if I can do an increment instead
3253 of add then GOOD for ME */
3254 if (genPlusIncr (ic) == TRUE)
3257 size = getDataSize (IC_RESULT (ic));
3259 leftOp = AOP(IC_LEFT(ic));
3260 rightOp = AOP(IC_RIGHT(ic));
3265 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3267 emitcode("mov", "b,a");
3268 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3269 emitcode("xch", "a,b");
3270 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3271 emitcode (add, "a,b");
3273 else if (aopGetUsesAcc (leftOp, offset))
3275 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3276 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3280 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3281 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3283 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3284 add = "addc"; /* further adds must propagate carry */
3287 adjustArithmeticResult (ic);
3290 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3291 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3292 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3295 /*-----------------------------------------------------------------*/
3296 /* genMinusDec :- does subtraction with deccrement if possible */
3297 /*-----------------------------------------------------------------*/
3299 genMinusDec (iCode * ic)
3301 unsigned int icount;
3302 unsigned int size = getDataSize (IC_RESULT (ic));
3304 /* will try to generate an increment */
3305 /* if the right side is not a literal
3307 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3310 /* if the literal value of the right hand side
3311 is greater than 4 then it is not worth it */
3312 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3315 D(emitcode ("; genMinusDec",""));
3317 /* if decrement >=16 bits in register or direct space */
3318 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3319 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3327 /* If the next instruction is a goto and the goto target
3328 * is <= 10 instructions previous to this, we can generate
3329 * jumps straight to that target.
3331 if (ic->next && ic->next->op == GOTO
3332 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3333 && labelRange <= 10)
3335 emitcode (";", "tail decrement optimized");
3336 tlbl = IC_LABEL (ic->next);
3341 tlbl = newiTempLabel (NULL);
3345 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3346 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3347 IS_AOP_PREG (IC_RESULT (ic)))
3348 emitcode ("cjne", "%s,#0xff,%05d$"
3349 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3353 emitcode ("mov", "a,#0xff");
3354 emitcode ("cjne", "a,%s,%05d$"
3355 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3358 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3361 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3362 IS_AOP_PREG (IC_RESULT (ic)))
3363 emitcode ("cjne", "%s,#0xff,%05d$"
3364 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3368 emitcode ("cjne", "a,%s,%05d$"
3369 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3372 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3376 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3377 IS_AOP_PREG (IC_RESULT (ic)))
3378 emitcode ("cjne", "%s,#0xff,%05d$"
3379 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3383 emitcode ("cjne", "a,%s,%05d$"
3384 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3387 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3391 emitcode ("", "%05d$:", tlbl->key + 100);
3396 /* if the sizes are greater than 1 then we cannot */
3397 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3398 AOP_SIZE (IC_LEFT (ic)) > 1)
3401 /* we can if the aops of the left & result match or
3402 if they are in registers and the registers are the
3404 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3408 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3416 /*-----------------------------------------------------------------*/
3417 /* addSign - complete with sign */
3418 /*-----------------------------------------------------------------*/
3420 addSign (operand * result, int offset, int sign)
3422 int size = (getDataSize (result) - offset);
3427 emitcode ("rlc", "a");
3428 emitcode ("subb", "a,acc");
3430 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3434 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3438 /*-----------------------------------------------------------------*/
3439 /* genMinusBits - generates code for subtraction of two bits */
3440 /*-----------------------------------------------------------------*/
3442 genMinusBits (iCode * ic)
3444 symbol *lbl = newiTempLabel (NULL);
3446 D(emitcode ("; genMinusBits",""));
3448 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3450 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3451 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3452 emitcode ("cpl", "c");
3453 emitcode ("", "%05d$:", (lbl->key + 100));
3454 outBitC (IC_RESULT (ic));
3458 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3459 emitcode ("subb", "a,acc");
3460 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3461 emitcode ("inc", "a");
3462 emitcode ("", "%05d$:", (lbl->key + 100));
3463 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3464 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3468 /*-----------------------------------------------------------------*/
3469 /* genMinus - generates code for subtraction */
3470 /*-----------------------------------------------------------------*/
3472 genMinus (iCode * ic)
3474 int size, offset = 0;
3476 D(emitcode ("; genMinus",""));
3478 aopOp (IC_LEFT (ic), ic, FALSE);
3479 aopOp (IC_RIGHT (ic), ic, FALSE);
3480 aopOp (IC_RESULT (ic), ic, TRUE);
3482 /* special cases :- */
3483 /* if both left & right are in bit space */
3484 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3485 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3491 /* if I can do an decrement instead
3492 of subtract then GOOD for ME */
3493 if (genMinusDec (ic) == TRUE)
3496 size = getDataSize (IC_RESULT (ic));
3498 /* if literal, add a,#-lit, else normal subb */
3499 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3501 unsigned long lit = 0L;
3503 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3508 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3509 /* first add without previous c */
3511 if (!size && lit== (unsigned long) -1) {
3512 emitcode ("dec", "a");
3514 emitcode ("add", "a,#0x%02x",
3515 (unsigned int) (lit & 0x0FFL));
3518 emitcode ("addc", "a,#0x%02x",
3519 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3521 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3526 asmop *leftOp, *rightOp;
3528 leftOp = AOP(IC_LEFT(ic));
3529 rightOp = AOP(IC_RIGHT(ic));
3533 if (aopGetUsesAcc(rightOp, offset)) {
3534 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3535 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3537 emitcode( "setb", "c");
3539 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3540 emitcode("cpl", "a");
3542 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3545 emitcode ("subb", "a,%s",
3546 aopGet(rightOp, offset, FALSE, TRUE));
3549 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3554 adjustArithmeticResult (ic);
3557 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3558 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3559 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3563 /*-----------------------------------------------------------------*/
3564 /* genMultbits :- multiplication of bits */
3565 /*-----------------------------------------------------------------*/
3567 genMultbits (operand * left,
3571 D(emitcode ("; genMultbits",""));
3573 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3574 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3579 /*-----------------------------------------------------------------*/
3580 /* genMultOneByte : 8*8=8/16 bit multiplication */
3581 /*-----------------------------------------------------------------*/
3583 genMultOneByte (operand * left,
3587 sym_link *opetype = operandType (result);
3589 int size=AOP_SIZE(result);
3591 D(emitcode ("; genMultOneByte",""));
3593 if (size<1 || size>2) {
3594 // this should never happen
3595 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3596 AOP_SIZE(result), __FILE__, lineno);
3600 /* (if two literals: the value is computed before) */
3601 /* if one literal, literal on the right */
3602 if (AOP_TYPE (left) == AOP_LIT)
3607 //emitcode (";", "swapped left and right");
3610 if (SPEC_USIGN(opetype)
3611 // ignore the sign of left and right, what else can we do?
3612 || (SPEC_USIGN(operandType(left)) &&
3613 SPEC_USIGN(operandType(right)))) {
3614 // just an unsigned 8*8=8/16 multiply
3615 //emitcode (";","unsigned");
3616 // TODO: check for accumulator clash between left & right aops?
3617 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3618 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3619 emitcode ("mul", "ab");
3620 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3622 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3627 // we have to do a signed multiply
3629 //emitcode (";", "signed");
3630 emitcode ("clr", "F0"); // reset sign flag
3631 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3633 lbl=newiTempLabel(NULL);
3634 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3635 // left side is negative, 8-bit two's complement, this fails for -128
3636 emitcode ("setb", "F0"); // set sign flag
3637 emitcode ("cpl", "a");
3638 emitcode ("inc", "a");
3640 emitcode ("", "%05d$:", lbl->key+100);
3643 if (AOP_TYPE(right)==AOP_LIT) {
3644 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3645 /* AND literal negative */
3647 emitcode ("cpl", "F0"); // complement sign flag
3648 emitcode ("mov", "b,#0x%02x", -val);
3650 emitcode ("mov", "b,#0x%02x", val);
3653 lbl=newiTempLabel(NULL);
3654 emitcode ("mov", "b,a");
3655 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3656 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3657 // right side is negative, 8-bit two's complement
3658 emitcode ("cpl", "F0"); // complement sign flag
3659 emitcode ("cpl", "a");
3660 emitcode ("inc", "a");
3661 emitcode ("", "%05d$:", lbl->key+100);
3663 emitcode ("mul", "ab");
3665 lbl=newiTempLabel(NULL);
3666 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3667 // only ONE op was negative, we have to do a 8/16-bit two's complement
3668 emitcode ("cpl", "a"); // lsb
3670 emitcode ("inc", "a");
3672 emitcode ("add", "a,#1");
3673 emitcode ("xch", "a,b");
3674 emitcode ("cpl", "a"); // msb
3675 emitcode ("addc", "a,#0");
3676 emitcode ("xch", "a,b");
3679 emitcode ("", "%05d$:", lbl->key+100);
3680 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3682 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3686 /*-----------------------------------------------------------------*/
3687 /* genMult - generates code for multiplication */
3688 /*-----------------------------------------------------------------*/
3690 genMult (iCode * ic)
3692 operand *left = IC_LEFT (ic);
3693 operand *right = IC_RIGHT (ic);
3694 operand *result = IC_RESULT (ic);
3696 D(emitcode ("; genMult",""));
3698 /* assign the amsops */
3699 aopOp (left, ic, FALSE);
3700 aopOp (right, ic, FALSE);
3701 aopOp (result, ic, TRUE);
3703 /* special cases first */
3705 if (AOP_TYPE (left) == AOP_CRY &&
3706 AOP_TYPE (right) == AOP_CRY)
3708 genMultbits (left, right, result);
3712 /* if both are of size == 1 */
3713 #if 0 // one of them can be a sloc shared with the result
3714 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3716 if (getSize(operandType(left)) == 1 &&
3717 getSize(operandType(right)) == 1)
3720 genMultOneByte (left, right, result);
3724 /* should have been converted to function call */
3725 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3726 getSize(OP_SYMBOL(right)->type));
3730 freeAsmop (result, NULL, ic, TRUE);
3731 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3732 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3735 /*-----------------------------------------------------------------*/
3736 /* genDivbits :- division of bits */
3737 /*-----------------------------------------------------------------*/
3739 genDivbits (operand * left,
3746 D(emitcode ("; genDivbits",""));
3748 /* the result must be bit */
3749 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3750 l = aopGet (AOP (left), 0, FALSE, FALSE);
3754 emitcode ("div", "ab");
3755 emitcode ("rrc", "a");
3756 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3759 /*-----------------------------------------------------------------*/
3760 /* genDivOneByte : 8 bit division */
3761 /*-----------------------------------------------------------------*/
3763 genDivOneByte (operand * left,
3767 sym_link *opetype = operandType (result);
3772 D(emitcode ("; genDivOneByte",""));
3774 size = AOP_SIZE (result) - 1;
3776 /* signed or unsigned */
3777 if (SPEC_USIGN (opetype))
3779 /* unsigned is easy */
3780 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3781 l = aopGet (AOP (left), 0, FALSE, FALSE);
3783 emitcode ("div", "ab");
3784 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3786 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3790 /* signed is a little bit more difficult */
3792 /* save the signs of the operands */
3793 l = aopGet (AOP (left), 0, FALSE, FALSE);
3795 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3796 emitcode ("push", "acc"); /* save it on the stack */
3798 /* now sign adjust for both left & right */
3799 l = aopGet (AOP (right), 0, FALSE, FALSE);
3801 lbl = newiTempLabel (NULL);
3802 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3803 emitcode ("cpl", "a");
3804 emitcode ("inc", "a");
3805 emitcode ("", "%05d$:", (lbl->key + 100));
3806 emitcode ("mov", "b,a");
3808 /* sign adjust left side */
3809 l = aopGet (AOP (left), 0, FALSE, FALSE);
3812 lbl = newiTempLabel (NULL);
3813 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3814 emitcode ("cpl", "a");
3815 emitcode ("inc", "a");
3816 emitcode ("", "%05d$:", (lbl->key + 100));
3818 /* now the division */
3819 emitcode ("div", "ab");
3820 /* we are interested in the lower order
3822 emitcode ("mov", "b,a");
3823 lbl = newiTempLabel (NULL);
3824 emitcode ("pop", "acc");
3825 /* if there was an over flow we don't
3826 adjust the sign of the result */
3827 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3828 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3830 emitcode ("clr", "a");
3831 emitcode ("subb", "a,b");
3832 emitcode ("mov", "b,a");
3833 emitcode ("", "%05d$:", (lbl->key + 100));
3835 /* now we are done */
3836 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3839 emitcode ("mov", "c,b.7");
3840 emitcode ("subb", "a,acc");
3843 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3847 /*-----------------------------------------------------------------*/
3848 /* genDiv - generates code for division */
3849 /*-----------------------------------------------------------------*/
3853 operand *left = IC_LEFT (ic);
3854 operand *right = IC_RIGHT (ic);
3855 operand *result = IC_RESULT (ic);
3857 D(emitcode ("; genDiv",""));
3859 /* assign the amsops */
3860 aopOp (left, ic, FALSE);
3861 aopOp (right, ic, FALSE);
3862 aopOp (result, ic, TRUE);
3864 /* special cases first */
3866 if (AOP_TYPE (left) == AOP_CRY &&
3867 AOP_TYPE (right) == AOP_CRY)
3869 genDivbits (left, right, result);
3873 /* if both are of size == 1 */
3874 if (AOP_SIZE (left) == 1 &&
3875 AOP_SIZE (right) == 1)
3877 genDivOneByte (left, right, result);
3881 /* should have been converted to function call */
3884 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3885 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3886 freeAsmop (result, NULL, ic, TRUE);
3889 /*-----------------------------------------------------------------*/
3890 /* genModbits :- modulus of bits */
3891 /*-----------------------------------------------------------------*/
3893 genModbits (operand * left,
3900 D(emitcode ("; genModbits",""));
3902 /* the result must be bit */
3903 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3904 l = aopGet (AOP (left), 0, FALSE, FALSE);
3908 emitcode ("div", "ab");
3909 emitcode ("mov", "a,b");
3910 emitcode ("rrc", "a");
3911 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3914 /*-----------------------------------------------------------------*/
3915 /* genModOneByte : 8 bit modulus */
3916 /*-----------------------------------------------------------------*/
3918 genModOneByte (operand * left,
3922 sym_link *opetype = operandType (result);
3926 D(emitcode ("; genModOneByte",""));
3928 /* signed or unsigned */
3929 if (SPEC_USIGN (opetype))
3931 /* unsigned is easy */
3932 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3933 l = aopGet (AOP (left), 0, FALSE, FALSE);
3935 emitcode ("div", "ab");
3936 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3940 /* signed is a little bit more difficult */
3942 /* save the signs of the operands */
3943 l = aopGet (AOP (left), 0, FALSE, FALSE);
3946 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3947 emitcode ("push", "acc"); /* save it on the stack */
3949 /* now sign adjust for both left & right */
3950 l = aopGet (AOP (right), 0, FALSE, FALSE);
3953 lbl = newiTempLabel (NULL);
3954 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3955 emitcode ("cpl", "a");
3956 emitcode ("inc", "a");
3957 emitcode ("", "%05d$:", (lbl->key + 100));
3958 emitcode ("mov", "b,a");
3960 /* sign adjust left side */
3961 l = aopGet (AOP (left), 0, FALSE, FALSE);
3964 lbl = newiTempLabel (NULL);
3965 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3966 emitcode ("cpl", "a");
3967 emitcode ("inc", "a");
3968 emitcode ("", "%05d$:", (lbl->key + 100));
3970 /* now the multiplication */
3971 emitcode ("div", "ab");
3972 /* we are interested in the lower order
3974 lbl = newiTempLabel (NULL);
3975 emitcode ("pop", "acc");
3976 /* if there was an over flow we don't
3977 adjust the sign of the result */
3978 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3979 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3981 emitcode ("clr", "a");
3982 emitcode ("subb", "a,b");
3983 emitcode ("mov", "b,a");
3984 emitcode ("", "%05d$:", (lbl->key + 100));
3986 /* now we are done */
3987 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3991 /*-----------------------------------------------------------------*/
3992 /* genMod - generates code for division */
3993 /*-----------------------------------------------------------------*/
3997 operand *left = IC_LEFT (ic);
3998 operand *right = IC_RIGHT (ic);
3999 operand *result = IC_RESULT (ic);
4001 D(emitcode ("; genMod",""));
4003 /* assign the amsops */
4004 aopOp (left, ic, FALSE);
4005 aopOp (right, ic, FALSE);
4006 aopOp (result, ic, TRUE);
4008 /* special cases first */
4010 if (AOP_TYPE (left) == AOP_CRY &&
4011 AOP_TYPE (right) == AOP_CRY)
4013 genModbits (left, right, result);
4017 /* if both are of size == 1 */
4018 if (AOP_SIZE (left) == 1 &&
4019 AOP_SIZE (right) == 1)
4021 genModOneByte (left, right, result);
4025 /* should have been converted to function call */
4029 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4030 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4031 freeAsmop (result, NULL, ic, TRUE);
4034 /*-----------------------------------------------------------------*/
4035 /* genIfxJump :- will create a jump depending on the ifx */
4036 /*-----------------------------------------------------------------*/
4038 genIfxJump (iCode * ic, char *jval)
4041 symbol *tlbl = newiTempLabel (NULL);
4044 D(emitcode ("; genIfxJump",""));
4046 /* if true label then we jump if condition
4050 jlbl = IC_TRUE (ic);
4051 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4052 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4056 /* false label is present */
4057 jlbl = IC_FALSE (ic);
4058 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4059 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4061 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4062 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4064 emitcode (inst, "%05d$", tlbl->key + 100);
4065 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4066 emitcode ("", "%05d$:", tlbl->key + 100);
4068 /* mark the icode as generated */
4072 /*-----------------------------------------------------------------*/
4073 /* genCmp :- greater or less than comparison */
4074 /*-----------------------------------------------------------------*/
4076 genCmp (operand * left, operand * right,
4077 operand * result, iCode * ifx, int sign, iCode *ic)
4079 int size, offset = 0;
4080 unsigned long lit = 0L;
4083 D(emitcode ("; genCmp",""));
4085 /* if left & right are bit variables */
4086 if (AOP_TYPE (left) == AOP_CRY &&
4087 AOP_TYPE (right) == AOP_CRY)
4089 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4090 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4094 /* subtract right from left if at the
4095 end the carry flag is set then we know that
4096 left is greater than right */
4097 size = max (AOP_SIZE (left), AOP_SIZE (right));
4099 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4100 if ((size == 1) && !sign &&
4101 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4103 symbol *lbl = newiTempLabel (NULL);
4104 emitcode ("cjne", "%s,%s,%05d$",
4105 aopGet (AOP (left), offset, FALSE, FALSE),
4106 aopGet (AOP (right), offset, FALSE, FALSE),
4108 emitcode ("", "%05d$:", lbl->key + 100);
4112 if (AOP_TYPE (right) == AOP_LIT)
4114 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4115 /* optimize if(x < 0) or if(x >= 0) */
4124 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4125 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4127 genIfxJump (ifx, "acc.7");
4131 emitcode ("rlc", "a");
4139 rightInB = aopGetUsesAcc(AOP (right), offset);
4141 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4142 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4143 if (sign && size == 0)
4145 emitcode ("xrl", "a,#0x80");
4146 if (AOP_TYPE (right) == AOP_LIT)
4148 unsigned long lit = (unsigned long)
4149 floatFromVal (AOP (right)->aopu.aop_lit);
4150 emitcode ("subb", "a,#0x%02x",
4151 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4156 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4157 emitcode ("xrl", "b,#0x80");
4158 emitcode ("subb", "a,b");
4164 emitcode ("subb", "a,b");
4166 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4174 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4175 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4176 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4182 /* if the result is used in the next
4183 ifx conditional branch then generate
4184 code a little differently */
4186 genIfxJump (ifx, "c");
4189 /* leave the result in acc */
4193 /*-----------------------------------------------------------------*/
4194 /* genCmpGt :- greater than comparison */
4195 /*-----------------------------------------------------------------*/
4197 genCmpGt (iCode * ic, iCode * ifx)
4199 operand *left, *right, *result;
4200 sym_link *letype, *retype;
4203 D(emitcode ("; genCmpGt",""));
4205 left = IC_LEFT (ic);
4206 right = IC_RIGHT (ic);
4207 result = IC_RESULT (ic);
4209 letype = getSpec (operandType (left));
4210 retype = getSpec (operandType (right));
4211 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4212 /* assign the amsops */
4213 aopOp (left, ic, FALSE);
4214 aopOp (right, ic, FALSE);
4215 aopOp (result, ic, TRUE);
4217 genCmp (right, left, result, ifx, sign,ic);
4219 freeAsmop (result, NULL, ic, TRUE);
4222 /*-----------------------------------------------------------------*/
4223 /* genCmpLt - less than comparisons */
4224 /*-----------------------------------------------------------------*/
4226 genCmpLt (iCode * ic, iCode * ifx)
4228 operand *left, *right, *result;
4229 sym_link *letype, *retype;
4232 D(emitcode ("; genCmpLt",""));
4234 left = IC_LEFT (ic);
4235 right = IC_RIGHT (ic);
4236 result = IC_RESULT (ic);
4238 letype = getSpec (operandType (left));
4239 retype = getSpec (operandType (right));
4240 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4242 /* assign the amsops */
4243 aopOp (left, ic, FALSE);
4244 aopOp (right, ic, FALSE);
4245 aopOp (result, ic, TRUE);
4247 genCmp (left, right, result, ifx, sign,ic);
4249 freeAsmop (result, NULL, ic, TRUE);
4252 /*-----------------------------------------------------------------*/
4253 /* gencjneshort - compare and jump if not equal */
4254 /*-----------------------------------------------------------------*/
4256 gencjneshort (operand * left, operand * right, symbol * lbl)
4258 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4260 unsigned long lit = 0L;
4262 /* if the left side is a literal or
4263 if the right is in a pointer register and left
4265 if ((AOP_TYPE (left) == AOP_LIT) ||
4266 (AOP_TYPE (left) == AOP_IMMD) ||
4267 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4274 if (AOP_TYPE (right) == AOP_LIT)
4275 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4277 /* if the right side is a literal then anything goes */
4278 if (AOP_TYPE (right) == AOP_LIT &&
4279 AOP_TYPE (left) != AOP_DIR &&
4280 AOP_TYPE (left) != AOP_IMMD)
4284 emitcode ("cjne", "%s,%s,%05d$",
4285 aopGet (AOP (left), offset, FALSE, FALSE),
4286 aopGet (AOP (right), offset, FALSE, FALSE),
4292 /* if the right side is in a register or in direct space or
4293 if the left is a pointer register & right is not */
4294 else if (AOP_TYPE (right) == AOP_REG ||
4295 AOP_TYPE (right) == AOP_DIR ||
4296 AOP_TYPE (right) == AOP_LIT ||
4297 AOP_TYPE (right) == AOP_IMMD ||
4298 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4299 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4303 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4304 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4305 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4306 emitcode ("jnz", "%05d$", lbl->key + 100);
4308 emitcode ("cjne", "a,%s,%05d$",
4309 aopGet (AOP (right), offset, FALSE, TRUE),
4316 /* right is a pointer reg need both a & b */
4319 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4320 if (strcmp (l, "b"))
4321 emitcode ("mov", "b,%s", l);
4322 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4323 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4329 /*-----------------------------------------------------------------*/
4330 /* gencjne - compare and jump if not equal */
4331 /*-----------------------------------------------------------------*/
4333 gencjne (operand * left, operand * right, symbol * lbl)
4335 symbol *tlbl = newiTempLabel (NULL);
4337 gencjneshort (left, right, lbl);
4339 emitcode ("mov", "a,%s", one);
4340 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4341 emitcode ("", "%05d$:", lbl->key + 100);
4342 emitcode ("clr", "a");
4343 emitcode ("", "%05d$:", tlbl->key + 100);
4346 /*-----------------------------------------------------------------*/
4347 /* genCmpEq - generates code for equal to */
4348 /*-----------------------------------------------------------------*/
4350 genCmpEq (iCode * ic, iCode * ifx)
4352 operand *left, *right, *result;
4354 D(emitcode ("; genCmpEq",""));
4356 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4357 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4358 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4360 /* if literal, literal on the right or
4361 if the right is in a pointer register and left
4363 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4364 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4366 operand *t = IC_RIGHT (ic);
4367 IC_RIGHT (ic) = IC_LEFT (ic);
4371 if (ifx && !AOP_SIZE (result))
4374 /* if they are both bit variables */
4375 if (AOP_TYPE (left) == AOP_CRY &&
4376 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4378 if (AOP_TYPE (right) == AOP_LIT)
4380 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4383 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4384 emitcode ("cpl", "c");
4388 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4392 emitcode ("clr", "c");
4394 /* AOP_TYPE(right) == AOP_CRY */
4398 symbol *lbl = newiTempLabel (NULL);
4399 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4400 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4401 emitcode ("cpl", "c");
4402 emitcode ("", "%05d$:", (lbl->key + 100));
4404 /* if true label then we jump if condition
4406 tlbl = newiTempLabel (NULL);
4409 emitcode ("jnc", "%05d$", tlbl->key + 100);
4410 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4414 emitcode ("jc", "%05d$", tlbl->key + 100);
4415 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4417 emitcode ("", "%05d$:", tlbl->key + 100);
4421 tlbl = newiTempLabel (NULL);
4422 gencjneshort (left, right, tlbl);
4425 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4426 emitcode ("", "%05d$:", tlbl->key + 100);
4430 symbol *lbl = newiTempLabel (NULL);
4431 emitcode ("sjmp", "%05d$", lbl->key + 100);
4432 emitcode ("", "%05d$:", tlbl->key + 100);
4433 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4434 emitcode ("", "%05d$:", lbl->key + 100);
4437 /* mark the icode as generated */
4442 /* if they are both bit variables */
4443 if (AOP_TYPE (left) == AOP_CRY &&
4444 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4446 if (AOP_TYPE (right) == AOP_LIT)
4448 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4451 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4452 emitcode ("cpl", "c");
4456 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4460 emitcode ("clr", "c");
4462 /* AOP_TYPE(right) == AOP_CRY */
4466 symbol *lbl = newiTempLabel (NULL);
4467 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4468 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4469 emitcode ("cpl", "c");
4470 emitcode ("", "%05d$:", (lbl->key + 100));
4473 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4480 genIfxJump (ifx, "c");
4483 /* if the result is used in an arithmetic operation
4484 then put the result in place */
4489 gencjne (left, right, newiTempLabel (NULL));
4490 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4492 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4497 genIfxJump (ifx, "a");
4500 /* if the result is used in an arithmetic operation
4501 then put the result in place */
4502 if (AOP_TYPE (result) != AOP_CRY)
4504 /* leave the result in acc */
4508 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4509 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4510 freeAsmop (result, NULL, ic, TRUE);
4513 /*-----------------------------------------------------------------*/
4514 /* ifxForOp - returns the icode containing the ifx for operand */
4515 /*-----------------------------------------------------------------*/
4517 ifxForOp (operand * op, iCode * ic)
4519 /* if true symbol then needs to be assigned */
4520 if (IS_TRUE_SYMOP (op))
4523 /* if this has register type condition and
4524 the next instruction is ifx with the same operand
4525 and live to of the operand is upto the ifx only then */
4527 ic->next->op == IFX &&
4528 IC_COND (ic->next)->key == op->key &&
4529 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4535 /*-----------------------------------------------------------------*/
4536 /* hasInc - operand is incremented before any other use */
4537 /*-----------------------------------------------------------------*/
4539 hasInc (operand *op, iCode *ic,int osize)
4541 sym_link *type = operandType(op);
4542 sym_link *retype = getSpec (type);
4543 iCode *lic = ic->next;
4546 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4547 if (!IS_SYMOP(op)) return NULL;
4549 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4550 if (IS_AGGREGATE(type->next)) return NULL;
4551 if (osize != (isize = getSize(type->next))) return NULL;
4554 /* if operand of the form op = op + <sizeof *op> */
4555 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4556 isOperandEqual(IC_RESULT(lic),op) &&
4557 isOperandLiteral(IC_RIGHT(lic)) &&
4558 operandLitValue(IC_RIGHT(lic)) == isize) {
4561 /* if the operand used or deffed */
4562 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4565 /* if GOTO or IFX */
4566 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4572 /*-----------------------------------------------------------------*/
4573 /* genAndOp - for && operation */
4574 /*-----------------------------------------------------------------*/
4576 genAndOp (iCode * ic)
4578 operand *left, *right, *result;
4581 D(emitcode ("; genAndOp",""));
4583 /* note here that && operations that are in an
4584 if statement are taken away by backPatchLabels
4585 only those used in arthmetic operations remain */
4586 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4587 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4588 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4590 /* if both are bit variables */
4591 if (AOP_TYPE (left) == AOP_CRY &&
4592 AOP_TYPE (right) == AOP_CRY)
4594 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4595 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4600 tlbl = newiTempLabel (NULL);
4602 emitcode ("jz", "%05d$", tlbl->key + 100);
4604 emitcode ("", "%05d$:", tlbl->key + 100);
4608 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4609 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4610 freeAsmop (result, NULL, ic, TRUE);
4614 /*-----------------------------------------------------------------*/
4615 /* genOrOp - for || operation */
4616 /*-----------------------------------------------------------------*/
4618 genOrOp (iCode * ic)
4620 operand *left, *right, *result;
4623 D(emitcode ("; genOrOp",""));
4625 /* note here that || operations that are in an
4626 if statement are taken away by backPatchLabels
4627 only those used in arthmetic operations remain */
4628 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4629 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4630 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4632 /* if both are bit variables */
4633 if (AOP_TYPE (left) == AOP_CRY &&
4634 AOP_TYPE (right) == AOP_CRY)
4636 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4637 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4642 tlbl = newiTempLabel (NULL);
4644 emitcode ("jnz", "%05d$", tlbl->key + 100);
4646 emitcode ("", "%05d$:", tlbl->key + 100);
4650 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4651 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4652 freeAsmop (result, NULL, ic, TRUE);
4655 /*-----------------------------------------------------------------*/
4656 /* isLiteralBit - test if lit == 2^n */
4657 /*-----------------------------------------------------------------*/
4659 isLiteralBit (unsigned long lit)
4661 unsigned long pw[32] =
4662 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4663 0x100L, 0x200L, 0x400L, 0x800L,
4664 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4665 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4666 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4667 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4668 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4671 for (idx = 0; idx < 32; idx++)
4677 /*-----------------------------------------------------------------*/
4678 /* continueIfTrue - */
4679 /*-----------------------------------------------------------------*/
4681 continueIfTrue (iCode * ic)
4684 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4688 /*-----------------------------------------------------------------*/
4690 /*-----------------------------------------------------------------*/
4692 jumpIfTrue (iCode * ic)
4695 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4699 /*-----------------------------------------------------------------*/
4700 /* jmpTrueOrFalse - */
4701 /*-----------------------------------------------------------------*/
4703 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4705 // ugly but optimized by peephole
4708 symbol *nlbl = newiTempLabel (NULL);
4709 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4710 emitcode ("", "%05d$:", tlbl->key + 100);
4711 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4712 emitcode ("", "%05d$:", nlbl->key + 100);
4716 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4717 emitcode ("", "%05d$:", tlbl->key + 100);
4722 /*-----------------------------------------------------------------*/
4723 /* genAnd - code for and */
4724 /*-----------------------------------------------------------------*/
4726 genAnd (iCode * ic, iCode * ifx)
4728 operand *left, *right, *result;
4729 int size, offset = 0;
4730 unsigned long lit = 0L;
4734 D(emitcode ("; genAnd",""));
4736 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4737 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4738 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4741 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4743 AOP_TYPE (left), AOP_TYPE (right));
4744 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4746 AOP_SIZE (left), AOP_SIZE (right));
4749 /* if left is a literal & right is not then exchange them */
4750 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4751 AOP_NEEDSACC (left))
4753 operand *tmp = right;
4758 /* if result = right then exchange them */
4759 if (sameRegs (AOP (result), AOP (right)))
4761 operand *tmp = right;
4766 /* if right is bit then exchange them */
4767 if (AOP_TYPE (right) == AOP_CRY &&
4768 AOP_TYPE (left) != AOP_CRY)
4770 operand *tmp = right;
4774 if (AOP_TYPE (right) == AOP_LIT)
4775 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4777 size = AOP_SIZE (result);
4780 // result = bit & yy;
4781 if (AOP_TYPE (left) == AOP_CRY)
4783 // c = bit & literal;
4784 if (AOP_TYPE (right) == AOP_LIT)
4788 if (size && sameRegs (AOP (result), AOP (left)))
4791 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4796 if (size && (AOP_TYPE (result) == AOP_CRY))
4798 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4801 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4806 emitcode ("clr", "c");
4811 if (AOP_TYPE (right) == AOP_CRY)
4814 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4815 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4820 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4822 emitcode ("rrc", "a");
4823 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4831 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4832 genIfxJump (ifx, "c");
4836 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4837 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4838 if ((AOP_TYPE (right) == AOP_LIT) &&
4839 (AOP_TYPE (result) == AOP_CRY) &&
4840 (AOP_TYPE (left) != AOP_CRY))
4842 int posbit = isLiteralBit (lit);
4847 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4850 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4856 sprintf (buffer, "acc.%d", posbit & 0x07);
4857 genIfxJump (ifx, buffer);
4864 symbol *tlbl = newiTempLabel (NULL);
4865 int sizel = AOP_SIZE (left);
4867 emitcode ("setb", "c");
4870 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4872 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4874 if ((posbit = isLiteralBit (bytelit)) != 0)
4875 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4878 if (bytelit != 0x0FFL)
4879 emitcode ("anl", "a,%s",
4880 aopGet (AOP (right), offset, FALSE, TRUE));
4881 emitcode ("jnz", "%05d$", tlbl->key + 100);
4886 // bit = left & literal
4889 emitcode ("clr", "c");
4890 emitcode ("", "%05d$:", tlbl->key + 100);
4892 // if(left & literal)
4896 jmpTrueOrFalse (ifx, tlbl);
4904 /* if left is same as result */
4905 if (sameRegs (AOP (result), AOP (left)))
4907 for (; size--; offset++)
4909 if (AOP_TYPE (right) == AOP_LIT)
4911 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4913 else if (bytelit == 0)
4915 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4917 else if (IS_AOP_PREG (result))
4919 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4920 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4921 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4924 emitcode ("anl", "%s,%s",
4925 aopGet (AOP (left), offset, FALSE, TRUE),
4926 aopGet (AOP (right), offset, FALSE, FALSE));
4930 if (AOP_TYPE (left) == AOP_ACC)
4931 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4934 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4935 if (IS_AOP_PREG (result))
4937 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4938 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4942 emitcode ("anl", "%s,a",
4943 aopGet (AOP (left), offset, FALSE, TRUE));
4950 // left & result in different registers
4951 if (AOP_TYPE (result) == AOP_CRY)
4954 // if(size), result in bit
4955 // if(!size && ifx), conditional oper: if(left & right)
4956 symbol *tlbl = newiTempLabel (NULL);
4957 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4959 emitcode ("setb", "c");
4962 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4963 emitcode ("anl", "a,%s",
4964 aopGet (AOP (right), offset, FALSE, FALSE));
4966 if (AOP_TYPE(left)==AOP_ACC) {
4967 emitcode("mov", "b,a");
4968 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4969 emitcode("anl", "a,b");
4971 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4972 emitcode ("anl", "a,%s",
4973 aopGet (AOP (left), offset, FALSE, FALSE));
4976 emitcode ("jnz", "%05d$", tlbl->key + 100);
4982 emitcode ("", "%05d$:", tlbl->key + 100);
4986 jmpTrueOrFalse (ifx, tlbl);
4990 for (; (size--); offset++)
4993 // result = left & right
4994 if (AOP_TYPE (right) == AOP_LIT)
4996 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4998 aopPut (AOP (result),
4999 aopGet (AOP (left), offset, FALSE, FALSE),
5001 isOperandVolatile (result, FALSE));
5004 else if (bytelit == 0)
5006 /* dummy read of volatile operand */
5007 if (isOperandVolatile (left, FALSE))
5008 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5009 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5013 // faster than result <- left, anl result,right
5014 // and better if result is SFR
5015 if (AOP_TYPE (left) == AOP_ACC)
5016 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5019 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5020 emitcode ("anl", "a,%s",
5021 aopGet (AOP (left), offset, FALSE, FALSE));
5023 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5029 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5030 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5031 freeAsmop (result, NULL, ic, TRUE);
5034 /*-----------------------------------------------------------------*/
5035 /* genOr - code for or */
5036 /*-----------------------------------------------------------------*/
5038 genOr (iCode * ic, iCode * ifx)
5040 operand *left, *right, *result;
5041 int size, offset = 0;
5042 unsigned long lit = 0L;
5044 D(emitcode ("; genOr",""));
5046 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5047 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5048 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5051 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5053 AOP_TYPE (left), AOP_TYPE (right));
5054 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5056 AOP_SIZE (left), AOP_SIZE (right));
5059 /* if left is a literal & right is not then exchange them */
5060 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5061 AOP_NEEDSACC (left))
5063 operand *tmp = right;
5068 /* if result = right then exchange them */
5069 if (sameRegs (AOP (result), AOP (right)))
5071 operand *tmp = right;
5076 /* if right is bit then exchange them */
5077 if (AOP_TYPE (right) == AOP_CRY &&
5078 AOP_TYPE (left) != AOP_CRY)
5080 operand *tmp = right;
5084 if (AOP_TYPE (right) == AOP_LIT)
5085 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5087 size = AOP_SIZE (result);
5091 if (AOP_TYPE (left) == AOP_CRY)
5093 if (AOP_TYPE (right) == AOP_LIT)
5095 // c = bit | literal;
5098 // lit != 0 => result = 1
5099 if (AOP_TYPE (result) == AOP_CRY)
5102 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5104 continueIfTrue (ifx);
5107 emitcode ("setb", "c");
5111 // lit == 0 => result = left
5112 if (size && sameRegs (AOP (result), AOP (left)))
5114 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5119 if (AOP_TYPE (right) == AOP_CRY)
5122 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5123 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5128 symbol *tlbl = newiTempLabel (NULL);
5129 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5130 emitcode ("setb", "c");
5131 emitcode ("jb", "%s,%05d$",
5132 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5134 emitcode ("jnz", "%05d$", tlbl->key + 100);
5135 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5137 jmpTrueOrFalse (ifx, tlbl);
5143 emitcode ("", "%05d$:", tlbl->key + 100);
5152 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5153 genIfxJump (ifx, "c");
5157 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5158 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5159 if ((AOP_TYPE (right) == AOP_LIT) &&
5160 (AOP_TYPE (result) == AOP_CRY) &&
5161 (AOP_TYPE (left) != AOP_CRY))
5167 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5169 continueIfTrue (ifx);
5174 // lit = 0, result = boolean(left)
5176 emitcode ("setb", "c");
5180 symbol *tlbl = newiTempLabel (NULL);
5181 emitcode ("jnz", "%05d$", tlbl->key + 100);
5183 emitcode ("", "%05d$:", tlbl->key + 100);
5187 genIfxJump (ifx, "a");
5195 /* if left is same as result */
5196 if (sameRegs (AOP (result), AOP (left)))
5198 for (; size--; offset++)
5200 if (AOP_TYPE (right) == AOP_LIT)
5202 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5204 /* dummy read of volatile operand */
5205 if (isOperandVolatile (left, FALSE))
5206 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5210 else if (IS_AOP_PREG (left))
5212 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5213 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5214 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5217 emitcode ("orl", "%s,%s",
5218 aopGet (AOP (left), offset, FALSE, TRUE),
5219 aopGet (AOP (right), offset, FALSE, FALSE));
5223 if (AOP_TYPE (left) == AOP_ACC)
5224 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5227 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5228 if (IS_AOP_PREG (left))
5230 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5231 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5234 emitcode ("orl", "%s,a",
5235 aopGet (AOP (left), offset, FALSE, TRUE));
5242 // left & result in different registers
5243 if (AOP_TYPE (result) == AOP_CRY)
5246 // if(size), result in bit
5247 // if(!size && ifx), conditional oper: if(left | right)
5248 symbol *tlbl = newiTempLabel (NULL);
5249 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5251 emitcode ("setb", "c");
5254 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5255 emitcode ("orl", "a,%s",
5256 aopGet (AOP (right), offset, FALSE, FALSE));
5258 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5259 emitcode ("orl", "a,%s",
5260 aopGet (AOP (left), offset, FALSE, FALSE));
5262 emitcode ("jnz", "%05d$", tlbl->key + 100);
5268 emitcode ("", "%05d$:", tlbl->key + 100);
5272 jmpTrueOrFalse (ifx, tlbl);
5275 for (; (size--); offset++)
5278 // result = left & right
5279 if (AOP_TYPE (right) == AOP_LIT)
5281 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5283 aopPut (AOP (result),
5284 aopGet (AOP (left), offset, FALSE, FALSE),
5286 isOperandVolatile (result, FALSE));
5290 // faster than result <- left, anl result,right
5291 // and better if result is SFR
5292 if (AOP_TYPE (left) == AOP_ACC)
5293 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5296 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5297 emitcode ("orl", "a,%s",
5298 aopGet (AOP (left), offset, FALSE, FALSE));
5300 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5305 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5306 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5307 freeAsmop (result, NULL, ic, TRUE);
5310 /*-----------------------------------------------------------------*/
5311 /* genXor - code for xclusive or */
5312 /*-----------------------------------------------------------------*/
5314 genXor (iCode * ic, iCode * ifx)
5316 operand *left, *right, *result;
5317 int size, offset = 0;
5318 unsigned long lit = 0L;
5320 D(emitcode ("; genXor",""));
5322 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5323 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5324 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5327 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5329 AOP_TYPE (left), AOP_TYPE (right));
5330 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5332 AOP_SIZE (left), AOP_SIZE (right));
5335 /* if left is a literal & right is not ||
5336 if left needs acc & right does not */
5337 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5338 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5340 operand *tmp = right;
5345 /* if result = right then exchange them */
5346 if (sameRegs (AOP (result), AOP (right)))
5348 operand *tmp = right;
5353 /* if right is bit then exchange them */
5354 if (AOP_TYPE (right) == AOP_CRY &&
5355 AOP_TYPE (left) != AOP_CRY)
5357 operand *tmp = right;
5361 if (AOP_TYPE (right) == AOP_LIT)
5362 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5364 size = AOP_SIZE (result);
5368 if (AOP_TYPE (left) == AOP_CRY)
5370 if (AOP_TYPE (right) == AOP_LIT)
5372 // c = bit & literal;
5375 // lit>>1 != 0 => result = 1
5376 if (AOP_TYPE (result) == AOP_CRY)
5379 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5381 continueIfTrue (ifx);
5384 emitcode ("setb", "c");
5391 // lit == 0, result = left
5392 if (size && sameRegs (AOP (result), AOP (left)))
5394 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5398 // lit == 1, result = not(left)
5399 if (size && sameRegs (AOP (result), AOP (left)))
5401 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5406 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5407 emitcode ("cpl", "c");
5416 symbol *tlbl = newiTempLabel (NULL);
5417 if (AOP_TYPE (right) == AOP_CRY)
5420 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5424 int sizer = AOP_SIZE (right);
5426 // if val>>1 != 0, result = 1
5427 emitcode ("setb", "c");
5430 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5432 // test the msb of the lsb
5433 emitcode ("anl", "a,#0xfe");
5434 emitcode ("jnz", "%05d$", tlbl->key + 100);
5438 emitcode ("rrc", "a");
5440 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5441 emitcode ("cpl", "c");
5442 emitcode ("", "%05d$:", (tlbl->key + 100));
5449 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5450 genIfxJump (ifx, "c");
5454 if (sameRegs (AOP (result), AOP (left)))
5456 /* if left is same as result */
5457 for (; size--; offset++)
5459 if (AOP_TYPE (right) == AOP_LIT)
5461 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5463 else if (IS_AOP_PREG (left))
5465 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5466 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5467 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5470 emitcode ("xrl", "%s,%s",
5471 aopGet (AOP (left), offset, FALSE, TRUE),
5472 aopGet (AOP (right), offset, FALSE, FALSE));
5476 if (AOP_TYPE (left) == AOP_ACC)
5477 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5480 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5481 if (IS_AOP_PREG (left))
5483 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5484 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5487 emitcode ("xrl", "%s,a",
5488 aopGet (AOP (left), offset, FALSE, TRUE));
5495 // left & result in different registers
5496 if (AOP_TYPE (result) == AOP_CRY)
5499 // if(size), result in bit
5500 // if(!size && ifx), conditional oper: if(left ^ right)
5501 symbol *tlbl = newiTempLabel (NULL);
5502 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5504 emitcode ("setb", "c");
5507 if ((AOP_TYPE (right) == AOP_LIT) &&
5508 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5510 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5514 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5515 emitcode ("xrl", "a,%s",
5516 aopGet (AOP (right), offset, FALSE, FALSE));
5518 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5519 emitcode ("xrl", "a,%s",
5520 aopGet (AOP (left), offset, FALSE, FALSE));
5523 emitcode ("jnz", "%05d$", tlbl->key + 100);
5529 emitcode ("", "%05d$:", tlbl->key + 100);
5533 jmpTrueOrFalse (ifx, tlbl);
5536 for (; (size--); offset++)
5539 // result = left & right
5540 if (AOP_TYPE (right) == AOP_LIT)
5542 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5544 aopPut (AOP (result),
5545 aopGet (AOP (left), offset, FALSE, FALSE),
5547 isOperandVolatile (result, FALSE));
5551 // faster than result <- left, anl result,right
5552 // and better if result is SFR
5553 if (AOP_TYPE (left) == AOP_ACC)
5554 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5557 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5558 emitcode ("xrl", "a,%s",
5559 aopGet (AOP (left), offset, FALSE, TRUE));
5561 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5566 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5567 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5568 freeAsmop (result, NULL, ic, TRUE);
5571 /*-----------------------------------------------------------------*/
5572 /* genInline - write the inline code out */
5573 /*-----------------------------------------------------------------*/
5575 genInline (iCode * ic)
5577 char *buffer, *bp, *bp1;
5579 D(emitcode ("; genInline",""));
5581 _G.inLine += (!options.asmpeep);
5583 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5584 strcpy (buffer, IC_INLINE (ic));
5586 /* emit each line as a code */
5611 /* emitcode("",buffer); */
5612 _G.inLine -= (!options.asmpeep);
5615 /*-----------------------------------------------------------------*/
5616 /* genRRC - rotate right with carry */
5617 /*-----------------------------------------------------------------*/
5621 operand *left, *result;
5622 int size, offset = 0;
5625 D(emitcode ("; genRRC",""));
5627 /* rotate right with carry */
5628 left = IC_LEFT (ic);
5629 result = IC_RESULT (ic);
5630 aopOp (left, ic, FALSE);
5631 aopOp (result, ic, FALSE);
5633 /* move it to the result */
5634 size = AOP_SIZE (result);
5636 if (size == 1) { /* special case for 1 byte */
5637 l = aopGet (AOP (left), offset, FALSE, FALSE);
5639 emitcode ("rr", "a");
5645 l = aopGet (AOP (left), offset, FALSE, FALSE);
5647 emitcode ("rrc", "a");
5648 if (AOP_SIZE (result) > 1)
5649 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5651 /* now we need to put the carry into the
5652 highest order byte of the result */
5653 if (AOP_SIZE (result) > 1)
5655 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5658 emitcode ("mov", "acc.7,c");
5660 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5661 freeAsmop (left, NULL, ic, TRUE);
5662 freeAsmop (result, NULL, ic, TRUE);
5665 /*-----------------------------------------------------------------*/
5666 /* genRLC - generate code for rotate left with carry */
5667 /*-----------------------------------------------------------------*/
5671 operand *left, *result;
5672 int size, offset = 0;
5675 D(emitcode ("; genRLC",""));
5677 /* rotate right with carry */
5678 left = IC_LEFT (ic);
5679 result = IC_RESULT (ic);
5680 aopOp (left, ic, FALSE);
5681 aopOp (result, ic, FALSE);
5683 /* move it to the result */
5684 size = AOP_SIZE (result);
5688 l = aopGet (AOP (left), offset, FALSE, FALSE);
5690 if (size == 0) { /* special case for 1 byte */
5694 emitcode ("add", "a,acc");
5695 if (AOP_SIZE (result) > 1)
5696 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5699 l = aopGet (AOP (left), offset, FALSE, FALSE);
5701 emitcode ("rlc", "a");
5702 if (AOP_SIZE (result) > 1)
5703 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5706 /* now we need to put the carry into the
5707 highest order byte of the result */
5708 if (AOP_SIZE (result) > 1)
5710 l = aopGet (AOP (result), 0, FALSE, FALSE);
5713 emitcode ("mov", "acc.0,c");
5715 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5716 freeAsmop (left, NULL, ic, TRUE);
5717 freeAsmop (result, NULL, ic, TRUE);
5720 /*-----------------------------------------------------------------*/
5721 /* genGetHbit - generates code get highest order bit */
5722 /*-----------------------------------------------------------------*/
5724 genGetHbit (iCode * ic)
5726 operand *left, *result;
5728 D(emitcode ("; genGetHbit",""));
5730 left = IC_LEFT (ic);
5731 result = IC_RESULT (ic);
5732 aopOp (left, ic, FALSE);
5733 aopOp (result, ic, FALSE);
5735 /* get the highest order byte into a */
5736 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5737 if (AOP_TYPE (result) == AOP_CRY)
5739 emitcode ("rlc", "a");
5744 emitcode ("rl", "a");
5745 emitcode ("anl", "a,#0x01");
5750 freeAsmop (left, NULL, ic, TRUE);
5751 freeAsmop (result, NULL, ic, TRUE);
5754 /*-----------------------------------------------------------------*/
5755 /* AccRol - rotate left accumulator by known count */
5756 /*-----------------------------------------------------------------*/
5758 AccRol (int shCount)
5760 shCount &= 0x0007; // shCount : 0..7
5767 emitcode ("rl", "a");
5770 emitcode ("rl", "a");
5771 emitcode ("rl", "a");
5774 emitcode ("swap", "a");
5775 emitcode ("rr", "a");
5778 emitcode ("swap", "a");
5781 emitcode ("swap", "a");
5782 emitcode ("rl", "a");
5785 emitcode ("rr", "a");
5786 emitcode ("rr", "a");
5789 emitcode ("rr", "a");
5794 /*-----------------------------------------------------------------*/
5795 /* AccLsh - left shift accumulator by known count */
5796 /*-----------------------------------------------------------------*/
5798 AccLsh (int shCount)
5803 emitcode ("add", "a,acc");
5804 else if (shCount == 2)
5806 emitcode ("add", "a,acc");
5807 emitcode ("add", "a,acc");
5811 /* rotate left accumulator */
5813 /* and kill the lower order bits */
5814 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5819 /*-----------------------------------------------------------------*/
5820 /* AccRsh - right shift accumulator by known count */
5821 /*-----------------------------------------------------------------*/
5823 AccRsh (int shCount)
5830 emitcode ("rrc", "a");
5834 /* rotate right accumulator */
5835 AccRol (8 - shCount);
5836 /* and kill the higher order bits */
5837 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5842 /*-----------------------------------------------------------------*/
5843 /* AccSRsh - signed right shift accumulator by known count */
5844 /*-----------------------------------------------------------------*/
5846 AccSRsh (int shCount)
5853 emitcode ("mov", "c,acc.7");
5854 emitcode ("rrc", "a");
5856 else if (shCount == 2)
5858 emitcode ("mov", "c,acc.7");
5859 emitcode ("rrc", "a");
5860 emitcode ("mov", "c,acc.7");
5861 emitcode ("rrc", "a");
5865 tlbl = newiTempLabel (NULL);
5866 /* rotate right accumulator */
5867 AccRol (8 - shCount);
5868 /* and kill the higher order bits */
5869 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5870 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5871 emitcode ("orl", "a,#0x%02x",
5872 (unsigned char) ~SRMask[shCount]);
5873 emitcode ("", "%05d$:", tlbl->key + 100);
5878 /*-----------------------------------------------------------------*/
5879 /* shiftR1Left2Result - shift right one byte from left to result */
5880 /*-----------------------------------------------------------------*/
5882 shiftR1Left2Result (operand * left, int offl,
5883 operand * result, int offr,
5884 int shCount, int sign)
5886 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5887 /* shift right accumulator */
5892 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5895 /*-----------------------------------------------------------------*/
5896 /* shiftL1Left2Result - shift left one byte from left to result */
5897 /*-----------------------------------------------------------------*/
5899 shiftL1Left2Result (operand * left, int offl,
5900 operand * result, int offr, int shCount)
5903 l = aopGet (AOP (left), offl, FALSE, FALSE);
5905 /* shift left accumulator */
5907 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5910 /*-----------------------------------------------------------------*/
5911 /* movLeft2Result - move byte from left to result */
5912 /*-----------------------------------------------------------------*/
5914 movLeft2Result (operand * left, int offl,
5915 operand * result, int offr, int sign)
5918 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5920 l = aopGet (AOP (left), offl, FALSE, FALSE);
5922 if (*l == '@' && (IS_AOP_PREG (result)))
5924 emitcode ("mov", "a,%s", l);
5925 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5930 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
5933 /* MSB sign in acc.7 ! */
5934 if (getDataSize (left) == offl + 1)
5936 emitcode ("mov", "a,%s", l);
5937 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5944 /*-----------------------------------------------------------------*/
5945 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5946 /*-----------------------------------------------------------------*/
5950 emitcode ("rrc", "a");
5951 emitcode ("xch", "a,%s", x);
5952 emitcode ("rrc", "a");
5953 emitcode ("xch", "a,%s", x);
5956 /*-----------------------------------------------------------------*/
5957 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5958 /*-----------------------------------------------------------------*/
5962 emitcode ("xch", "a,%s", x);
5963 emitcode ("rlc", "a");
5964 emitcode ("xch", "a,%s", x);
5965 emitcode ("rlc", "a");
5968 /*-----------------------------------------------------------------*/
5969 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5970 /*-----------------------------------------------------------------*/
5974 emitcode ("xch", "a,%s", x);
5975 emitcode ("add", "a,acc");
5976 emitcode ("xch", "a,%s", x);
5977 emitcode ("rlc", "a");
5980 /*-----------------------------------------------------------------*/
5981 /* AccAXLsh - left shift a:x by known count (0..7) */
5982 /*-----------------------------------------------------------------*/
5984 AccAXLsh (char *x, int shCount)
5999 case 5: // AAAAABBB:CCCCCDDD
6001 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6003 emitcode ("anl", "a,#0x%02x",
6004 SLMask[shCount]); // BBB00000:CCCCCDDD
6006 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6008 AccRol (shCount); // DDDCCCCC:BBB00000
6010 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6012 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6014 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6016 emitcode ("anl", "a,#0x%02x",
6017 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6019 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6021 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6024 case 6: // AAAAAABB:CCCCCCDD
6025 emitcode ("anl", "a,#0x%02x",
6026 SRMask[shCount]); // 000000BB:CCCCCCDD
6027 emitcode ("mov", "c,acc.0"); // c = B
6028 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6030 AccAXRrl1 (x); // BCCCCCCD:D000000B
6031 AccAXRrl1 (x); // BBCCCCCC:DD000000
6033 emitcode("rrc","a");
6034 emitcode("xch","a,%s", x);
6035 emitcode("rrc","a");
6036 emitcode("mov","c,acc.0"); //<< get correct bit
6037 emitcode("xch","a,%s", x);
6039 emitcode("rrc","a");
6040 emitcode("xch","a,%s", x);
6041 emitcode("rrc","a");
6042 emitcode("xch","a,%s", x);
6045 case 7: // a:x <<= 7
6047 emitcode ("anl", "a,#0x%02x",
6048 SRMask[shCount]); // 0000000B:CCCCCCCD
6050 emitcode ("mov", "c,acc.0"); // c = B
6052 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6054 AccAXRrl1 (x); // BCCCCCCC:D0000000
6062 /*-----------------------------------------------------------------*/
6063 /* AccAXRsh - right shift a:x known count (0..7) */
6064 /*-----------------------------------------------------------------*/
6066 AccAXRsh (char *x, int shCount)
6074 AccAXRrl1 (x); // 0->a:x
6079 AccAXRrl1 (x); // 0->a:x
6082 AccAXRrl1 (x); // 0->a:x
6087 case 5: // AAAAABBB:CCCCCDDD = a:x
6089 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6091 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6093 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6095 emitcode ("anl", "a,#0x%02x",
6096 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6098 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6100 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6102 emitcode ("anl", "a,#0x%02x",
6103 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6105 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6107 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6109 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6112 case 6: // AABBBBBB:CCDDDDDD
6114 emitcode ("mov", "c,acc.7");
6115 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6117 emitcode ("mov", "c,acc.7");
6118 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6120 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6122 emitcode ("anl", "a,#0x%02x",
6123 SRMask[shCount]); // 000000AA:BBBBBBCC
6126 case 7: // ABBBBBBB:CDDDDDDD
6128 emitcode ("mov", "c,acc.7"); // c = A
6130 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6132 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6134 emitcode ("anl", "a,#0x%02x",
6135 SRMask[shCount]); // 0000000A:BBBBBBBC
6143 /*-----------------------------------------------------------------*/
6144 /* AccAXRshS - right shift signed a:x known count (0..7) */
6145 /*-----------------------------------------------------------------*/
6147 AccAXRshS (char *x, int shCount)
6155 emitcode ("mov", "c,acc.7");
6156 AccAXRrl1 (x); // s->a:x
6160 emitcode ("mov", "c,acc.7");
6161 AccAXRrl1 (x); // s->a:x
6163 emitcode ("mov", "c,acc.7");
6164 AccAXRrl1 (x); // s->a:x
6169 case 5: // AAAAABBB:CCCCCDDD = a:x
6171 tlbl = newiTempLabel (NULL);
6172 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6174 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6176 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6178 emitcode ("anl", "a,#0x%02x",
6179 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6181 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6183 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6185 emitcode ("anl", "a,#0x%02x",
6186 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6188 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6190 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6192 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6194 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6195 emitcode ("orl", "a,#0x%02x",
6196 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6198 emitcode ("", "%05d$:", tlbl->key + 100);
6199 break; // SSSSAAAA:BBBCCCCC
6201 case 6: // AABBBBBB:CCDDDDDD
6203 tlbl = newiTempLabel (NULL);
6204 emitcode ("mov", "c,acc.7");
6205 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6207 emitcode ("mov", "c,acc.7");
6208 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6210 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6212 emitcode ("anl", "a,#0x%02x",
6213 SRMask[shCount]); // 000000AA:BBBBBBCC
6215 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6216 emitcode ("orl", "a,#0x%02x",
6217 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6219 emitcode ("", "%05d$:", tlbl->key + 100);
6221 case 7: // ABBBBBBB:CDDDDDDD
6223 tlbl = newiTempLabel (NULL);
6224 emitcode ("mov", "c,acc.7"); // c = A
6226 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6228 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6230 emitcode ("anl", "a,#0x%02x",
6231 SRMask[shCount]); // 0000000A:BBBBBBBC
6233 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6234 emitcode ("orl", "a,#0x%02x",
6235 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6237 emitcode ("", "%05d$:", tlbl->key + 100);
6244 /*-----------------------------------------------------------------*/
6245 /* shiftL2Left2Result - shift left two bytes from left to result */
6246 /*-----------------------------------------------------------------*/
6248 shiftL2Left2Result (operand * left, int offl,
6249 operand * result, int offr, int shCount)
6251 if (sameRegs (AOP (result), AOP (left)) &&
6252 ((offl + MSB16) == offr))
6254 /* don't crash result[offr] */
6255 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6256 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6260 movLeft2Result (left, offl, result, offr, 0);
6261 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6263 /* ax << shCount (x = lsb(result)) */
6264 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6265 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6269 /*-----------------------------------------------------------------*/
6270 /* shiftR2Left2Result - shift right two bytes from left to result */
6271 /*-----------------------------------------------------------------*/
6273 shiftR2Left2Result (operand * left, int offl,
6274 operand * result, int offr,
6275 int shCount, int sign)
6277 if (sameRegs (AOP (result), AOP (left)) &&
6278 ((offl + MSB16) == offr))
6280 /* don't crash result[offr] */
6281 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6282 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6286 movLeft2Result (left, offl, result, offr, 0);
6287 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6289 /* a:x >> shCount (x = lsb(result)) */
6291 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6293 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6294 if (getDataSize (result) > 1)
6295 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6298 /*-----------------------------------------------------------------*/
6299 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6300 /*-----------------------------------------------------------------*/
6302 shiftLLeftOrResult (operand * left, int offl,
6303 operand * result, int offr, int shCount)
6305 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6306 /* shift left accumulator */
6308 /* or with result */
6309 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6310 /* back to result */
6311 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6314 /*-----------------------------------------------------------------*/
6315 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6316 /*-----------------------------------------------------------------*/
6318 shiftRLeftOrResult (operand * left, int offl,
6319 operand * result, int offr, int shCount)
6321 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6322 /* shift right accumulator */
6324 /* or with result */
6325 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6326 /* back to result */
6327 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6330 /*-----------------------------------------------------------------*/
6331 /* genlshOne - left shift a one byte quantity by known count */
6332 /*-----------------------------------------------------------------*/
6334 genlshOne (operand * result, operand * left, int shCount)
6336 D(emitcode ("; genlshOne",""));
6338 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6341 /*-----------------------------------------------------------------*/
6342 /* genlshTwo - left shift two bytes by known amount != 0 */
6343 /*-----------------------------------------------------------------*/
6345 genlshTwo (operand * result, operand * left, int shCount)
6349 D(emitcode ("; genlshTwo",""));
6351 size = getDataSize (result);
6353 /* if shCount >= 8 */
6361 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6363 movLeft2Result (left, LSB, result, MSB16, 0);
6365 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6368 /* 1 <= shCount <= 7 */
6372 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6374 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6378 /*-----------------------------------------------------------------*/
6379 /* shiftLLong - shift left one long from left to result */
6380 /* offl = LSB or MSB16 */
6381 /*-----------------------------------------------------------------*/
6383 shiftLLong (operand * left, operand * result, int offr)
6386 int size = AOP_SIZE (result);
6388 if (size >= LSB + offr)
6390 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6392 emitcode ("add", "a,acc");
6393 if (sameRegs (AOP (left), AOP (result)) &&
6394 size >= MSB16 + offr && offr != LSB)
6395 emitcode ("xch", "a,%s",
6396 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6398 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6401 if (size >= MSB16 + offr)
6403 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6405 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6408 emitcode ("rlc", "a");
6409 if (sameRegs (AOP (left), AOP (result)) &&
6410 size >= MSB24 + offr && offr != LSB)
6411 emitcode ("xch", "a,%s",
6412 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6414 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6417 if (size >= MSB24 + offr)
6419 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6421 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6424 emitcode ("rlc", "a");
6425 if (sameRegs (AOP (left), AOP (result)) &&
6426 size >= MSB32 + offr && offr != LSB)
6427 emitcode ("xch", "a,%s",
6428 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6430 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6433 if (size > MSB32 + offr)
6435 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6437 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6440 emitcode ("rlc", "a");
6441 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6444 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6447 /*-----------------------------------------------------------------*/
6448 /* genlshFour - shift four byte by a known amount != 0 */
6449 /*-----------------------------------------------------------------*/
6451 genlshFour (operand * result, operand * left, int shCount)
6455 D(emitcode ("; genlshFour",""));
6457 size = AOP_SIZE (result);
6459 /* if shifting more that 3 bytes */
6464 /* lowest order of left goes to the highest
6465 order of the destination */
6466 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6468 movLeft2Result (left, LSB, result, MSB32, 0);
6469 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6470 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6471 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6475 /* more than two bytes */
6476 else if (shCount >= 16)
6478 /* lower order two bytes goes to higher order two bytes */
6480 /* if some more remaining */
6482 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6485 movLeft2Result (left, MSB16, result, MSB32, 0);
6486 movLeft2Result (left, LSB, result, MSB24, 0);
6488 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6489 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6493 /* if more than 1 byte */
6494 else if (shCount >= 8)
6496 /* lower order three bytes goes to higher order three bytes */
6501 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6503 movLeft2Result (left, LSB, result, MSB16, 0);
6509 movLeft2Result (left, MSB24, result, MSB32, 0);
6510 movLeft2Result (left, MSB16, result, MSB24, 0);
6511 movLeft2Result (left, LSB, result, MSB16, 0);
6512 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6514 else if (shCount == 1)
6515 shiftLLong (left, result, MSB16);
6518 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6519 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6520 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6521 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6526 /* 1 <= shCount <= 7 */
6527 else if (shCount <= 2)
6529 shiftLLong (left, result, LSB);
6531 shiftLLong (result, result, LSB);
6533 /* 3 <= shCount <= 7, optimize */
6536 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6537 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6538 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6542 /*-----------------------------------------------------------------*/
6543 /* genLeftShiftLiteral - left shifting by known count */
6544 /*-----------------------------------------------------------------*/
6546 genLeftShiftLiteral (operand * left,
6551 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6554 D(emitcode ("; genLeftShiftLiteral",""));
6556 freeAsmop (right, NULL, ic, TRUE);
6558 aopOp (left, ic, FALSE);
6559 aopOp (result, ic, FALSE);
6561 size = getSize (operandType (result));
6564 emitcode ("; shift left ", "result %d, left %d", size,
6568 /* I suppose that the left size >= result size */
6573 movLeft2Result (left, size, result, size, 0);
6577 else if (shCount >= (size * 8))
6579 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6585 genlshOne (result, left, shCount);
6589 genlshTwo (result, left, shCount);
6593 genlshFour (result, left, shCount);
6596 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6597 "*** ack! mystery literal shift!\n");
6601 freeAsmop (left, NULL, ic, TRUE);
6602 freeAsmop (result, NULL, ic, TRUE);
6605 /*-----------------------------------------------------------------*/
6606 /* genLeftShift - generates code for left shifting */
6607 /*-----------------------------------------------------------------*/
6609 genLeftShift (iCode * ic)
6611 operand *left, *right, *result;
6614 symbol *tlbl, *tlbl1;
6616 D(emitcode ("; genLeftShift",""));
6618 right = IC_RIGHT (ic);
6619 left = IC_LEFT (ic);
6620 result = IC_RESULT (ic);
6622 aopOp (right, ic, FALSE);
6624 /* if the shift count is known then do it
6625 as efficiently as possible */
6626 if (AOP_TYPE (right) == AOP_LIT)
6628 genLeftShiftLiteral (left, right, result, ic);
6632 /* shift count is unknown then we have to form
6633 a loop get the loop count in B : Note: we take
6634 only the lower order byte since shifting
6635 more that 32 bits make no sense anyway, ( the
6636 largest size of an object can be only 32 bits ) */
6638 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6639 emitcode ("inc", "b");
6640 freeAsmop (right, NULL, ic, TRUE);
6641 aopOp (left, ic, FALSE);
6642 aopOp (result, ic, FALSE);
6644 /* now move the left to the result if they are not the
6646 if (!sameRegs (AOP (left), AOP (result)) &&
6647 AOP_SIZE (result) > 1)
6650 size = AOP_SIZE (result);
6654 l = aopGet (AOP (left), offset, FALSE, TRUE);
6655 if (*l == '@' && (IS_AOP_PREG (result)))
6658 emitcode ("mov", "a,%s", l);
6659 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6662 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6667 tlbl = newiTempLabel (NULL);
6668 size = AOP_SIZE (result);
6670 tlbl1 = newiTempLabel (NULL);
6672 /* if it is only one byte then */
6675 symbol *tlbl1 = newiTempLabel (NULL);
6677 l = aopGet (AOP (left), 0, FALSE, FALSE);
6679 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6680 emitcode ("", "%05d$:", tlbl->key + 100);
6681 emitcode ("add", "a,acc");
6682 emitcode ("", "%05d$:", tlbl1->key + 100);
6683 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6684 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6688 reAdjustPreg (AOP (result));
6690 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6691 emitcode ("", "%05d$:", tlbl->key + 100);
6692 l = aopGet (AOP (result), offset, FALSE, FALSE);
6694 emitcode ("add", "a,acc");
6695 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6698 l = aopGet (AOP (result), offset, FALSE, FALSE);
6700 emitcode ("rlc", "a");
6701 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6703 reAdjustPreg (AOP (result));
6705 emitcode ("", "%05d$:", tlbl1->key + 100);
6706 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6708 freeAsmop (left, NULL, ic, TRUE);
6709 freeAsmop (result, NULL, ic, TRUE);
6712 /*-----------------------------------------------------------------*/
6713 /* genrshOne - right shift a one byte quantity by known count */
6714 /*-----------------------------------------------------------------*/
6716 genrshOne (operand * result, operand * left,
6717 int shCount, int sign)
6719 D(emitcode ("; genrshOne",""));
6721 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6724 /*-----------------------------------------------------------------*/
6725 /* genrshTwo - right shift two bytes by known amount != 0 */
6726 /*-----------------------------------------------------------------*/
6728 genrshTwo (operand * result, operand * left,
6729 int shCount, int sign)
6731 D(emitcode ("; genrshTwo",""));
6733 /* if shCount >= 8 */
6738 shiftR1Left2Result (left, MSB16, result, LSB,
6741 movLeft2Result (left, MSB16, result, LSB, sign);
6742 addSign (result, MSB16, sign);
6745 /* 1 <= shCount <= 7 */
6747 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6750 /*-----------------------------------------------------------------*/
6751 /* shiftRLong - shift right one long from left to result */
6752 /* offl = LSB or MSB16 */
6753 /*-----------------------------------------------------------------*/
6755 shiftRLong (operand * left, int offl,
6756 operand * result, int sign)
6758 int isSameRegs=sameRegs(AOP(left),AOP(result));
6760 if (isSameRegs && offl>1) {
6761 // we are in big trouble, but this shouldn't happen
6762 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6765 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6770 emitcode ("rlc", "a");
6771 emitcode ("subb", "a,acc");
6773 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6775 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6776 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6779 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6784 emitcode ("clr", "c");
6786 emitcode ("mov", "c,acc.7");
6789 emitcode ("rrc", "a");
6791 if (isSameRegs && offl==MSB16) {
6792 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6794 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6795 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6798 emitcode ("rrc", "a");
6799 if (isSameRegs && offl==1) {
6800 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6802 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6803 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6805 emitcode ("rrc", "a");
6806 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6810 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6811 emitcode ("rrc", "a");
6812 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6816 /*-----------------------------------------------------------------*/
6817 /* genrshFour - shift four byte by a known amount != 0 */
6818 /*-----------------------------------------------------------------*/
6820 genrshFour (operand * result, operand * left,
6821 int shCount, int sign)
6823 D(emitcode ("; genrshFour",""));
6825 /* if shifting more that 3 bytes */
6830 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6832 movLeft2Result (left, MSB32, result, LSB, sign);
6833 addSign (result, MSB16, sign);
6835 else if (shCount >= 16)
6839 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6842 movLeft2Result (left, MSB24, result, LSB, 0);
6843 movLeft2Result (left, MSB32, result, MSB16, sign);
6845 addSign (result, MSB24, sign);
6847 else if (shCount >= 8)
6851 shiftRLong (left, MSB16, result, sign);
6852 else if (shCount == 0)
6854 movLeft2Result (left, MSB16, result, LSB, 0);
6855 movLeft2Result (left, MSB24, result, MSB16, 0);
6856 movLeft2Result (left, MSB32, result, MSB24, sign);
6857 addSign (result, MSB32, sign);
6861 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6862 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6863 /* the last shift is signed */
6864 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6865 addSign (result, MSB32, sign);
6869 { /* 1 <= shCount <= 7 */
6872 shiftRLong (left, LSB, result, sign);
6874 shiftRLong (result, LSB, result, sign);
6878 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6879 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6880 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6885 /*-----------------------------------------------------------------*/
6886 /* genRightShiftLiteral - right shifting by known count */
6887 /*-----------------------------------------------------------------*/
6889 genRightShiftLiteral (operand * left,
6895 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6898 D(emitcode ("; genRightShiftLiteral",""));
6900 freeAsmop (right, NULL, ic, TRUE);
6902 aopOp (left, ic, FALSE);
6903 aopOp (result, ic, FALSE);
6906 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6910 size = getDataSize (left);
6911 /* test the LEFT size !!! */
6913 /* I suppose that the left size >= result size */
6916 size = getDataSize (result);
6918 movLeft2Result (left, size, result, size, 0);
6921 else if (shCount >= (size * 8))
6924 /* get sign in acc.7 */
6925 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6927 addSign (result, LSB, sign);
6934 genrshOne (result, left, shCount, sign);
6938 genrshTwo (result, left, shCount, sign);
6942 genrshFour (result, left, shCount, sign);
6948 freeAsmop (left, NULL, ic, TRUE);
6949 freeAsmop (result, NULL, ic, TRUE);
6952 /*-----------------------------------------------------------------*/
6953 /* genSignedRightShift - right shift of signed number */
6954 /*-----------------------------------------------------------------*/
6956 genSignedRightShift (iCode * ic)
6958 operand *right, *left, *result;
6961 symbol *tlbl, *tlbl1;
6963 D(emitcode ("; genSignedRightShift",""));
6965 /* we do it the hard way put the shift count in b
6966 and loop thru preserving the sign */
6968 right = IC_RIGHT (ic);
6969 left = IC_LEFT (ic);
6970 result = IC_RESULT (ic);
6972 aopOp (right, ic, FALSE);
6975 if (AOP_TYPE (right) == AOP_LIT)
6977 genRightShiftLiteral (left, right, result, ic, 1);
6980 /* shift count is unknown then we have to form
6981 a loop get the loop count in B : Note: we take
6982 only the lower order byte since shifting
6983 more that 32 bits make no sense anyway, ( the
6984 largest size of an object can be only 32 bits ) */
6986 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6987 emitcode ("inc", "b");
6988 freeAsmop (right, NULL, ic, TRUE);
6989 aopOp (left, ic, FALSE);
6990 aopOp (result, ic, FALSE);
6992 /* now move the left to the result if they are not the
6994 if (!sameRegs (AOP (left), AOP (result)) &&
6995 AOP_SIZE (result) > 1)
6998 size = AOP_SIZE (result);
7002 l = aopGet (AOP (left), offset, FALSE, TRUE);
7003 if (*l == '@' && IS_AOP_PREG (result))
7006 emitcode ("mov", "a,%s", l);
7007 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7010 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7015 /* mov the highest order bit to OVR */
7016 tlbl = newiTempLabel (NULL);
7017 tlbl1 = newiTempLabel (NULL);
7019 size = AOP_SIZE (result);
7021 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7022 emitcode ("rlc", "a");
7023 emitcode ("mov", "ov,c");
7024 /* if it is only one byte then */
7027 l = aopGet (AOP (left), 0, FALSE, FALSE);
7029 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7030 emitcode ("", "%05d$:", tlbl->key + 100);
7031 emitcode ("mov", "c,ov");
7032 emitcode ("rrc", "a");
7033 emitcode ("", "%05d$:", tlbl1->key + 100);
7034 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7035 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7039 reAdjustPreg (AOP (result));
7040 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7041 emitcode ("", "%05d$:", tlbl->key + 100);
7042 emitcode ("mov", "c,ov");
7045 l = aopGet (AOP (result), offset, FALSE, FALSE);
7047 emitcode ("rrc", "a");
7048 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7050 reAdjustPreg (AOP (result));
7051 emitcode ("", "%05d$:", tlbl1->key + 100);
7052 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7055 freeAsmop (left, NULL, ic, TRUE);
7056 freeAsmop (result, NULL, ic, TRUE);
7059 /*-----------------------------------------------------------------*/
7060 /* genRightShift - generate code for right shifting */
7061 /*-----------------------------------------------------------------*/
7063 genRightShift (iCode * ic)
7065 operand *right, *left, *result;
7069 symbol *tlbl, *tlbl1;
7071 D(emitcode ("; genRightShift",""));
7073 /* if signed then we do it the hard way preserve the
7074 sign bit moving it inwards */
7075 retype = getSpec (operandType (IC_RESULT (ic)));
7077 if (!SPEC_USIGN (retype))
7079 genSignedRightShift (ic);
7083 /* signed & unsigned types are treated the same : i.e. the
7084 signed is NOT propagated inwards : quoting from the
7085 ANSI - standard : "for E1 >> E2, is equivalent to division
7086 by 2**E2 if unsigned or if it has a non-negative value,
7087 otherwise the result is implementation defined ", MY definition
7088 is that the sign does not get propagated */
7090 right = IC_RIGHT (ic);
7091 left = IC_LEFT (ic);
7092 result = IC_RESULT (ic);
7094 aopOp (right, ic, FALSE);
7096 /* if the shift count is known then do it
7097 as efficiently as possible */
7098 if (AOP_TYPE (right) == AOP_LIT)
7100 genRightShiftLiteral (left, right, result, ic, 0);
7104 /* shift count is unknown then we have to form
7105 a loop get the loop count in B : Note: we take
7106 only the lower order byte since shifting
7107 more that 32 bits make no sense anyway, ( the
7108 largest size of an object can be only 32 bits ) */
7110 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7111 emitcode ("inc", "b");
7112 freeAsmop (right, NULL, ic, TRUE);
7113 aopOp (left, ic, FALSE);
7114 aopOp (result, ic, FALSE);
7116 /* now move the left to the result if they are not the
7118 if (!sameRegs (AOP (left), AOP (result)) &&
7119 AOP_SIZE (result) > 1)
7122 size = AOP_SIZE (result);
7126 l = aopGet (AOP (left), offset, FALSE, TRUE);
7127 if (*l == '@' && IS_AOP_PREG (result))
7130 emitcode ("mov", "a,%s", l);
7131 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7134 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7139 tlbl = newiTempLabel (NULL);
7140 tlbl1 = newiTempLabel (NULL);
7141 size = AOP_SIZE (result);
7144 /* if it is only one byte then */
7147 l = aopGet (AOP (left), 0, FALSE, FALSE);
7149 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7150 emitcode ("", "%05d$:", tlbl->key + 100);
7152 emitcode ("rrc", "a");
7153 emitcode ("", "%05d$:", tlbl1->key + 100);
7154 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7155 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7159 reAdjustPreg (AOP (result));
7160 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7161 emitcode ("", "%05d$:", tlbl->key + 100);
7165 l = aopGet (AOP (result), offset, FALSE, FALSE);
7167 emitcode ("rrc", "a");
7168 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7170 reAdjustPreg (AOP (result));
7172 emitcode ("", "%05d$:", tlbl1->key + 100);
7173 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7176 freeAsmop (left, NULL, ic, TRUE);
7177 freeAsmop (result, NULL, ic, TRUE);
7180 /*-----------------------------------------------------------------*/
7181 /* emitPtrByteGet - emits code to get a byte into A through a */
7182 /* pointer register (R0, R1, or DPTR). The */
7183 /* original value of A can be preserved in B. */
7184 /*-----------------------------------------------------------------*/
7186 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7193 emitcode ("mov", "b,a");
7194 emitcode ("mov", "a,@%s", rname);
7199 emitcode ("mov", "b,a");
7200 emitcode ("movx", "a,@%s", rname);
7205 emitcode ("mov", "b,a");
7206 emitcode ("movx", "a,@dptr");
7211 emitcode ("mov", "b,a");
7212 emitcode ("clr", "a");
7213 emitcode ("movc", "a,@a+dptr");
7219 emitcode ("push", "b");
7220 emitcode ("push", "acc");
7222 emitcode ("lcall", "__gptrget");
7224 emitcode ("pop", "b");
7229 /*-----------------------------------------------------------------*/
7230 /* emitPtrByteSet - emits code to set a byte from src through a */
7231 /* pointer register (R0, R1, or DPTR). */
7232 /*-----------------------------------------------------------------*/
7234 emitPtrByteSet (char *rname, int p_type, char *src)
7243 emitcode ("mov", "@%s,a", rname);
7246 emitcode ("mov", "@%s,%s", rname, src);
7251 emitcode ("movx", "@%s,a", rname);
7256 emitcode ("movx", "@dptr,a");
7261 emitcode ("lcall", "__gptrput");
7266 /*-----------------------------------------------------------------*/
7267 /* genUnpackBits - generates code for unpacking bits */
7268 /*-----------------------------------------------------------------*/
7270 genUnpackBits (operand * result, char *rname, int ptype)
7272 int offset = 0; /* result byte offset */
7273 int rsize; /* result size */
7274 int rlen = 0; /* remaining bitfield length */
7275 sym_link *etype; /* bitfield type information */
7276 int blen; /* bitfield length */
7277 int bstr; /* bitfield starting bit within byte */
7279 D(emitcode ("; genUnpackBits",""));
7281 etype = getSpec (operandType (result));
7282 rsize = getSize (operandType (result));
7283 blen = SPEC_BLEN (etype);
7284 bstr = SPEC_BSTR (etype);
7286 /* If the bitfield length is less than a byte */
7289 emitPtrByteGet (rname, ptype, FALSE);
7291 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7292 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7296 /* Bit field did not fit in a byte. Copy all
7297 but the partial byte at the end. */
7298 for (rlen=blen;rlen>=8;rlen-=8)
7300 emitPtrByteGet (rname, ptype, FALSE);
7301 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7303 emitcode ("inc", "%s", rname);
7306 /* Handle the partial byte at the end */
7309 emitPtrByteGet (rname, ptype, FALSE);
7310 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7311 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7319 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7324 /*-----------------------------------------------------------------*/
7325 /* genDataPointerGet - generates code when ptr offset is known */
7326 /*-----------------------------------------------------------------*/
7328 genDataPointerGet (operand * left,
7334 int size, offset = 0;
7336 D(emitcode ("; genDataPointerGet",""));
7338 aopOp (result, ic, TRUE);
7340 /* get the string representation of the name */
7341 l = aopGet (AOP (left), 0, FALSE, TRUE);
7342 size = AOP_SIZE (result);
7346 sprintf (buffer, "(%s + %d)", l + 1, offset);
7348 sprintf (buffer, "%s", l + 1);
7349 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7352 freeAsmop (left, NULL, ic, TRUE);
7353 freeAsmop (result, NULL, ic, TRUE);
7356 /*-----------------------------------------------------------------*/
7357 /* genNearPointerGet - emitcode for near pointer fetch */
7358 /*-----------------------------------------------------------------*/
7360 genNearPointerGet (operand * left,
7368 sym_link *rtype, *retype;
7369 sym_link *ltype = operandType (left);
7372 D(emitcode ("; genNearPointerGet",""));
7374 rtype = operandType (result);
7375 retype = getSpec (rtype);
7377 aopOp (left, ic, FALSE);
7379 /* if left is rematerialisable and
7380 result is not bit variable type and
7381 the left is pointer to data space i.e
7382 lower 128 bytes of space */
7383 if (AOP_TYPE (left) == AOP_IMMD &&
7384 !IS_BITVAR (retype) &&
7385 DCL_TYPE (ltype) == POINTER)
7387 genDataPointerGet (left, result, ic);
7391 /* if the value is already in a pointer register
7392 then don't need anything more */
7393 if (!AOP_INPREG (AOP (left)))
7395 if (IS_AOP_PREG (left))
7397 // Aha, it is a pointer, just in disguise.
7398 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7401 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7402 __FILE__, __LINE__);
7407 emitcode ("mov", "a%s,%s", rname + 1, rname);
7408 rname++; // skip the '@'.
7413 /* otherwise get a free pointer register */
7415 preg = getFreePtr (ic, &aop, FALSE);
7416 emitcode ("mov", "%s,%s",
7418 aopGet (AOP (left), 0, FALSE, TRUE));
7423 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7425 //aopOp (result, ic, FALSE);
7426 aopOp (result, ic, result?TRUE:FALSE);
7428 /* if bitfield then unpack the bits */
7429 if (IS_BITVAR (retype))
7430 genUnpackBits (result, rname, POINTER);
7433 /* we have can just get the values */
7434 int size = AOP_SIZE (result);
7439 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7442 emitcode ("mov", "a,@%s", rname);
7443 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7447 sprintf (buffer, "@%s", rname);
7448 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7452 emitcode ("inc", "%s", rname);
7456 /* now some housekeeping stuff */
7457 if (aop) /* we had to allocate for this iCode */
7459 if (pi) { /* post increment present */
7460 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7462 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7466 /* we did not allocate which means left
7467 already in a pointer register, then
7468 if size > 0 && this could be used again
7469 we have to point it back to where it
7471 if ((AOP_SIZE (result) > 1 &&
7472 !OP_SYMBOL (left)->remat &&
7473 (OP_SYMBOL (left)->liveTo > ic->seq ||
7477 int size = AOP_SIZE (result) - 1;
7479 emitcode ("dec", "%s", rname);
7484 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7485 freeAsmop (left, NULL, ic, TRUE);
7486 if (pi) pi->generated = 1;
7489 /*-----------------------------------------------------------------*/
7490 /* genPagedPointerGet - emitcode for paged pointer fetch */
7491 /*-----------------------------------------------------------------*/
7493 genPagedPointerGet (operand * left,
7501 sym_link *rtype, *retype;
7503 D(emitcode ("; genPagedPointerGet",""));
7505 rtype = operandType (result);
7506 retype = getSpec (rtype);
7508 aopOp (left, ic, FALSE);
7510 /* if the value is already in a pointer register
7511 then don't need anything more */
7512 if (!AOP_INPREG (AOP (left)))
7514 /* otherwise get a free pointer register */
7516 preg = getFreePtr (ic, &aop, FALSE);
7517 emitcode ("mov", "%s,%s",
7519 aopGet (AOP (left), 0, FALSE, TRUE));
7523 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7525 aopOp (result, ic, FALSE);
7527 /* if bitfield then unpack the bits */
7528 if (IS_BITVAR (retype))
7529 genUnpackBits (result, rname, PPOINTER);
7532 /* we have can just get the values */
7533 int size = AOP_SIZE (result);
7539 emitcode ("movx", "a,@%s", rname);
7540 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7545 emitcode ("inc", "%s", rname);
7549 /* now some housekeeping stuff */
7550 if (aop) /* we had to allocate for this iCode */
7552 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7553 freeAsmop (NULL, aop, ic, TRUE);
7557 /* we did not allocate which means left
7558 already in a pointer register, then
7559 if size > 0 && this could be used again
7560 we have to point it back to where it
7562 if ((AOP_SIZE (result) > 1 &&
7563 !OP_SYMBOL (left)->remat &&
7564 (OP_SYMBOL (left)->liveTo > ic->seq ||
7568 int size = AOP_SIZE (result) - 1;
7570 emitcode ("dec", "%s", rname);
7575 freeAsmop (left, NULL, ic, TRUE);
7576 freeAsmop (result, NULL, ic, TRUE);
7577 if (pi) pi->generated = 1;
7581 /*--------------------------------------------------------------------*/
7582 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7583 /*--------------------------------------------------------------------*/
7585 loadDptrFromOperand (operand *op, bool loadBToo)
7587 if (AOP_TYPE (op) != AOP_STR)
7589 /* if this is remateriazable */
7590 if (AOP_TYPE (op) == AOP_IMMD)
7592 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7595 if (AOP(op)->aopu.aop_immd.from_cast_remat)
7596 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7599 wassertl(FALSE, "need pointerCode");
7600 emitcode ("", "; mov b,???");
7601 /* genPointerGet and genPointerSet originally did different
7602 ** things for this case. Both seem wrong.
7603 ** from genPointerGet:
7604 ** emitcode ("mov", "b,#%d", pointerCode (retype));
7605 ** from genPointerSet:
7606 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7611 else if (AOP_TYPE (op) == AOP_DPTR)
7615 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7616 emitcode ("push", "acc");
7617 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7618 emitcode ("push", "acc");
7619 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7620 emitcode ("pop", "dph");
7621 emitcode ("pop", "dpl");
7625 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7626 emitcode ("push", "acc");
7627 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7628 emitcode ("pop", "dpl");
7632 { /* we need to get it byte by byte */
7633 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7634 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7636 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7641 /*-----------------------------------------------------------------*/
7642 /* genFarPointerGet - gget value from far space */
7643 /*-----------------------------------------------------------------*/
7645 genFarPointerGet (operand * left,
7646 operand * result, iCode * ic, iCode * pi)
7649 sym_link *retype = getSpec (operandType (result));
7651 D(emitcode ("; genFarPointerGet",""));
7653 aopOp (left, ic, FALSE);
7654 loadDptrFromOperand (left, FALSE);
7656 /* so dptr now contains the address */
7657 aopOp (result, ic, FALSE);
7659 /* if bit then unpack */
7660 if (IS_BITVAR (retype))
7661 genUnpackBits (result, "dptr", FPOINTER);
7664 size = AOP_SIZE (result);
7669 emitcode ("movx", "a,@dptr");
7670 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7672 emitcode ("inc", "dptr");
7676 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7677 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7678 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7681 freeAsmop (left, NULL, ic, TRUE);
7682 freeAsmop (result, NULL, ic, TRUE);
7685 /*-----------------------------------------------------------------*/
7686 /* genCodePointerGet - gget value from code space */
7687 /*-----------------------------------------------------------------*/
7689 genCodePointerGet (operand * left,
7690 operand * result, iCode * ic, iCode *pi)
7693 sym_link *retype = getSpec (operandType (result));
7695 D(emitcode ("; genCodePointerGet",""));
7697 aopOp (left, ic, FALSE);
7698 loadDptrFromOperand (left, FALSE);
7700 /* so dptr now contains the address */
7701 aopOp (result, ic, FALSE);
7703 /* if bit then unpack */
7704 if (IS_BITVAR (retype))
7705 genUnpackBits (result, "dptr", CPOINTER);
7708 size = AOP_SIZE (result);
7715 emitcode ("clr", "a");
7716 emitcode ("movc", "a,@a+dptr");
7717 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7718 emitcode ("inc", "dptr");
7722 emitcode ("mov", "a,#0x%02x", offset);
7723 emitcode ("movc", "a,@a+dptr");
7724 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7729 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7730 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7731 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7734 freeAsmop (left, NULL, ic, TRUE);
7735 freeAsmop (result, NULL, ic, TRUE);
7738 /*-----------------------------------------------------------------*/
7739 /* genGenPointerGet - gget value from generic pointer space */
7740 /*-----------------------------------------------------------------*/
7742 genGenPointerGet (operand * left,
7743 operand * result, iCode * ic, iCode *pi)
7746 sym_link *retype = getSpec (operandType (result));
7748 D(emitcode ("; genGenPointerGet",""));
7750 aopOp (left, ic, FALSE);
7751 loadDptrFromOperand (left, TRUE);
7753 /* so dptr know contains the address */
7754 aopOp (result, ic, FALSE);
7756 /* if bit then unpack */
7757 if (IS_BITVAR (retype))
7758 genUnpackBits (result, "dptr", GPOINTER);
7761 size = AOP_SIZE (result);
7766 emitcode ("lcall", "__gptrget");
7767 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7769 emitcode ("inc", "dptr");
7773 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7774 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7775 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7778 freeAsmop (left, NULL, ic, TRUE);
7779 freeAsmop (result, NULL, ic, TRUE);
7782 /*-----------------------------------------------------------------*/
7783 /* genPointerGet - generate code for pointer get */
7784 /*-----------------------------------------------------------------*/
7786 genPointerGet (iCode * ic, iCode *pi)
7788 operand *left, *result;
7789 sym_link *type, *etype;
7792 D(emitcode ("; genPointerGet",""));
7794 left = IC_LEFT (ic);
7795 result = IC_RESULT (ic);
7797 /* depending on the type of pointer we need to
7798 move it to the correct pointer register */
7799 type = operandType (left);
7800 etype = getSpec (type);
7801 /* if left is of type of pointer then it is simple */
7802 if (IS_PTR (type) && !IS_FUNC (type->next))
7803 p_type = DCL_TYPE (type);
7806 /* we have to go by the storage class */
7807 p_type = PTR_TYPE (SPEC_OCLS (etype));
7810 /* special case when cast remat */
7811 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7812 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7813 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7814 type = operandType (left);
7815 p_type = DCL_TYPE (type);
7817 /* now that we have the pointer type we assign
7818 the pointer values */
7824 genNearPointerGet (left, result, ic, pi);
7828 genPagedPointerGet (left, result, ic, pi);
7832 genFarPointerGet (left, result, ic, pi);
7836 genCodePointerGet (left, result, ic, pi);
7840 genGenPointerGet (left, result, ic, pi);
7848 /*-----------------------------------------------------------------*/
7849 /* genPackBits - generates code for packed bit storage */
7850 /*-----------------------------------------------------------------*/
7852 genPackBits (sym_link * etype,
7854 char *rname, int p_type)
7856 int offset = 0; /* source byte offset */
7857 int rlen = 0; /* remaining bitfield length */
7858 int blen; /* bitfield length */
7859 int bstr; /* bitfield starting bit within byte */
7860 int litval; /* source literal value (if AOP_LIT) */
7861 unsigned char mask; /* bitmask within current byte */
7863 D(emitcode ("; genPackBits",""));
7865 blen = SPEC_BLEN (etype);
7866 bstr = SPEC_BSTR (etype);
7868 /* If the bitfield length is less than a byte */
7871 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7872 (unsigned char) (0xFF >> (8 - bstr)));
7874 if (AOP_TYPE (right) == AOP_LIT)
7876 /* Case with a bitfield length <8 and literal source
7878 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7880 litval &= (~mask) & 0xff;
7881 emitPtrByteGet (rname, p_type, FALSE);
7882 if ((mask|litval)!=0xff)
7883 emitcode ("anl","a,#0x%02x", mask);
7885 emitcode ("orl","a,#0x%02x", litval);
7889 if ((blen==1) && (p_type!=GPOINTER))
7891 /* Case with a bitfield length == 1 and no generic pointer
7893 if (AOP_TYPE (right) == AOP_CRY)
7894 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7897 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7898 emitcode ("rrc","a");
7900 emitPtrByteGet (rname, p_type, FALSE);
7901 emitcode ("mov","acc.%d,c",bstr);
7905 /* Case with a bitfield length < 8 and arbitrary source
7907 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7908 /* shift and mask source value */
7910 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7912 /* transfer A to B and get next byte */
7913 emitPtrByteGet (rname, p_type, TRUE);
7915 emitcode ("anl", "a,#0x%02x", mask);
7916 emitcode ("orl", "a,b");
7917 if (p_type == GPOINTER)
7918 emitcode ("pop", "b");
7922 emitPtrByteSet (rname, p_type, "a");
7926 /* Bit length is greater than 7 bits. In this case, copy */
7927 /* all except the partial byte at the end */
7928 for (rlen=blen;rlen>=8;rlen-=8)
7930 emitPtrByteSet (rname, p_type,
7931 aopGet (AOP (right), offset++, FALSE, TRUE) );
7933 emitcode ("inc", "%s", rname);
7936 /* If there was a partial byte at the end */
7939 mask = (((unsigned char) -1 << rlen) & 0xff);
7941 if (AOP_TYPE (right) == AOP_LIT)
7943 /* Case with partial byte and literal source
7945 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7946 litval >>= (blen-rlen);
7947 litval &= (~mask) & 0xff;
7948 emitPtrByteGet (rname, p_type, FALSE);
7949 if ((mask|litval)!=0xff)
7950 emitcode ("anl","a,#0x%02x", mask);
7952 emitcode ("orl","a,#0x%02x", litval);
7956 /* Case with partial byte and arbitrary source
7958 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
7959 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7961 /* transfer A to B and get next byte */
7962 emitPtrByteGet (rname, p_type, TRUE);
7964 emitcode ("anl", "a,#0x%02x", mask);
7965 emitcode ("orl", "a,b");
7966 if (p_type == GPOINTER)
7967 emitcode ("pop", "b");
7969 emitPtrByteSet (rname, p_type, "a");
7975 /*-----------------------------------------------------------------*/
7976 /* genDataPointerSet - remat pointer to data space */
7977 /*-----------------------------------------------------------------*/
7979 genDataPointerSet (operand * right,
7983 int size, offset = 0;
7984 char *l, buffer[256];
7986 D(emitcode ("; genDataPointerSet",""));
7988 aopOp (right, ic, FALSE);
7990 l = aopGet (AOP (result), 0, FALSE, TRUE);
7991 size = AOP_SIZE (right);
7995 sprintf (buffer, "(%s + %d)", l + 1, offset);
7997 sprintf (buffer, "%s", l + 1);
7998 emitcode ("mov", "%s,%s", buffer,
7999 aopGet (AOP (right), offset++, FALSE, FALSE));
8002 freeAsmop (right, NULL, ic, TRUE);
8003 freeAsmop (result, NULL, ic, TRUE);
8006 /*-----------------------------------------------------------------*/
8007 /* genNearPointerSet - emitcode for near pointer put */
8008 /*-----------------------------------------------------------------*/
8010 genNearPointerSet (operand * right,
8018 sym_link *retype, *letype;
8019 sym_link *ptype = operandType (result);
8021 D(emitcode ("; genNearPointerSet",""));
8023 retype = getSpec (operandType (right));
8024 letype = getSpec (ptype);
8025 aopOp (result, ic, FALSE);
8027 /* if the result is rematerializable &
8028 in data space & not a bit variable */
8029 if (AOP_TYPE (result) == AOP_IMMD &&
8030 DCL_TYPE (ptype) == POINTER &&
8031 !IS_BITVAR (retype) &&
8032 !IS_BITVAR (letype))
8034 genDataPointerSet (right, result, ic);
8038 /* if the value is already in a pointer register
8039 then don't need anything more */
8040 if (!AOP_INPREG (AOP (result)))
8043 //AOP_TYPE (result) == AOP_STK
8047 // Aha, it is a pointer, just in disguise.
8048 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8051 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8052 __FILE__, __LINE__);
8057 emitcode ("mov", "a%s,%s", rname + 1, rname);
8058 rname++; // skip the '@'.
8063 /* otherwise get a free pointer register */
8065 preg = getFreePtr (ic, &aop, FALSE);
8066 emitcode ("mov", "%s,%s",
8068 aopGet (AOP (result), 0, FALSE, TRUE));
8074 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8077 aopOp (right, ic, FALSE);
8079 /* if bitfield then unpack the bits */
8080 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8081 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8084 /* we have can just get the values */
8085 int size = AOP_SIZE (right);
8090 l = aopGet (AOP (right), offset, FALSE, TRUE);
8094 emitcode ("mov", "@%s,a", rname);
8097 emitcode ("mov", "@%s,%s", rname, l);
8099 emitcode ("inc", "%s", rname);
8104 /* now some housekeeping stuff */
8105 if (aop) /* we had to allocate for this iCode */
8108 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8109 freeAsmop (NULL, aop, ic, TRUE);
8113 /* we did not allocate which means left
8114 already in a pointer register, then
8115 if size > 0 && this could be used again
8116 we have to point it back to where it
8118 if ((AOP_SIZE (right) > 1 &&
8119 !OP_SYMBOL (result)->remat &&
8120 (OP_SYMBOL (result)->liveTo > ic->seq ||
8124 int size = AOP_SIZE (right) - 1;
8126 emitcode ("dec", "%s", rname);
8131 if (pi) pi->generated = 1;
8132 freeAsmop (result, NULL, ic, TRUE);
8133 freeAsmop (right, NULL, ic, TRUE);
8136 /*-----------------------------------------------------------------*/
8137 /* genPagedPointerSet - emitcode for Paged pointer put */
8138 /*-----------------------------------------------------------------*/
8140 genPagedPointerSet (operand * right,
8148 sym_link *retype, *letype;
8150 D(emitcode ("; genPagedPointerSet",""));
8152 retype = getSpec (operandType (right));
8153 letype = getSpec (operandType (result));
8155 aopOp (result, ic, FALSE);
8157 /* if the value is already in a pointer register
8158 then don't need anything more */
8159 if (!AOP_INPREG (AOP (result)))
8161 /* otherwise get a free pointer register */
8163 preg = getFreePtr (ic, &aop, FALSE);
8164 emitcode ("mov", "%s,%s",
8166 aopGet (AOP (result), 0, FALSE, TRUE));
8170 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8172 aopOp (right, ic, FALSE);
8174 /* if bitfield then unpack the bits */
8175 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8176 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8179 /* we have can just get the values */
8180 int size = AOP_SIZE (right);
8185 l = aopGet (AOP (right), offset, FALSE, TRUE);
8188 emitcode ("movx", "@%s,a", rname);
8191 emitcode ("inc", "%s", rname);
8197 /* now some housekeeping stuff */
8198 if (aop) /* we had to allocate for this iCode */
8201 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8202 freeAsmop (NULL, aop, ic, TRUE);
8206 /* we did not allocate which means left
8207 already in a pointer register, then
8208 if size > 0 && this could be used again
8209 we have to point it back to where it
8211 if (AOP_SIZE (right) > 1 &&
8212 !OP_SYMBOL (result)->remat &&
8213 (OP_SYMBOL (result)->liveTo > ic->seq ||
8216 int size = AOP_SIZE (right) - 1;
8218 emitcode ("dec", "%s", rname);
8223 if (pi) pi->generated = 1;
8224 freeAsmop (result, NULL, ic, TRUE);
8225 freeAsmop (right, NULL, ic, TRUE);
8230 /*-----------------------------------------------------------------*/
8231 /* genFarPointerSet - set value from far space */
8232 /*-----------------------------------------------------------------*/
8234 genFarPointerSet (operand * right,
8235 operand * result, iCode * ic, iCode * pi)
8238 sym_link *retype = getSpec (operandType (right));
8239 sym_link *letype = getSpec (operandType (result));
8241 D(emitcode ("; genFarPointerSet",""));
8243 aopOp (result, ic, FALSE);
8244 loadDptrFromOperand (result, FALSE);
8246 /* so dptr know contains the address */
8247 aopOp (right, ic, FALSE);
8249 /* if bit then unpack */
8250 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8251 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8254 size = AOP_SIZE (right);
8259 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8261 emitcode ("movx", "@dptr,a");
8263 emitcode ("inc", "dptr");
8266 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8267 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8268 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8271 freeAsmop (result, NULL, ic, TRUE);
8272 freeAsmop (right, NULL, ic, TRUE);
8275 /*-----------------------------------------------------------------*/
8276 /* genGenPointerSet - set value from generic pointer space */
8277 /*-----------------------------------------------------------------*/
8279 genGenPointerSet (operand * right,
8280 operand * result, iCode * ic, iCode * pi)
8283 sym_link *retype = getSpec (operandType (right));
8284 sym_link *letype = getSpec (operandType (result));
8286 D(emitcode ("; genGenPointerSet",""));
8288 aopOp (result, ic, FALSE);
8289 loadDptrFromOperand (result, TRUE);
8291 /* so dptr know contains the address */
8292 aopOp (right, ic, FALSE);
8294 /* if bit then unpack */
8295 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8296 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8299 size = AOP_SIZE (right);
8304 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8306 emitcode ("lcall", "__gptrput");
8308 emitcode ("inc", "dptr");
8312 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8313 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8314 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8317 freeAsmop (result, NULL, ic, TRUE);
8318 freeAsmop (right, NULL, ic, TRUE);
8321 /*-----------------------------------------------------------------*/
8322 /* genPointerSet - stores the value into a pointer location */
8323 /*-----------------------------------------------------------------*/
8325 genPointerSet (iCode * ic, iCode *pi)
8327 operand *right, *result;
8328 sym_link *type, *etype;
8331 D(emitcode ("; genPointerSet",""));
8333 right = IC_RIGHT (ic);
8334 result = IC_RESULT (ic);
8336 /* depending on the type of pointer we need to
8337 move it to the correct pointer register */
8338 type = operandType (result);
8339 etype = getSpec (type);
8340 /* if left is of type of pointer then it is simple */
8341 if (IS_PTR (type) && !IS_FUNC (type->next))
8343 p_type = DCL_TYPE (type);
8347 /* we have to go by the storage class */
8348 p_type = PTR_TYPE (SPEC_OCLS (etype));
8351 /* special case when cast remat */
8352 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8353 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8354 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8355 type = operandType (result);
8356 p_type = DCL_TYPE (type);
8358 /* now that we have the pointer type we assign
8359 the pointer values */
8365 genNearPointerSet (right, result, ic, pi);
8369 genPagedPointerSet (right, result, ic, pi);
8373 genFarPointerSet (right, result, ic, pi);
8377 genGenPointerSet (right, result, ic, pi);
8381 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8382 "genPointerSet: illegal pointer type");
8387 /*-----------------------------------------------------------------*/
8388 /* genIfx - generate code for Ifx statement */
8389 /*-----------------------------------------------------------------*/
8391 genIfx (iCode * ic, iCode * popIc)
8393 operand *cond = IC_COND (ic);
8396 D(emitcode ("; genIfx",""));
8398 aopOp (cond, ic, FALSE);
8400 /* get the value into acc */
8401 if (AOP_TYPE (cond) != AOP_CRY)
8405 /* the result is now in the accumulator */
8406 freeAsmop (cond, NULL, ic, TRUE);
8408 /* if there was something to be popped then do it */
8412 /* if the condition is a bit variable */
8413 if (isbit && IS_ITEMP (cond) &&
8415 genIfxJump (ic, SPIL_LOC (cond)->rname);
8416 else if (isbit && !IS_ITEMP (cond))
8417 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8419 genIfxJump (ic, "a");
8424 /*-----------------------------------------------------------------*/
8425 /* genAddrOf - generates code for address of */
8426 /*-----------------------------------------------------------------*/
8428 genAddrOf (iCode * ic)
8430 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8433 D(emitcode ("; genAddrOf",""));
8435 aopOp (IC_RESULT (ic), ic, FALSE);
8437 /* if the operand is on the stack then we
8438 need to get the stack offset of this
8442 /* if it has an offset then we need to compute
8446 emitcode ("mov", "a,_bp");
8447 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8448 ((char) (sym->stack - _G.nRegsSaved)) :
8449 ((char) sym->stack)) & 0xff);
8450 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8454 /* we can just move _bp */
8455 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8457 /* fill the result with zero */
8458 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8463 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8469 /* object not on stack then we need the name */
8470 size = AOP_SIZE (IC_RESULT (ic));
8475 char s[SDCC_NAME_MAX];
8477 sprintf (s, "#(%s >> %d)",
8481 sprintf (s, "#%s", sym->rname);
8482 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8486 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8490 /*-----------------------------------------------------------------*/
8491 /* genFarFarAssign - assignment when both are in far space */
8492 /*-----------------------------------------------------------------*/
8494 genFarFarAssign (operand * result, operand * right, iCode * ic)
8496 int size = AOP_SIZE (right);
8500 D(emitcode ("; genFarFarAssign",""));
8502 /* first push the right side on to the stack */
8505 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8507 emitcode ("push", "acc");
8510 freeAsmop (right, NULL, ic, FALSE);
8511 /* now assign DPTR to result */
8512 aopOp (result, ic, FALSE);
8513 size = AOP_SIZE (result);
8516 emitcode ("pop", "acc");
8517 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8519 freeAsmop (result, NULL, ic, FALSE);
8523 /*-----------------------------------------------------------------*/
8524 /* genAssign - generate code for assignment */
8525 /*-----------------------------------------------------------------*/
8527 genAssign (iCode * ic)
8529 operand *result, *right;
8531 unsigned long lit = 0L;
8533 D(emitcode("; genAssign",""));
8535 result = IC_RESULT (ic);
8536 right = IC_RIGHT (ic);
8538 /* if they are the same */
8539 if (operandsEqu (result, right) &&
8540 !isOperandVolatile (result, FALSE) &&
8541 !isOperandVolatile (right, FALSE))
8544 aopOp (right, ic, FALSE);
8546 /* special case both in far space */
8547 if (AOP_TYPE (right) == AOP_DPTR &&
8548 IS_TRUE_SYMOP (result) &&
8549 isOperandInFarSpace (result))
8552 genFarFarAssign (result, right, ic);
8556 aopOp (result, ic, TRUE);
8558 /* if they are the same registers */
8559 if (sameRegs (AOP (right), AOP (result)) &&
8560 !isOperandVolatile (result, FALSE) &&
8561 !isOperandVolatile (right, FALSE))
8564 /* if the result is a bit */
8565 if (AOP_TYPE (result) == AOP_CRY)
8568 /* if the right size is a literal then
8569 we know what the value is */
8570 if (AOP_TYPE (right) == AOP_LIT)
8572 if (((int) operandLitValue (right)))
8573 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8575 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8579 /* the right is also a bit variable */
8580 if (AOP_TYPE (right) == AOP_CRY)
8582 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8583 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8589 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8593 /* bit variables done */
8595 size = AOP_SIZE (result);
8597 if (AOP_TYPE (right) == AOP_LIT)
8598 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8600 (AOP_TYPE (result) != AOP_REG) &&
8601 (AOP_TYPE (right) == AOP_LIT) &&
8602 !IS_FLOAT (operandType (right)) &&
8605 emitcode ("clr", "a");
8608 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8609 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8611 aopPut (AOP (result),
8612 aopGet (AOP (right), size, FALSE, FALSE),
8614 isOperandVolatile (result, FALSE));
8621 aopPut (AOP (result),
8622 aopGet (AOP (right), offset, FALSE, FALSE),
8624 isOperandVolatile (result, FALSE));
8630 freeAsmop (right, NULL, ic, TRUE);
8631 freeAsmop (result, NULL, ic, TRUE);
8634 /*-----------------------------------------------------------------*/
8635 /* genJumpTab - genrates code for jump table */
8636 /*-----------------------------------------------------------------*/
8638 genJumpTab (iCode * ic)
8643 D(emitcode ("; genJumpTab",""));
8645 aopOp (IC_JTCOND (ic), ic, FALSE);
8646 /* get the condition into accumulator */
8647 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8649 /* multiply by three */
8650 emitcode ("add", "a,acc");
8651 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8652 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8654 jtab = newiTempLabel (NULL);
8655 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8656 emitcode ("jmp", "@a+dptr");
8657 emitcode ("", "%05d$:", jtab->key + 100);
8658 /* now generate the jump labels */
8659 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8660 jtab = setNextItem (IC_JTLABELS (ic)))
8661 emitcode ("ljmp", "%05d$", jtab->key + 100);
8665 /*-----------------------------------------------------------------*/
8666 /* genCast - gen code for casting */
8667 /*-----------------------------------------------------------------*/
8669 genCast (iCode * ic)
8671 operand *result = IC_RESULT (ic);
8672 sym_link *ctype = operandType (IC_LEFT (ic));
8673 sym_link *rtype = operandType (IC_RIGHT (ic));
8674 operand *right = IC_RIGHT (ic);
8677 D(emitcode("; genCast",""));
8679 /* if they are equivalent then do nothing */
8680 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8683 aopOp (right, ic, FALSE);
8684 aopOp (result, ic, FALSE);
8686 /* if the result is a bit (and not a bitfield) */
8687 // if (AOP_TYPE (result) == AOP_CRY)
8688 if (IS_BITVAR (OP_SYMBOL (result)->type)
8689 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8691 /* if the right size is a literal then
8692 we know what the value is */
8693 if (AOP_TYPE (right) == AOP_LIT)
8695 if (((int) operandLitValue (right)))
8696 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8698 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8703 /* the right is also a bit variable */
8704 if (AOP_TYPE (right) == AOP_CRY)
8706 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8707 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8713 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8718 /* if they are the same size : or less */
8719 if (AOP_SIZE (result) <= AOP_SIZE (right))
8722 /* if they are in the same place */
8723 if (sameRegs (AOP (right), AOP (result)))
8726 /* if they in different places then copy */
8727 size = AOP_SIZE (result);
8731 aopPut (AOP (result),
8732 aopGet (AOP (right), offset, FALSE, FALSE),
8734 isOperandVolatile (result, FALSE));
8741 /* if the result is of type pointer */
8746 sym_link *type = operandType (right);
8747 sym_link *etype = getSpec (type);
8749 /* pointer to generic pointer */
8750 if (IS_GENPTR (ctype))
8753 p_type = DCL_TYPE (type);
8756 if (SPEC_SCLS(etype)==S_REGISTER) {
8757 // let's assume it is a generic pointer
8760 /* we have to go by the storage class */
8761 p_type = PTR_TYPE (SPEC_OCLS (etype));
8765 /* the first two bytes are known */
8766 size = GPTRSIZE - 1;
8770 aopPut (AOP (result),
8771 aopGet (AOP (right), offset, FALSE, FALSE),
8773 isOperandVolatile (result, FALSE));
8776 /* the last byte depending on type */
8778 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8783 // pointerTypeToGPByte will have bitched.
8787 sprintf(gpValStr, "#0x%d", gpVal);
8788 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8793 /* just copy the pointers */
8794 size = AOP_SIZE (result);
8798 aopPut (AOP (result),
8799 aopGet (AOP (right), offset, FALSE, FALSE),
8801 isOperandVolatile (result, FALSE));
8807 /* so we now know that the size of destination is greater
8808 than the size of the source */
8809 /* we move to result for the size of source */
8810 size = AOP_SIZE (right);
8814 aopPut (AOP (result),
8815 aopGet (AOP (right), offset, FALSE, FALSE),
8817 isOperandVolatile (result, FALSE));
8821 /* now depending on the sign of the source && destination */
8822 size = AOP_SIZE (result) - AOP_SIZE (right);
8823 /* if unsigned or not an integral type */
8824 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8827 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8831 /* we need to extend the sign :{ */
8832 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8835 emitcode ("rlc", "a");
8836 emitcode ("subb", "a,acc");
8838 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8841 /* we are done hurray !!!! */
8844 freeAsmop (right, NULL, ic, TRUE);
8845 freeAsmop (result, NULL, ic, TRUE);
8849 /*-----------------------------------------------------------------*/
8850 /* genDjnz - generate decrement & jump if not zero instrucion */
8851 /*-----------------------------------------------------------------*/
8853 genDjnz (iCode * ic, iCode * ifx)
8859 D(emitcode ("; genDjnz",""));
8861 /* if the if condition has a false label
8862 then we cannot save */
8866 /* if the minus is not of the form
8868 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8869 !IS_OP_LITERAL (IC_RIGHT (ic)))
8872 if (operandLitValue (IC_RIGHT (ic)) != 1)
8875 /* if the size of this greater than one then no
8877 if (getSize (operandType (IC_RESULT (ic))) > 1)
8880 /* otherwise we can save BIG */
8881 lbl = newiTempLabel (NULL);
8882 lbl1 = newiTempLabel (NULL);
8884 aopOp (IC_RESULT (ic), ic, FALSE);
8886 if (AOP_NEEDSACC(IC_RESULT(ic)))
8888 /* If the result is accessed indirectly via
8889 * the accumulator, we must explicitly write
8890 * it back after the decrement.
8892 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8894 if (strcmp(rByte, "a"))
8896 /* Something is hopelessly wrong */
8897 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8898 __FILE__, __LINE__);
8899 /* We can just give up; the generated code will be inefficient,
8902 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8905 emitcode ("dec", "%s", rByte);
8906 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8907 emitcode ("jnz", "%05d$", lbl->key + 100);
8909 else if (IS_AOP_PREG (IC_RESULT (ic)))
8911 emitcode ("dec", "%s",
8912 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8913 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8914 emitcode ("jnz", "%05d$", lbl->key + 100);
8918 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8921 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8922 emitcode ("", "%05d$:", lbl->key + 100);
8923 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8924 emitcode ("", "%05d$:", lbl1->key + 100);
8926 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8931 /*-----------------------------------------------------------------*/
8932 /* genReceive - generate code for a receive iCode */
8933 /*-----------------------------------------------------------------*/
8935 genReceive (iCode * ic)
8937 int size = getSize (operandType (IC_RESULT (ic)));
8939 D(emitcode ("; genReceive",""));
8941 if (ic->argreg == 1) { /* first parameter */
8942 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8943 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8944 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
8946 offset = fReturnSizeMCS51 - size;
8948 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8949 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8952 aopOp (IC_RESULT (ic), ic, FALSE);
8953 size = AOP_SIZE (IC_RESULT (ic));
8956 emitcode ("pop", "acc");
8957 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8962 aopOp (IC_RESULT (ic), ic, FALSE);
8964 assignResultValue (IC_RESULT (ic));
8966 } else { /* second receive onwards */
8968 aopOp (IC_RESULT (ic), ic, FALSE);
8969 rb1off = ic->argreg;
8971 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8974 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8977 /*-----------------------------------------------------------------*/
8978 /* genDummyRead - generate code for dummy read of volatiles */
8979 /*-----------------------------------------------------------------*/
8981 genDummyRead (iCode * ic)
8986 D(emitcode("; genDummyRead",""));
8988 right = IC_RIGHT (ic);
8990 aopOp (right, ic, FALSE);
8992 /* if the result is a bit */
8993 if (AOP_TYPE (right) == AOP_CRY)
8995 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8999 /* bit variables done */
9001 size = AOP_SIZE (right);
9005 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
9010 freeAsmop (right, NULL, ic, TRUE);
9013 /*-----------------------------------------------------------------*/
9014 /* genCritical - generate code for start of a critical sequence */
9015 /*-----------------------------------------------------------------*/
9017 genCritical (iCode *ic)
9019 symbol *tlbl = newiTempLabel (NULL);
9021 D(emitcode("; genCritical",""));
9024 aopOp (IC_RESULT (ic), ic, TRUE);
9026 emitcode ("setb", "c");
9027 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9028 emitcode ("clr", "c");
9029 emitcode ("", "%05d$:", (tlbl->key + 100));
9032 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9034 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9037 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9040 /*-----------------------------------------------------------------*/
9041 /* genEndCritical - generate code for end of a critical sequence */
9042 /*-----------------------------------------------------------------*/
9044 genEndCritical (iCode *ic)
9046 D(emitcode("; genEndCritical",""));
9050 aopOp (IC_RIGHT (ic), ic, FALSE);
9051 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9053 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9054 emitcode ("mov", "ea,c");
9058 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9059 emitcode ("rrc", "a");
9060 emitcode ("mov", "ea,c");
9062 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9066 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9067 emitcode ("mov", "ea,c");
9072 /*-----------------------------------------------------------------*/
9073 /* gen51Code - generate code for 8051 based controllers */
9074 /*-----------------------------------------------------------------*/
9076 gen51Code (iCode * lic)
9081 lineHead = lineCurr = NULL;
9083 /* print the allocation information */
9084 if (allocInfo && currFunc)
9085 printAllocInfo (currFunc, codeOutFile);
9086 /* if debug information required */
9087 if (options.debug && currFunc)
9089 debugFile->writeFunction(currFunc);
9091 if (IS_STATIC (currFunc->etype))
9092 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9094 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9097 /* stack pointer name */
9098 if (options.useXstack)
9104 for (ic = lic; ic; ic = ic->next)
9106 _G.current_iCode = ic;
9108 if (ic->lineno && cln != ic->lineno)
9113 emitcode ("", "C$%s$%d$%d$%d ==.",
9114 FileBaseName (ic->filename), ic->lineno,
9115 ic->level, ic->block);
9118 if (!options.noCcodeInAsm) {
9119 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9120 printCLine(ic->filename, ic->lineno));
9124 if (options.iCodeInAsm) {
9128 for (i=0; i<8; i++) {
9129 sprintf (®sInUse[i],
9130 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9133 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9135 /* if the result is marked as
9136 spilt and rematerializable or code for
9137 this has already been generated then
9139 if (resultRemat (ic) || ic->generated)
9142 /* depending on the operation */
9162 /* IPOP happens only when trying to restore a
9163 spilt live range, if there is an ifx statement
9164 following this pop then the if statement might
9165 be using some of the registers being popped which
9166 would destory the contents of the register so
9167 we need to check for this condition and handle it */
9169 ic->next->op == IFX &&
9170 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9171 genIfx (ic->next, ic);
9189 genEndFunction (ic);
9209 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9226 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9230 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9237 /* note these two are xlated by algebraic equivalence
9238 during parsing SDCC.y */
9239 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9240 "got '>=' or '<=' shouldn't have come here");
9244 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9256 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9260 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9264 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9291 case GET_VALUE_AT_ADDRESS:
9292 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9296 if (POINTER_SET (ic))
9297 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9323 addSet (&_G.sendSet, ic);
9326 case DUMMY_READ_VOLATILE:
9335 genEndCritical (ic);
9343 _G.current_iCode = NULL;
9345 /* now we are ready to call the
9346 peep hole optimizer */
9347 if (!options.nopeep)
9348 peepHole (&lineHead);
9350 /* now do the actual printing */
9351 printLine (lineHead, codeOutFile);