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;
3197 asmop *leftOp, *rightOp;
3199 /* special cases :- */
3201 D(emitcode ("; genPlus",""));
3203 aopOp (IC_LEFT (ic), ic, FALSE);
3204 aopOp (IC_RIGHT (ic), ic, FALSE);
3205 aopOp (IC_RESULT (ic), ic, TRUE);
3207 /* if literal, literal on the right or
3208 if left requires ACC or right is already
3210 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3211 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3212 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3214 operand *t = IC_RIGHT (ic);
3215 IC_RIGHT (ic) = IC_LEFT (ic);
3219 /* if both left & right are in bit
3221 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3222 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3228 /* if left in bit space & right literal */
3229 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3230 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3232 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3233 /* if result in bit space */
3234 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3236 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3237 emitcode ("cpl", "c");
3238 outBitC (IC_RESULT (ic));
3242 size = getDataSize (IC_RESULT (ic));
3245 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3246 emitcode ("addc", "a,#00");
3247 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3253 /* if I can do an increment instead
3254 of add then GOOD for ME */
3255 if (genPlusIncr (ic) == TRUE)
3258 size = getDataSize (IC_RESULT (ic));
3260 /* if the lower bytes of a literal are zero skip the addition */
3261 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3263 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3264 (skip_bytes+1 < size))
3269 D(emitcode ("; genPlus shortcut",""));
3272 leftOp = AOP(IC_LEFT(ic));
3273 rightOp = AOP(IC_RIGHT(ic));
3277 if( offset >= skip_bytes )
3279 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3281 emitcode("mov", "b,a");
3282 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3283 emitcode("xch", "a,b");
3284 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3285 emitcode (add, "a,b");
3287 else if (aopGetUsesAcc (leftOp, offset))
3289 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3290 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3294 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3295 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3297 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3298 add = "addc"; /* further adds must propagate carry */
3302 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3303 isOperandVolatile (IC_RESULT (ic), FALSE))
3306 aopPut (AOP (IC_RESULT (ic)),
3307 aopGet (leftOp, offset, FALSE, FALSE),
3309 isOperandVolatile (IC_RESULT (ic), FALSE));
3315 adjustArithmeticResult (ic);
3318 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3319 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3320 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3323 /*-----------------------------------------------------------------*/
3324 /* genMinusDec :- does subtraction with deccrement if possible */
3325 /*-----------------------------------------------------------------*/
3327 genMinusDec (iCode * ic)
3329 unsigned int icount;
3330 unsigned int size = getDataSize (IC_RESULT (ic));
3332 /* will try to generate an increment */
3333 /* if the right side is not a literal
3335 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3338 /* if the literal value of the right hand side
3339 is greater than 4 then it is not worth it */
3340 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3343 D(emitcode ("; genMinusDec",""));
3345 /* if decrement >=16 bits in register or direct space */
3346 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3347 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3355 /* If the next instruction is a goto and the goto target
3356 * is <= 10 instructions previous to this, we can generate
3357 * jumps straight to that target.
3359 if (ic->next && ic->next->op == GOTO
3360 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3361 && labelRange <= 10)
3363 emitcode (";", "tail decrement optimized");
3364 tlbl = IC_LABEL (ic->next);
3369 tlbl = newiTempLabel (NULL);
3373 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3374 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3375 IS_AOP_PREG (IC_RESULT (ic)))
3376 emitcode ("cjne", "%s,#0xff,%05d$"
3377 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3381 emitcode ("mov", "a,#0xff");
3382 emitcode ("cjne", "a,%s,%05d$"
3383 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3386 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3389 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3390 IS_AOP_PREG (IC_RESULT (ic)))
3391 emitcode ("cjne", "%s,#0xff,%05d$"
3392 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3396 emitcode ("cjne", "a,%s,%05d$"
3397 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3400 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3404 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3405 IS_AOP_PREG (IC_RESULT (ic)))
3406 emitcode ("cjne", "%s,#0xff,%05d$"
3407 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3411 emitcode ("cjne", "a,%s,%05d$"
3412 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3415 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3419 emitcode ("", "%05d$:", tlbl->key + 100);
3424 /* if the sizes are greater than 1 then we cannot */
3425 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3426 AOP_SIZE (IC_LEFT (ic)) > 1)
3429 /* we can if the aops of the left & result match or
3430 if they are in registers and the registers are the
3432 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3436 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3444 /*-----------------------------------------------------------------*/
3445 /* addSign - complete with sign */
3446 /*-----------------------------------------------------------------*/
3448 addSign (operand * result, int offset, int sign)
3450 int size = (getDataSize (result) - offset);
3455 emitcode ("rlc", "a");
3456 emitcode ("subb", "a,acc");
3458 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3462 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3466 /*-----------------------------------------------------------------*/
3467 /* genMinusBits - generates code for subtraction of two bits */
3468 /*-----------------------------------------------------------------*/
3470 genMinusBits (iCode * ic)
3472 symbol *lbl = newiTempLabel (NULL);
3474 D(emitcode ("; genMinusBits",""));
3476 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3478 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3479 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3480 emitcode ("cpl", "c");
3481 emitcode ("", "%05d$:", (lbl->key + 100));
3482 outBitC (IC_RESULT (ic));
3486 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3487 emitcode ("subb", "a,acc");
3488 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3489 emitcode ("inc", "a");
3490 emitcode ("", "%05d$:", (lbl->key + 100));
3491 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3492 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3496 /*-----------------------------------------------------------------*/
3497 /* genMinus - generates code for subtraction */
3498 /*-----------------------------------------------------------------*/
3500 genMinus (iCode * ic)
3502 int size, offset = 0;
3504 D(emitcode ("; genMinus",""));
3506 aopOp (IC_LEFT (ic), ic, FALSE);
3507 aopOp (IC_RIGHT (ic), ic, FALSE);
3508 aopOp (IC_RESULT (ic), ic, TRUE);
3510 /* special cases :- */
3511 /* if both left & right are in bit space */
3512 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3513 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3519 /* if I can do an decrement instead
3520 of subtract then GOOD for ME */
3521 if (genMinusDec (ic) == TRUE)
3524 size = getDataSize (IC_RESULT (ic));
3526 /* if literal, add a,#-lit, else normal subb */
3527 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3529 unsigned long lit = 0L;
3531 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3536 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3537 /* first add without previous c */
3539 if (!size && lit== (unsigned long) -1) {
3540 emitcode ("dec", "a");
3542 emitcode ("add", "a,#0x%02x",
3543 (unsigned int) (lit & 0x0FFL));
3546 emitcode ("addc", "a,#0x%02x",
3547 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3549 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3554 asmop *leftOp, *rightOp;
3556 leftOp = AOP(IC_LEFT(ic));
3557 rightOp = AOP(IC_RIGHT(ic));
3561 if (aopGetUsesAcc(rightOp, offset)) {
3562 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3563 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3565 emitcode( "setb", "c");
3567 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3568 emitcode("cpl", "a");
3570 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3573 emitcode ("subb", "a,%s",
3574 aopGet(rightOp, offset, FALSE, TRUE));
3577 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3582 adjustArithmeticResult (ic);
3585 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3586 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3587 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3591 /*-----------------------------------------------------------------*/
3592 /* genMultbits :- multiplication of bits */
3593 /*-----------------------------------------------------------------*/
3595 genMultbits (operand * left,
3599 D(emitcode ("; genMultbits",""));
3601 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3602 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3607 /*-----------------------------------------------------------------*/
3608 /* genMultOneByte : 8*8=8/16 bit multiplication */
3609 /*-----------------------------------------------------------------*/
3611 genMultOneByte (operand * left,
3615 sym_link *opetype = operandType (result);
3617 int size=AOP_SIZE(result);
3619 D(emitcode ("; genMultOneByte",""));
3621 if (size<1 || size>2) {
3622 // this should never happen
3623 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3624 AOP_SIZE(result), __FILE__, lineno);
3628 /* (if two literals: the value is computed before) */
3629 /* if one literal, literal on the right */
3630 if (AOP_TYPE (left) == AOP_LIT)
3635 //emitcode (";", "swapped left and right");
3638 if (SPEC_USIGN(opetype)
3639 // ignore the sign of left and right, what else can we do?
3640 || (SPEC_USIGN(operandType(left)) &&
3641 SPEC_USIGN(operandType(right)))) {
3642 // just an unsigned 8*8=8/16 multiply
3643 //emitcode (";","unsigned");
3644 // TODO: check for accumulator clash between left & right aops?
3645 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3646 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3647 emitcode ("mul", "ab");
3648 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3650 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3655 // we have to do a signed multiply
3657 //emitcode (";", "signed");
3658 emitcode ("clr", "F0"); // reset sign flag
3659 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3661 lbl=newiTempLabel(NULL);
3662 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3663 // left side is negative, 8-bit two's complement, this fails for -128
3664 emitcode ("setb", "F0"); // set sign flag
3665 emitcode ("cpl", "a");
3666 emitcode ("inc", "a");
3668 emitcode ("", "%05d$:", lbl->key+100);
3671 if (AOP_TYPE(right)==AOP_LIT) {
3672 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3673 /* AND literal negative */
3675 emitcode ("cpl", "F0"); // complement sign flag
3676 emitcode ("mov", "b,#0x%02x", -val);
3678 emitcode ("mov", "b,#0x%02x", val);
3681 lbl=newiTempLabel(NULL);
3682 emitcode ("mov", "b,a");
3683 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3684 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3685 // right side is negative, 8-bit two's complement
3686 emitcode ("cpl", "F0"); // complement sign flag
3687 emitcode ("cpl", "a");
3688 emitcode ("inc", "a");
3689 emitcode ("", "%05d$:", lbl->key+100);
3691 emitcode ("mul", "ab");
3693 lbl=newiTempLabel(NULL);
3694 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3695 // only ONE op was negative, we have to do a 8/16-bit two's complement
3696 emitcode ("cpl", "a"); // lsb
3698 emitcode ("inc", "a");
3700 emitcode ("add", "a,#1");
3701 emitcode ("xch", "a,b");
3702 emitcode ("cpl", "a"); // msb
3703 emitcode ("addc", "a,#0");
3704 emitcode ("xch", "a,b");
3707 emitcode ("", "%05d$:", lbl->key+100);
3708 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3710 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3714 /*-----------------------------------------------------------------*/
3715 /* genMult - generates code for multiplication */
3716 /*-----------------------------------------------------------------*/
3718 genMult (iCode * ic)
3720 operand *left = IC_LEFT (ic);
3721 operand *right = IC_RIGHT (ic);
3722 operand *result = IC_RESULT (ic);
3724 D(emitcode ("; genMult",""));
3726 /* assign the amsops */
3727 aopOp (left, ic, FALSE);
3728 aopOp (right, ic, FALSE);
3729 aopOp (result, ic, TRUE);
3731 /* special cases first */
3733 if (AOP_TYPE (left) == AOP_CRY &&
3734 AOP_TYPE (right) == AOP_CRY)
3736 genMultbits (left, right, result);
3740 /* if both are of size == 1 */
3741 #if 0 // one of them can be a sloc shared with the result
3742 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3744 if (getSize(operandType(left)) == 1 &&
3745 getSize(operandType(right)) == 1)
3748 genMultOneByte (left, right, result);
3752 /* should have been converted to function call */
3753 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3754 getSize(OP_SYMBOL(right)->type));
3758 freeAsmop (result, NULL, ic, TRUE);
3759 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3760 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3763 /*-----------------------------------------------------------------*/
3764 /* genDivbits :- division of bits */
3765 /*-----------------------------------------------------------------*/
3767 genDivbits (operand * left,
3774 D(emitcode ("; genDivbits",""));
3776 /* the result must be bit */
3777 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3778 l = aopGet (AOP (left), 0, FALSE, FALSE);
3782 emitcode ("div", "ab");
3783 emitcode ("rrc", "a");
3784 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3787 /*-----------------------------------------------------------------*/
3788 /* genDivOneByte : 8 bit division */
3789 /*-----------------------------------------------------------------*/
3791 genDivOneByte (operand * left,
3795 sym_link *opetype = operandType (result);
3800 D(emitcode ("; genDivOneByte",""));
3802 size = AOP_SIZE (result) - 1;
3804 /* signed or unsigned */
3805 if (SPEC_USIGN (opetype))
3807 /* unsigned is easy */
3808 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3809 l = aopGet (AOP (left), 0, FALSE, FALSE);
3811 emitcode ("div", "ab");
3812 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3814 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3818 /* signed is a little bit more difficult */
3820 /* save the signs of the operands */
3821 l = aopGet (AOP (left), 0, FALSE, FALSE);
3823 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3824 emitcode ("push", "acc"); /* save it on the stack */
3826 /* now sign adjust for both left & right */
3827 l = aopGet (AOP (right), 0, FALSE, FALSE);
3829 lbl = newiTempLabel (NULL);
3830 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3831 emitcode ("cpl", "a");
3832 emitcode ("inc", "a");
3833 emitcode ("", "%05d$:", (lbl->key + 100));
3834 emitcode ("mov", "b,a");
3836 /* sign adjust left side */
3837 l = aopGet (AOP (left), 0, FALSE, FALSE);
3840 lbl = newiTempLabel (NULL);
3841 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3842 emitcode ("cpl", "a");
3843 emitcode ("inc", "a");
3844 emitcode ("", "%05d$:", (lbl->key + 100));
3846 /* now the division */
3847 emitcode ("div", "ab");
3848 /* we are interested in the lower order
3850 emitcode ("mov", "b,a");
3851 lbl = newiTempLabel (NULL);
3852 emitcode ("pop", "acc");
3853 /* if there was an over flow we don't
3854 adjust the sign of the result */
3855 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3856 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3858 emitcode ("clr", "a");
3859 emitcode ("subb", "a,b");
3860 emitcode ("mov", "b,a");
3861 emitcode ("", "%05d$:", (lbl->key + 100));
3863 /* now we are done */
3864 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3867 emitcode ("mov", "c,b.7");
3868 emitcode ("subb", "a,acc");
3871 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3875 /*-----------------------------------------------------------------*/
3876 /* genDiv - generates code for division */
3877 /*-----------------------------------------------------------------*/
3881 operand *left = IC_LEFT (ic);
3882 operand *right = IC_RIGHT (ic);
3883 operand *result = IC_RESULT (ic);
3885 D(emitcode ("; genDiv",""));
3887 /* assign the amsops */
3888 aopOp (left, ic, FALSE);
3889 aopOp (right, ic, FALSE);
3890 aopOp (result, ic, TRUE);
3892 /* special cases first */
3894 if (AOP_TYPE (left) == AOP_CRY &&
3895 AOP_TYPE (right) == AOP_CRY)
3897 genDivbits (left, right, result);
3901 /* if both are of size == 1 */
3902 if (AOP_SIZE (left) == 1 &&
3903 AOP_SIZE (right) == 1)
3905 genDivOneByte (left, right, result);
3909 /* should have been converted to function call */
3912 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3913 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3914 freeAsmop (result, NULL, ic, TRUE);
3917 /*-----------------------------------------------------------------*/
3918 /* genModbits :- modulus of bits */
3919 /*-----------------------------------------------------------------*/
3921 genModbits (operand * left,
3928 D(emitcode ("; genModbits",""));
3930 /* the result must be bit */
3931 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3932 l = aopGet (AOP (left), 0, FALSE, FALSE);
3936 emitcode ("div", "ab");
3937 emitcode ("mov", "a,b");
3938 emitcode ("rrc", "a");
3939 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3942 /*-----------------------------------------------------------------*/
3943 /* genModOneByte : 8 bit modulus */
3944 /*-----------------------------------------------------------------*/
3946 genModOneByte (operand * left,
3950 sym_link *opetype = operandType (result);
3954 D(emitcode ("; genModOneByte",""));
3956 /* signed or unsigned */
3957 if (SPEC_USIGN (opetype))
3959 /* unsigned is easy */
3960 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3961 l = aopGet (AOP (left), 0, FALSE, FALSE);
3963 emitcode ("div", "ab");
3964 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3968 /* signed is a little bit more difficult */
3970 /* save the signs of the operands */
3971 l = aopGet (AOP (left), 0, FALSE, FALSE);
3974 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3975 emitcode ("push", "acc"); /* save it on the stack */
3977 /* now sign adjust for both left & right */
3978 l = aopGet (AOP (right), 0, FALSE, FALSE);
3981 lbl = newiTempLabel (NULL);
3982 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3983 emitcode ("cpl", "a");
3984 emitcode ("inc", "a");
3985 emitcode ("", "%05d$:", (lbl->key + 100));
3986 emitcode ("mov", "b,a");
3988 /* sign adjust left side */
3989 l = aopGet (AOP (left), 0, FALSE, FALSE);
3992 lbl = newiTempLabel (NULL);
3993 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3994 emitcode ("cpl", "a");
3995 emitcode ("inc", "a");
3996 emitcode ("", "%05d$:", (lbl->key + 100));
3998 /* now the multiplication */
3999 emitcode ("div", "ab");
4000 /* we are interested in the lower order
4002 lbl = newiTempLabel (NULL);
4003 emitcode ("pop", "acc");
4004 /* if there was an over flow we don't
4005 adjust the sign of the result */
4006 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4007 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4009 emitcode ("clr", "a");
4010 emitcode ("subb", "a,b");
4011 emitcode ("mov", "b,a");
4012 emitcode ("", "%05d$:", (lbl->key + 100));
4014 /* now we are done */
4015 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4019 /*-----------------------------------------------------------------*/
4020 /* genMod - generates code for division */
4021 /*-----------------------------------------------------------------*/
4025 operand *left = IC_LEFT (ic);
4026 operand *right = IC_RIGHT (ic);
4027 operand *result = IC_RESULT (ic);
4029 D(emitcode ("; genMod",""));
4031 /* assign the amsops */
4032 aopOp (left, ic, FALSE);
4033 aopOp (right, ic, FALSE);
4034 aopOp (result, ic, TRUE);
4036 /* special cases first */
4038 if (AOP_TYPE (left) == AOP_CRY &&
4039 AOP_TYPE (right) == AOP_CRY)
4041 genModbits (left, right, result);
4045 /* if both are of size == 1 */
4046 if (AOP_SIZE (left) == 1 &&
4047 AOP_SIZE (right) == 1)
4049 genModOneByte (left, right, result);
4053 /* should have been converted to function call */
4057 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4058 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4059 freeAsmop (result, NULL, ic, TRUE);
4062 /*-----------------------------------------------------------------*/
4063 /* genIfxJump :- will create a jump depending on the ifx */
4064 /*-----------------------------------------------------------------*/
4066 genIfxJump (iCode * ic, char *jval)
4069 symbol *tlbl = newiTempLabel (NULL);
4072 D(emitcode ("; genIfxJump",""));
4074 /* if true label then we jump if condition
4078 jlbl = IC_TRUE (ic);
4079 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4080 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4084 /* false label is present */
4085 jlbl = IC_FALSE (ic);
4086 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4087 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4089 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4090 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4092 emitcode (inst, "%05d$", tlbl->key + 100);
4093 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4094 emitcode ("", "%05d$:", tlbl->key + 100);
4096 /* mark the icode as generated */
4100 /*-----------------------------------------------------------------*/
4101 /* genCmp :- greater or less than comparison */
4102 /*-----------------------------------------------------------------*/
4104 genCmp (operand * left, operand * right,
4105 operand * result, iCode * ifx, int sign, iCode *ic)
4107 int size, offset = 0;
4108 unsigned long lit = 0L;
4111 D(emitcode ("; genCmp",""));
4113 /* if left & right are bit variables */
4114 if (AOP_TYPE (left) == AOP_CRY &&
4115 AOP_TYPE (right) == AOP_CRY)
4117 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4118 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4122 /* subtract right from left if at the
4123 end the carry flag is set then we know that
4124 left is greater than right */
4125 size = max (AOP_SIZE (left), AOP_SIZE (right));
4127 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4128 if ((size == 1) && !sign &&
4129 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4131 symbol *lbl = newiTempLabel (NULL);
4132 emitcode ("cjne", "%s,%s,%05d$",
4133 aopGet (AOP (left), offset, FALSE, FALSE),
4134 aopGet (AOP (right), offset, FALSE, FALSE),
4136 emitcode ("", "%05d$:", lbl->key + 100);
4140 if (AOP_TYPE (right) == AOP_LIT)
4142 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4143 /* optimize if(x < 0) or if(x >= 0) */
4152 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4153 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4155 genIfxJump (ifx, "acc.7");
4159 emitcode ("rlc", "a");
4167 rightInB = aopGetUsesAcc(AOP (right), offset);
4169 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4170 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4171 if (sign && size == 0)
4173 emitcode ("xrl", "a,#0x80");
4174 if (AOP_TYPE (right) == AOP_LIT)
4176 unsigned long lit = (unsigned long)
4177 floatFromVal (AOP (right)->aopu.aop_lit);
4178 emitcode ("subb", "a,#0x%02x",
4179 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4184 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4185 emitcode ("xrl", "b,#0x80");
4186 emitcode ("subb", "a,b");
4192 emitcode ("subb", "a,b");
4194 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4202 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4203 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4204 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4210 /* if the result is used in the next
4211 ifx conditional branch then generate
4212 code a little differently */
4214 genIfxJump (ifx, "c");
4217 /* leave the result in acc */
4221 /*-----------------------------------------------------------------*/
4222 /* genCmpGt :- greater than comparison */
4223 /*-----------------------------------------------------------------*/
4225 genCmpGt (iCode * ic, iCode * ifx)
4227 operand *left, *right, *result;
4228 sym_link *letype, *retype;
4231 D(emitcode ("; genCmpGt",""));
4233 left = IC_LEFT (ic);
4234 right = IC_RIGHT (ic);
4235 result = IC_RESULT (ic);
4237 letype = getSpec (operandType (left));
4238 retype = getSpec (operandType (right));
4239 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4240 /* assign the amsops */
4241 aopOp (left, ic, FALSE);
4242 aopOp (right, ic, FALSE);
4243 aopOp (result, ic, TRUE);
4245 genCmp (right, left, result, ifx, sign,ic);
4247 freeAsmop (result, NULL, ic, TRUE);
4250 /*-----------------------------------------------------------------*/
4251 /* genCmpLt - less than comparisons */
4252 /*-----------------------------------------------------------------*/
4254 genCmpLt (iCode * ic, iCode * ifx)
4256 operand *left, *right, *result;
4257 sym_link *letype, *retype;
4260 D(emitcode ("; genCmpLt",""));
4262 left = IC_LEFT (ic);
4263 right = IC_RIGHT (ic);
4264 result = IC_RESULT (ic);
4266 letype = getSpec (operandType (left));
4267 retype = getSpec (operandType (right));
4268 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4270 /* assign the amsops */
4271 aopOp (left, ic, FALSE);
4272 aopOp (right, ic, FALSE);
4273 aopOp (result, ic, TRUE);
4275 genCmp (left, right, result, ifx, sign,ic);
4277 freeAsmop (result, NULL, ic, TRUE);
4280 /*-----------------------------------------------------------------*/
4281 /* gencjneshort - compare and jump if not equal */
4282 /*-----------------------------------------------------------------*/
4284 gencjneshort (operand * left, operand * right, symbol * lbl)
4286 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4288 unsigned long lit = 0L;
4290 /* if the left side is a literal or
4291 if the right is in a pointer register and left
4293 if ((AOP_TYPE (left) == AOP_LIT) ||
4294 (AOP_TYPE (left) == AOP_IMMD) ||
4295 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4302 if (AOP_TYPE (right) == AOP_LIT)
4303 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4305 /* if the right side is a literal then anything goes */
4306 if (AOP_TYPE (right) == AOP_LIT &&
4307 AOP_TYPE (left) != AOP_DIR &&
4308 AOP_TYPE (left) != AOP_IMMD)
4312 emitcode ("cjne", "%s,%s,%05d$",
4313 aopGet (AOP (left), offset, FALSE, FALSE),
4314 aopGet (AOP (right), offset, FALSE, FALSE),
4320 /* if the right side is in a register or in direct space or
4321 if the left is a pointer register & right is not */
4322 else if (AOP_TYPE (right) == AOP_REG ||
4323 AOP_TYPE (right) == AOP_DIR ||
4324 AOP_TYPE (right) == AOP_LIT ||
4325 AOP_TYPE (right) == AOP_IMMD ||
4326 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4327 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4331 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4332 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4333 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4334 emitcode ("jnz", "%05d$", lbl->key + 100);
4336 emitcode ("cjne", "a,%s,%05d$",
4337 aopGet (AOP (right), offset, FALSE, TRUE),
4344 /* right is a pointer reg need both a & b */
4347 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4348 if (strcmp (l, "b"))
4349 emitcode ("mov", "b,%s", l);
4350 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4351 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4357 /*-----------------------------------------------------------------*/
4358 /* gencjne - compare and jump if not equal */
4359 /*-----------------------------------------------------------------*/
4361 gencjne (operand * left, operand * right, symbol * lbl)
4363 symbol *tlbl = newiTempLabel (NULL);
4365 gencjneshort (left, right, lbl);
4367 emitcode ("mov", "a,%s", one);
4368 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4369 emitcode ("", "%05d$:", lbl->key + 100);
4370 emitcode ("clr", "a");
4371 emitcode ("", "%05d$:", tlbl->key + 100);
4374 /*-----------------------------------------------------------------*/
4375 /* genCmpEq - generates code for equal to */
4376 /*-----------------------------------------------------------------*/
4378 genCmpEq (iCode * ic, iCode * ifx)
4380 operand *left, *right, *result;
4382 D(emitcode ("; genCmpEq",""));
4384 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4385 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4386 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4388 /* if literal, literal on the right or
4389 if the right is in a pointer register and left
4391 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4392 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4394 operand *t = IC_RIGHT (ic);
4395 IC_RIGHT (ic) = IC_LEFT (ic);
4399 if (ifx && !AOP_SIZE (result))
4402 /* if they are both bit variables */
4403 if (AOP_TYPE (left) == AOP_CRY &&
4404 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4406 if (AOP_TYPE (right) == AOP_LIT)
4408 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4411 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4412 emitcode ("cpl", "c");
4416 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4420 emitcode ("clr", "c");
4422 /* AOP_TYPE(right) == AOP_CRY */
4426 symbol *lbl = newiTempLabel (NULL);
4427 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4428 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4429 emitcode ("cpl", "c");
4430 emitcode ("", "%05d$:", (lbl->key + 100));
4432 /* if true label then we jump if condition
4434 tlbl = newiTempLabel (NULL);
4437 emitcode ("jnc", "%05d$", tlbl->key + 100);
4438 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4442 emitcode ("jc", "%05d$", tlbl->key + 100);
4443 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4445 emitcode ("", "%05d$:", tlbl->key + 100);
4449 tlbl = newiTempLabel (NULL);
4450 gencjneshort (left, right, tlbl);
4453 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4454 emitcode ("", "%05d$:", tlbl->key + 100);
4458 symbol *lbl = newiTempLabel (NULL);
4459 emitcode ("sjmp", "%05d$", lbl->key + 100);
4460 emitcode ("", "%05d$:", tlbl->key + 100);
4461 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4462 emitcode ("", "%05d$:", lbl->key + 100);
4465 /* mark the icode as generated */
4470 /* if they are both bit variables */
4471 if (AOP_TYPE (left) == AOP_CRY &&
4472 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4474 if (AOP_TYPE (right) == AOP_LIT)
4476 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4479 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4480 emitcode ("cpl", "c");
4484 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4488 emitcode ("clr", "c");
4490 /* AOP_TYPE(right) == AOP_CRY */
4494 symbol *lbl = newiTempLabel (NULL);
4495 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4496 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4497 emitcode ("cpl", "c");
4498 emitcode ("", "%05d$:", (lbl->key + 100));
4501 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4508 genIfxJump (ifx, "c");
4511 /* if the result is used in an arithmetic operation
4512 then put the result in place */
4517 gencjne (left, right, newiTempLabel (NULL));
4518 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4520 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4525 genIfxJump (ifx, "a");
4528 /* if the result is used in an arithmetic operation
4529 then put the result in place */
4530 if (AOP_TYPE (result) != AOP_CRY)
4532 /* leave the result in acc */
4536 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4537 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4538 freeAsmop (result, NULL, ic, TRUE);
4541 /*-----------------------------------------------------------------*/
4542 /* ifxForOp - returns the icode containing the ifx for operand */
4543 /*-----------------------------------------------------------------*/
4545 ifxForOp (operand * op, iCode * ic)
4547 /* if true symbol then needs to be assigned */
4548 if (IS_TRUE_SYMOP (op))
4551 /* if this has register type condition and
4552 the next instruction is ifx with the same operand
4553 and live to of the operand is upto the ifx only then */
4555 ic->next->op == IFX &&
4556 IC_COND (ic->next)->key == op->key &&
4557 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4563 /*-----------------------------------------------------------------*/
4564 /* hasInc - operand is incremented before any other use */
4565 /*-----------------------------------------------------------------*/
4567 hasInc (operand *op, iCode *ic,int osize)
4569 sym_link *type = operandType(op);
4570 sym_link *retype = getSpec (type);
4571 iCode *lic = ic->next;
4574 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4575 if (!IS_SYMOP(op)) return NULL;
4577 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4578 if (IS_AGGREGATE(type->next)) return NULL;
4579 if (osize != (isize = getSize(type->next))) return NULL;
4582 /* if operand of the form op = op + <sizeof *op> */
4583 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4584 isOperandEqual(IC_RESULT(lic),op) &&
4585 isOperandLiteral(IC_RIGHT(lic)) &&
4586 operandLitValue(IC_RIGHT(lic)) == isize) {
4589 /* if the operand used or deffed */
4590 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4593 /* if GOTO or IFX */
4594 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4600 /*-----------------------------------------------------------------*/
4601 /* genAndOp - for && operation */
4602 /*-----------------------------------------------------------------*/
4604 genAndOp (iCode * ic)
4606 operand *left, *right, *result;
4609 D(emitcode ("; genAndOp",""));
4611 /* note here that && operations that are in an
4612 if statement are taken away by backPatchLabels
4613 only those used in arthmetic operations remain */
4614 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4615 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4616 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4618 /* if both are bit variables */
4619 if (AOP_TYPE (left) == AOP_CRY &&
4620 AOP_TYPE (right) == AOP_CRY)
4622 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4623 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4628 tlbl = newiTempLabel (NULL);
4630 emitcode ("jz", "%05d$", tlbl->key + 100);
4632 emitcode ("", "%05d$:", tlbl->key + 100);
4636 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4637 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4638 freeAsmop (result, NULL, ic, TRUE);
4642 /*-----------------------------------------------------------------*/
4643 /* genOrOp - for || operation */
4644 /*-----------------------------------------------------------------*/
4646 genOrOp (iCode * ic)
4648 operand *left, *right, *result;
4651 D(emitcode ("; genOrOp",""));
4653 /* note here that || operations that are in an
4654 if statement are taken away by backPatchLabels
4655 only those used in arthmetic operations remain */
4656 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4657 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4658 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4660 /* if both are bit variables */
4661 if (AOP_TYPE (left) == AOP_CRY &&
4662 AOP_TYPE (right) == AOP_CRY)
4664 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4665 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4670 tlbl = newiTempLabel (NULL);
4672 emitcode ("jnz", "%05d$", tlbl->key + 100);
4674 emitcode ("", "%05d$:", tlbl->key + 100);
4678 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4679 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4680 freeAsmop (result, NULL, ic, TRUE);
4683 /*-----------------------------------------------------------------*/
4684 /* isLiteralBit - test if lit == 2^n */
4685 /*-----------------------------------------------------------------*/
4687 isLiteralBit (unsigned long lit)
4689 unsigned long pw[32] =
4690 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4691 0x100L, 0x200L, 0x400L, 0x800L,
4692 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4693 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4694 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4695 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4696 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4699 for (idx = 0; idx < 32; idx++)
4705 /*-----------------------------------------------------------------*/
4706 /* continueIfTrue - */
4707 /*-----------------------------------------------------------------*/
4709 continueIfTrue (iCode * ic)
4712 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4716 /*-----------------------------------------------------------------*/
4718 /*-----------------------------------------------------------------*/
4720 jumpIfTrue (iCode * ic)
4723 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4727 /*-----------------------------------------------------------------*/
4728 /* jmpTrueOrFalse - */
4729 /*-----------------------------------------------------------------*/
4731 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4733 // ugly but optimized by peephole
4736 symbol *nlbl = newiTempLabel (NULL);
4737 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4738 emitcode ("", "%05d$:", tlbl->key + 100);
4739 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4740 emitcode ("", "%05d$:", nlbl->key + 100);
4744 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4745 emitcode ("", "%05d$:", tlbl->key + 100);
4750 /*-----------------------------------------------------------------*/
4751 /* genAnd - code for and */
4752 /*-----------------------------------------------------------------*/
4754 genAnd (iCode * ic, iCode * ifx)
4756 operand *left, *right, *result;
4757 int size, offset = 0;
4758 unsigned long lit = 0L;
4762 D(emitcode ("; genAnd",""));
4764 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4765 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4766 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4769 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4771 AOP_TYPE (left), AOP_TYPE (right));
4772 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4774 AOP_SIZE (left), AOP_SIZE (right));
4777 /* if left is a literal & right is not then exchange them */
4778 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4779 AOP_NEEDSACC (left))
4781 operand *tmp = right;
4786 /* if result = right then exchange them */
4787 if (sameRegs (AOP (result), AOP (right)))
4789 operand *tmp = right;
4794 /* if right is bit then exchange them */
4795 if (AOP_TYPE (right) == AOP_CRY &&
4796 AOP_TYPE (left) != AOP_CRY)
4798 operand *tmp = right;
4802 if (AOP_TYPE (right) == AOP_LIT)
4803 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4805 size = AOP_SIZE (result);
4808 // result = bit & yy;
4809 if (AOP_TYPE (left) == AOP_CRY)
4811 // c = bit & literal;
4812 if (AOP_TYPE (right) == AOP_LIT)
4816 if (size && sameRegs (AOP (result), AOP (left)))
4819 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4824 if (size && (AOP_TYPE (result) == AOP_CRY))
4826 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4829 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4834 emitcode ("clr", "c");
4839 if (AOP_TYPE (right) == AOP_CRY)
4842 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4843 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4848 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4850 emitcode ("rrc", "a");
4851 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4859 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4860 genIfxJump (ifx, "c");
4864 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4865 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4866 if ((AOP_TYPE (right) == AOP_LIT) &&
4867 (AOP_TYPE (result) == AOP_CRY) &&
4868 (AOP_TYPE (left) != AOP_CRY))
4870 int posbit = isLiteralBit (lit);
4875 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4878 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4884 sprintf (buffer, "acc.%d", posbit & 0x07);
4885 genIfxJump (ifx, buffer);
4892 symbol *tlbl = newiTempLabel (NULL);
4893 int sizel = AOP_SIZE (left);
4895 emitcode ("setb", "c");
4898 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4900 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4902 if ((posbit = isLiteralBit (bytelit)) != 0)
4903 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4906 if (bytelit != 0x0FFL)
4907 emitcode ("anl", "a,%s",
4908 aopGet (AOP (right), offset, FALSE, TRUE));
4909 emitcode ("jnz", "%05d$", tlbl->key + 100);
4914 // bit = left & literal
4917 emitcode ("clr", "c");
4918 emitcode ("", "%05d$:", tlbl->key + 100);
4920 // if(left & literal)
4924 jmpTrueOrFalse (ifx, tlbl);
4932 /* if left is same as result */
4933 if (sameRegs (AOP (result), AOP (left)))
4935 for (; size--; offset++)
4937 if (AOP_TYPE (right) == AOP_LIT)
4939 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4941 else if (bytelit == 0)
4943 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4945 else if (IS_AOP_PREG (result))
4947 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4948 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4949 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4952 emitcode ("anl", "%s,%s",
4953 aopGet (AOP (left), offset, FALSE, TRUE),
4954 aopGet (AOP (right), offset, FALSE, FALSE));
4958 if (AOP_TYPE (left) == AOP_ACC)
4959 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4962 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4963 if (IS_AOP_PREG (result))
4965 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4966 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4970 emitcode ("anl", "%s,a",
4971 aopGet (AOP (left), offset, FALSE, TRUE));
4978 // left & result in different registers
4979 if (AOP_TYPE (result) == AOP_CRY)
4982 // if(size), result in bit
4983 // if(!size && ifx), conditional oper: if(left & right)
4984 symbol *tlbl = newiTempLabel (NULL);
4985 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4987 emitcode ("setb", "c");
4990 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4991 emitcode ("anl", "a,%s",
4992 aopGet (AOP (right), offset, FALSE, FALSE));
4994 if (AOP_TYPE(left)==AOP_ACC) {
4995 emitcode("mov", "b,a");
4996 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4997 emitcode("anl", "a,b");
4999 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5000 emitcode ("anl", "a,%s",
5001 aopGet (AOP (left), offset, FALSE, FALSE));
5004 emitcode ("jnz", "%05d$", tlbl->key + 100);
5010 emitcode ("", "%05d$:", tlbl->key + 100);
5014 jmpTrueOrFalse (ifx, tlbl);
5018 for (; (size--); offset++)
5021 // result = left & right
5022 if (AOP_TYPE (right) == AOP_LIT)
5024 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5026 aopPut (AOP (result),
5027 aopGet (AOP (left), offset, FALSE, FALSE),
5029 isOperandVolatile (result, FALSE));
5032 else if (bytelit == 0)
5034 /* dummy read of volatile operand */
5035 if (isOperandVolatile (left, FALSE))
5036 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5037 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5041 // faster than result <- left, anl result,right
5042 // and better if result is SFR
5043 if (AOP_TYPE (left) == AOP_ACC)
5044 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5047 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5048 emitcode ("anl", "a,%s",
5049 aopGet (AOP (left), offset, FALSE, FALSE));
5051 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5057 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5058 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5059 freeAsmop (result, NULL, ic, TRUE);
5062 /*-----------------------------------------------------------------*/
5063 /* genOr - code for or */
5064 /*-----------------------------------------------------------------*/
5066 genOr (iCode * ic, iCode * ifx)
5068 operand *left, *right, *result;
5069 int size, offset = 0;
5070 unsigned long lit = 0L;
5072 D(emitcode ("; genOr",""));
5074 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5075 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5076 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5079 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5081 AOP_TYPE (left), AOP_TYPE (right));
5082 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5084 AOP_SIZE (left), AOP_SIZE (right));
5087 /* if left is a literal & right is not then exchange them */
5088 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5089 AOP_NEEDSACC (left))
5091 operand *tmp = right;
5096 /* if result = right then exchange them */
5097 if (sameRegs (AOP (result), AOP (right)))
5099 operand *tmp = right;
5104 /* if right is bit then exchange them */
5105 if (AOP_TYPE (right) == AOP_CRY &&
5106 AOP_TYPE (left) != AOP_CRY)
5108 operand *tmp = right;
5112 if (AOP_TYPE (right) == AOP_LIT)
5113 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5115 size = AOP_SIZE (result);
5119 if (AOP_TYPE (left) == AOP_CRY)
5121 if (AOP_TYPE (right) == AOP_LIT)
5123 // c = bit | literal;
5126 // lit != 0 => result = 1
5127 if (AOP_TYPE (result) == AOP_CRY)
5130 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5132 continueIfTrue (ifx);
5135 emitcode ("setb", "c");
5139 // lit == 0 => result = left
5140 if (size && sameRegs (AOP (result), AOP (left)))
5142 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5147 if (AOP_TYPE (right) == AOP_CRY)
5150 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5151 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5156 symbol *tlbl = newiTempLabel (NULL);
5157 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5158 emitcode ("setb", "c");
5159 emitcode ("jb", "%s,%05d$",
5160 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5162 emitcode ("jnz", "%05d$", tlbl->key + 100);
5163 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5165 jmpTrueOrFalse (ifx, tlbl);
5171 emitcode ("", "%05d$:", tlbl->key + 100);
5180 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5181 genIfxJump (ifx, "c");
5185 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5186 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5187 if ((AOP_TYPE (right) == AOP_LIT) &&
5188 (AOP_TYPE (result) == AOP_CRY) &&
5189 (AOP_TYPE (left) != AOP_CRY))
5195 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5197 continueIfTrue (ifx);
5202 // lit = 0, result = boolean(left)
5204 emitcode ("setb", "c");
5208 symbol *tlbl = newiTempLabel (NULL);
5209 emitcode ("jnz", "%05d$", tlbl->key + 100);
5211 emitcode ("", "%05d$:", tlbl->key + 100);
5215 genIfxJump (ifx, "a");
5223 /* if left is same as result */
5224 if (sameRegs (AOP (result), AOP (left)))
5226 for (; size--; offset++)
5228 if (AOP_TYPE (right) == AOP_LIT)
5230 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5232 /* dummy read of volatile operand */
5233 if (isOperandVolatile (left, FALSE))
5234 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5238 else if (IS_AOP_PREG (left))
5240 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5241 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5242 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5245 emitcode ("orl", "%s,%s",
5246 aopGet (AOP (left), offset, FALSE, TRUE),
5247 aopGet (AOP (right), offset, FALSE, FALSE));
5251 if (AOP_TYPE (left) == AOP_ACC)
5252 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5255 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5256 if (IS_AOP_PREG (left))
5258 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5259 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5262 emitcode ("orl", "%s,a",
5263 aopGet (AOP (left), offset, FALSE, TRUE));
5270 // left & result in different registers
5271 if (AOP_TYPE (result) == AOP_CRY)
5274 // if(size), result in bit
5275 // if(!size && ifx), conditional oper: if(left | right)
5276 symbol *tlbl = newiTempLabel (NULL);
5277 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5279 emitcode ("setb", "c");
5282 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5283 emitcode ("orl", "a,%s",
5284 aopGet (AOP (right), offset, FALSE, FALSE));
5286 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5287 emitcode ("orl", "a,%s",
5288 aopGet (AOP (left), offset, FALSE, FALSE));
5290 emitcode ("jnz", "%05d$", tlbl->key + 100);
5296 emitcode ("", "%05d$:", tlbl->key + 100);
5300 jmpTrueOrFalse (ifx, tlbl);
5303 for (; (size--); offset++)
5306 // result = left & right
5307 if (AOP_TYPE (right) == AOP_LIT)
5309 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5311 aopPut (AOP (result),
5312 aopGet (AOP (left), offset, FALSE, FALSE),
5314 isOperandVolatile (result, FALSE));
5318 // faster than result <- left, anl result,right
5319 // and better if result is SFR
5320 if (AOP_TYPE (left) == AOP_ACC)
5321 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5324 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5325 emitcode ("orl", "a,%s",
5326 aopGet (AOP (left), offset, FALSE, FALSE));
5328 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5333 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5334 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5335 freeAsmop (result, NULL, ic, TRUE);
5338 /*-----------------------------------------------------------------*/
5339 /* genXor - code for xclusive or */
5340 /*-----------------------------------------------------------------*/
5342 genXor (iCode * ic, iCode * ifx)
5344 operand *left, *right, *result;
5345 int size, offset = 0;
5346 unsigned long lit = 0L;
5348 D(emitcode ("; genXor",""));
5350 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5351 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5352 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5355 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5357 AOP_TYPE (left), AOP_TYPE (right));
5358 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5360 AOP_SIZE (left), AOP_SIZE (right));
5363 /* if left is a literal & right is not ||
5364 if left needs acc & right does not */
5365 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5366 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5368 operand *tmp = right;
5373 /* if result = right then exchange them */
5374 if (sameRegs (AOP (result), AOP (right)))
5376 operand *tmp = right;
5381 /* if right is bit then exchange them */
5382 if (AOP_TYPE (right) == AOP_CRY &&
5383 AOP_TYPE (left) != AOP_CRY)
5385 operand *tmp = right;
5389 if (AOP_TYPE (right) == AOP_LIT)
5390 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5392 size = AOP_SIZE (result);
5396 if (AOP_TYPE (left) == AOP_CRY)
5398 if (AOP_TYPE (right) == AOP_LIT)
5400 // c = bit & literal;
5403 // lit>>1 != 0 => result = 1
5404 if (AOP_TYPE (result) == AOP_CRY)
5407 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5409 continueIfTrue (ifx);
5412 emitcode ("setb", "c");
5419 // lit == 0, result = left
5420 if (size && sameRegs (AOP (result), AOP (left)))
5422 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5426 // lit == 1, result = not(left)
5427 if (size && sameRegs (AOP (result), AOP (left)))
5429 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5434 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5435 emitcode ("cpl", "c");
5444 symbol *tlbl = newiTempLabel (NULL);
5445 if (AOP_TYPE (right) == AOP_CRY)
5448 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5452 int sizer = AOP_SIZE (right);
5454 // if val>>1 != 0, result = 1
5455 emitcode ("setb", "c");
5458 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5460 // test the msb of the lsb
5461 emitcode ("anl", "a,#0xfe");
5462 emitcode ("jnz", "%05d$", tlbl->key + 100);
5466 emitcode ("rrc", "a");
5468 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5469 emitcode ("cpl", "c");
5470 emitcode ("", "%05d$:", (tlbl->key + 100));
5477 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5478 genIfxJump (ifx, "c");
5482 if (sameRegs (AOP (result), AOP (left)))
5484 /* if left is same as result */
5485 for (; size--; offset++)
5487 if (AOP_TYPE (right) == AOP_LIT)
5489 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5491 else if (IS_AOP_PREG (left))
5493 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5494 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5495 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5498 emitcode ("xrl", "%s,%s",
5499 aopGet (AOP (left), offset, FALSE, TRUE),
5500 aopGet (AOP (right), offset, FALSE, FALSE));
5504 if (AOP_TYPE (left) == AOP_ACC)
5505 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5508 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5509 if (IS_AOP_PREG (left))
5511 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5512 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5515 emitcode ("xrl", "%s,a",
5516 aopGet (AOP (left), offset, FALSE, TRUE));
5523 // left & result in different registers
5524 if (AOP_TYPE (result) == AOP_CRY)
5527 // if(size), result in bit
5528 // if(!size && ifx), conditional oper: if(left ^ right)
5529 symbol *tlbl = newiTempLabel (NULL);
5530 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5532 emitcode ("setb", "c");
5535 if ((AOP_TYPE (right) == AOP_LIT) &&
5536 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5538 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5542 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5543 emitcode ("xrl", "a,%s",
5544 aopGet (AOP (right), offset, FALSE, FALSE));
5546 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5547 emitcode ("xrl", "a,%s",
5548 aopGet (AOP (left), offset, FALSE, FALSE));
5551 emitcode ("jnz", "%05d$", tlbl->key + 100);
5557 emitcode ("", "%05d$:", tlbl->key + 100);
5561 jmpTrueOrFalse (ifx, tlbl);
5564 for (; (size--); offset++)
5567 // result = left & right
5568 if (AOP_TYPE (right) == AOP_LIT)
5570 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5572 aopPut (AOP (result),
5573 aopGet (AOP (left), offset, FALSE, FALSE),
5575 isOperandVolatile (result, FALSE));
5579 // faster than result <- left, anl result,right
5580 // and better if result is SFR
5581 if (AOP_TYPE (left) == AOP_ACC)
5582 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5585 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5586 emitcode ("xrl", "a,%s",
5587 aopGet (AOP (left), offset, FALSE, TRUE));
5589 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5594 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5595 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5596 freeAsmop (result, NULL, ic, TRUE);
5599 /*-----------------------------------------------------------------*/
5600 /* genInline - write the inline code out */
5601 /*-----------------------------------------------------------------*/
5603 genInline (iCode * ic)
5605 char *buffer, *bp, *bp1;
5607 D(emitcode ("; genInline",""));
5609 _G.inLine += (!options.asmpeep);
5611 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5612 strcpy (buffer, IC_INLINE (ic));
5614 /* emit each line as a code */
5639 /* emitcode("",buffer); */
5640 _G.inLine -= (!options.asmpeep);
5643 /*-----------------------------------------------------------------*/
5644 /* genRRC - rotate right with carry */
5645 /*-----------------------------------------------------------------*/
5649 operand *left, *result;
5650 int size, offset = 0;
5653 D(emitcode ("; genRRC",""));
5655 /* rotate right with carry */
5656 left = IC_LEFT (ic);
5657 result = IC_RESULT (ic);
5658 aopOp (left, ic, FALSE);
5659 aopOp (result, ic, FALSE);
5661 /* move it to the result */
5662 size = AOP_SIZE (result);
5664 if (size == 1) { /* special case for 1 byte */
5665 l = aopGet (AOP (left), offset, FALSE, FALSE);
5667 emitcode ("rr", "a");
5673 l = aopGet (AOP (left), offset, FALSE, FALSE);
5675 emitcode ("rrc", "a");
5676 if (AOP_SIZE (result) > 1)
5677 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5679 /* now we need to put the carry into the
5680 highest order byte of the result */
5681 if (AOP_SIZE (result) > 1)
5683 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5686 emitcode ("mov", "acc.7,c");
5688 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5689 freeAsmop (left, NULL, ic, TRUE);
5690 freeAsmop (result, NULL, ic, TRUE);
5693 /*-----------------------------------------------------------------*/
5694 /* genRLC - generate code for rotate left with carry */
5695 /*-----------------------------------------------------------------*/
5699 operand *left, *result;
5700 int size, offset = 0;
5703 D(emitcode ("; genRLC",""));
5705 /* rotate right with carry */
5706 left = IC_LEFT (ic);
5707 result = IC_RESULT (ic);
5708 aopOp (left, ic, FALSE);
5709 aopOp (result, ic, FALSE);
5711 /* move it to the result */
5712 size = AOP_SIZE (result);
5716 l = aopGet (AOP (left), offset, FALSE, FALSE);
5718 if (size == 0) { /* special case for 1 byte */
5722 emitcode ("add", "a,acc");
5723 if (AOP_SIZE (result) > 1)
5724 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5727 l = aopGet (AOP (left), offset, FALSE, FALSE);
5729 emitcode ("rlc", "a");
5730 if (AOP_SIZE (result) > 1)
5731 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5734 /* now we need to put the carry into the
5735 highest order byte of the result */
5736 if (AOP_SIZE (result) > 1)
5738 l = aopGet (AOP (result), 0, FALSE, FALSE);
5741 emitcode ("mov", "acc.0,c");
5743 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5744 freeAsmop (left, NULL, ic, TRUE);
5745 freeAsmop (result, NULL, ic, TRUE);
5748 /*-----------------------------------------------------------------*/
5749 /* genGetHbit - generates code get highest order bit */
5750 /*-----------------------------------------------------------------*/
5752 genGetHbit (iCode * ic)
5754 operand *left, *result;
5756 D(emitcode ("; genGetHbit",""));
5758 left = IC_LEFT (ic);
5759 result = IC_RESULT (ic);
5760 aopOp (left, ic, FALSE);
5761 aopOp (result, ic, FALSE);
5763 /* get the highest order byte into a */
5764 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5765 if (AOP_TYPE (result) == AOP_CRY)
5767 emitcode ("rlc", "a");
5772 emitcode ("rl", "a");
5773 emitcode ("anl", "a,#0x01");
5778 freeAsmop (left, NULL, ic, TRUE);
5779 freeAsmop (result, NULL, ic, TRUE);
5782 /*-----------------------------------------------------------------*/
5783 /* genSwap - generates code to swap nibbles or bytes */
5784 /*-----------------------------------------------------------------*/
5786 genSwap (iCode * ic)
5788 operand *left, *result;
5790 D(emitcode ("; genSwap",""));
5792 left = IC_LEFT (ic);
5793 result = IC_RESULT (ic);
5794 aopOp (left, ic, FALSE);
5795 aopOp (result, ic, FALSE);
5797 switch (AOP_SIZE (left))
5799 case 1: /* swap nibbles in byte */
5800 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5801 emitcode ("swap", "a");
5802 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5804 case 2: /* swap bytes in word */
5805 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
5807 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5808 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5809 0, isOperandVolatile (result, FALSE));
5810 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
5812 else if (operandsEqu (left, result))
5815 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5816 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
5818 emitcode ("mov", "b,a");
5821 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5822 0, isOperandVolatile (result, FALSE));
5823 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
5827 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5828 0, isOperandVolatile (result, FALSE));
5829 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
5830 1, isOperandVolatile (result, FALSE));
5834 wassertl(FALSE, "unsupported SWAP operand size");
5837 freeAsmop (left, NULL, ic, TRUE);
5838 freeAsmop (result, NULL, ic, TRUE);
5842 /*-----------------------------------------------------------------*/
5843 /* AccRol - rotate left accumulator by known count */
5844 /*-----------------------------------------------------------------*/
5846 AccRol (int shCount)
5848 shCount &= 0x0007; // shCount : 0..7
5855 emitcode ("rl", "a");
5858 emitcode ("rl", "a");
5859 emitcode ("rl", "a");
5862 emitcode ("swap", "a");
5863 emitcode ("rr", "a");
5866 emitcode ("swap", "a");
5869 emitcode ("swap", "a");
5870 emitcode ("rl", "a");
5873 emitcode ("rr", "a");
5874 emitcode ("rr", "a");
5877 emitcode ("rr", "a");
5882 /*-----------------------------------------------------------------*/
5883 /* AccLsh - left shift accumulator by known count */
5884 /*-----------------------------------------------------------------*/
5886 AccLsh (int shCount)
5891 emitcode ("add", "a,acc");
5892 else if (shCount == 2)
5894 emitcode ("add", "a,acc");
5895 emitcode ("add", "a,acc");
5899 /* rotate left accumulator */
5901 /* and kill the lower order bits */
5902 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5907 /*-----------------------------------------------------------------*/
5908 /* AccRsh - right shift accumulator by known count */
5909 /*-----------------------------------------------------------------*/
5911 AccRsh (int shCount)
5918 emitcode ("rrc", "a");
5922 /* rotate right accumulator */
5923 AccRol (8 - shCount);
5924 /* and kill the higher order bits */
5925 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5930 /*-----------------------------------------------------------------*/
5931 /* AccSRsh - signed right shift accumulator by known count */
5932 /*-----------------------------------------------------------------*/
5934 AccSRsh (int shCount)
5941 emitcode ("mov", "c,acc.7");
5942 emitcode ("rrc", "a");
5944 else if (shCount == 2)
5946 emitcode ("mov", "c,acc.7");
5947 emitcode ("rrc", "a");
5948 emitcode ("mov", "c,acc.7");
5949 emitcode ("rrc", "a");
5953 tlbl = newiTempLabel (NULL);
5954 /* rotate right accumulator */
5955 AccRol (8 - shCount);
5956 /* and kill the higher order bits */
5957 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5958 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5959 emitcode ("orl", "a,#0x%02x",
5960 (unsigned char) ~SRMask[shCount]);
5961 emitcode ("", "%05d$:", tlbl->key + 100);
5966 /*-----------------------------------------------------------------*/
5967 /* shiftR1Left2Result - shift right one byte from left to result */
5968 /*-----------------------------------------------------------------*/
5970 shiftR1Left2Result (operand * left, int offl,
5971 operand * result, int offr,
5972 int shCount, int sign)
5974 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5975 /* shift right accumulator */
5980 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5983 /*-----------------------------------------------------------------*/
5984 /* shiftL1Left2Result - shift left one byte from left to result */
5985 /*-----------------------------------------------------------------*/
5987 shiftL1Left2Result (operand * left, int offl,
5988 operand * result, int offr, int shCount)
5991 l = aopGet (AOP (left), offl, FALSE, FALSE);
5993 /* shift left accumulator */
5995 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5998 /*-----------------------------------------------------------------*/
5999 /* movLeft2Result - move byte from left to result */
6000 /*-----------------------------------------------------------------*/
6002 movLeft2Result (operand * left, int offl,
6003 operand * result, int offr, int sign)
6006 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6008 l = aopGet (AOP (left), offl, FALSE, FALSE);
6010 if (*l == '@' && (IS_AOP_PREG (result)))
6012 emitcode ("mov", "a,%s", l);
6013 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6018 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6021 /* MSB sign in acc.7 ! */
6022 if (getDataSize (left) == offl + 1)
6024 emitcode ("mov", "a,%s", l);
6025 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6032 /*-----------------------------------------------------------------*/
6033 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6034 /*-----------------------------------------------------------------*/
6038 emitcode ("rrc", "a");
6039 emitcode ("xch", "a,%s", x);
6040 emitcode ("rrc", "a");
6041 emitcode ("xch", "a,%s", x);
6044 /*-----------------------------------------------------------------*/
6045 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6046 /*-----------------------------------------------------------------*/
6050 emitcode ("xch", "a,%s", x);
6051 emitcode ("rlc", "a");
6052 emitcode ("xch", "a,%s", x);
6053 emitcode ("rlc", "a");
6056 /*-----------------------------------------------------------------*/
6057 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6058 /*-----------------------------------------------------------------*/
6062 emitcode ("xch", "a,%s", x);
6063 emitcode ("add", "a,acc");
6064 emitcode ("xch", "a,%s", x);
6065 emitcode ("rlc", "a");
6068 /*-----------------------------------------------------------------*/
6069 /* AccAXLsh - left shift a:x by known count (0..7) */
6070 /*-----------------------------------------------------------------*/
6072 AccAXLsh (char *x, int shCount)
6087 case 5: // AAAAABBB:CCCCCDDD
6089 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6091 emitcode ("anl", "a,#0x%02x",
6092 SLMask[shCount]); // BBB00000:CCCCCDDD
6094 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6096 AccRol (shCount); // DDDCCCCC:BBB00000
6098 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6100 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6102 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6104 emitcode ("anl", "a,#0x%02x",
6105 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6107 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6109 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6112 case 6: // AAAAAABB:CCCCCCDD
6113 emitcode ("anl", "a,#0x%02x",
6114 SRMask[shCount]); // 000000BB:CCCCCCDD
6115 emitcode ("mov", "c,acc.0"); // c = B
6116 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6118 AccAXRrl1 (x); // BCCCCCCD:D000000B
6119 AccAXRrl1 (x); // BBCCCCCC:DD000000
6121 emitcode("rrc","a");
6122 emitcode("xch","a,%s", x);
6123 emitcode("rrc","a");
6124 emitcode("mov","c,acc.0"); //<< get correct bit
6125 emitcode("xch","a,%s", x);
6127 emitcode("rrc","a");
6128 emitcode("xch","a,%s", x);
6129 emitcode("rrc","a");
6130 emitcode("xch","a,%s", x);
6133 case 7: // a:x <<= 7
6135 emitcode ("anl", "a,#0x%02x",
6136 SRMask[shCount]); // 0000000B:CCCCCCCD
6138 emitcode ("mov", "c,acc.0"); // c = B
6140 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6142 AccAXRrl1 (x); // BCCCCCCC:D0000000
6150 /*-----------------------------------------------------------------*/
6151 /* AccAXRsh - right shift a:x known count (0..7) */
6152 /*-----------------------------------------------------------------*/
6154 AccAXRsh (char *x, int shCount)
6162 AccAXRrl1 (x); // 0->a:x
6167 AccAXRrl1 (x); // 0->a:x
6170 AccAXRrl1 (x); // 0->a:x
6175 case 5: // AAAAABBB:CCCCCDDD = a:x
6177 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6179 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6181 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6183 emitcode ("anl", "a,#0x%02x",
6184 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6186 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6188 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6190 emitcode ("anl", "a,#0x%02x",
6191 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6193 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6195 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6197 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6200 case 6: // AABBBBBB:CCDDDDDD
6202 emitcode ("mov", "c,acc.7");
6203 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6205 emitcode ("mov", "c,acc.7");
6206 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6208 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6210 emitcode ("anl", "a,#0x%02x",
6211 SRMask[shCount]); // 000000AA:BBBBBBCC
6214 case 7: // ABBBBBBB:CDDDDDDD
6216 emitcode ("mov", "c,acc.7"); // c = A
6218 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6220 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6222 emitcode ("anl", "a,#0x%02x",
6223 SRMask[shCount]); // 0000000A:BBBBBBBC
6231 /*-----------------------------------------------------------------*/
6232 /* AccAXRshS - right shift signed a:x known count (0..7) */
6233 /*-----------------------------------------------------------------*/
6235 AccAXRshS (char *x, int shCount)
6243 emitcode ("mov", "c,acc.7");
6244 AccAXRrl1 (x); // s->a:x
6248 emitcode ("mov", "c,acc.7");
6249 AccAXRrl1 (x); // s->a:x
6251 emitcode ("mov", "c,acc.7");
6252 AccAXRrl1 (x); // s->a:x
6257 case 5: // AAAAABBB:CCCCCDDD = a:x
6259 tlbl = newiTempLabel (NULL);
6260 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6262 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6264 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6266 emitcode ("anl", "a,#0x%02x",
6267 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6269 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6271 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6273 emitcode ("anl", "a,#0x%02x",
6274 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6276 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6278 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6280 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6282 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6283 emitcode ("orl", "a,#0x%02x",
6284 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6286 emitcode ("", "%05d$:", tlbl->key + 100);
6287 break; // SSSSAAAA:BBBCCCCC
6289 case 6: // AABBBBBB:CCDDDDDD
6291 tlbl = newiTempLabel (NULL);
6292 emitcode ("mov", "c,acc.7");
6293 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6295 emitcode ("mov", "c,acc.7");
6296 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6298 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6300 emitcode ("anl", "a,#0x%02x",
6301 SRMask[shCount]); // 000000AA:BBBBBBCC
6303 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6304 emitcode ("orl", "a,#0x%02x",
6305 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6307 emitcode ("", "%05d$:", tlbl->key + 100);
6309 case 7: // ABBBBBBB:CDDDDDDD
6311 tlbl = newiTempLabel (NULL);
6312 emitcode ("mov", "c,acc.7"); // c = A
6314 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6316 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6318 emitcode ("anl", "a,#0x%02x",
6319 SRMask[shCount]); // 0000000A:BBBBBBBC
6321 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6322 emitcode ("orl", "a,#0x%02x",
6323 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6325 emitcode ("", "%05d$:", tlbl->key + 100);
6332 /*-----------------------------------------------------------------*/
6333 /* shiftL2Left2Result - shift left two bytes from left to result */
6334 /*-----------------------------------------------------------------*/
6336 shiftL2Left2Result (operand * left, int offl,
6337 operand * result, int offr, int shCount)
6339 if (sameRegs (AOP (result), AOP (left)) &&
6340 ((offl + MSB16) == offr))
6342 /* don't crash result[offr] */
6343 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6344 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6348 movLeft2Result (left, offl, result, offr, 0);
6349 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6351 /* ax << shCount (x = lsb(result)) */
6352 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6353 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6357 /*-----------------------------------------------------------------*/
6358 /* shiftR2Left2Result - shift right two bytes from left to result */
6359 /*-----------------------------------------------------------------*/
6361 shiftR2Left2Result (operand * left, int offl,
6362 operand * result, int offr,
6363 int shCount, int sign)
6365 if (sameRegs (AOP (result), AOP (left)) &&
6366 ((offl + MSB16) == offr))
6368 /* don't crash result[offr] */
6369 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6370 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6374 movLeft2Result (left, offl, result, offr, 0);
6375 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6377 /* a:x >> shCount (x = lsb(result)) */
6379 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6381 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6382 if (getDataSize (result) > 1)
6383 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6386 /*-----------------------------------------------------------------*/
6387 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6388 /*-----------------------------------------------------------------*/
6390 shiftLLeftOrResult (operand * left, int offl,
6391 operand * result, int offr, int shCount)
6393 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6394 /* shift left accumulator */
6396 /* or with result */
6397 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6398 /* back to result */
6399 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6402 /*-----------------------------------------------------------------*/
6403 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6404 /*-----------------------------------------------------------------*/
6406 shiftRLeftOrResult (operand * left, int offl,
6407 operand * result, int offr, int shCount)
6409 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6410 /* shift right accumulator */
6412 /* or with result */
6413 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6414 /* back to result */
6415 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6418 /*-----------------------------------------------------------------*/
6419 /* genlshOne - left shift a one byte quantity by known count */
6420 /*-----------------------------------------------------------------*/
6422 genlshOne (operand * result, operand * left, int shCount)
6424 D(emitcode ("; genlshOne",""));
6426 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6429 /*-----------------------------------------------------------------*/
6430 /* genlshTwo - left shift two bytes by known amount != 0 */
6431 /*-----------------------------------------------------------------*/
6433 genlshTwo (operand * result, operand * left, int shCount)
6437 D(emitcode ("; genlshTwo",""));
6439 size = getDataSize (result);
6441 /* if shCount >= 8 */
6449 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6451 movLeft2Result (left, LSB, result, MSB16, 0);
6453 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6456 /* 1 <= shCount <= 7 */
6460 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6462 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6466 /*-----------------------------------------------------------------*/
6467 /* shiftLLong - shift left one long from left to result */
6468 /* offl = LSB or MSB16 */
6469 /*-----------------------------------------------------------------*/
6471 shiftLLong (operand * left, operand * result, int offr)
6474 int size = AOP_SIZE (result);
6476 if (size >= LSB + offr)
6478 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6480 emitcode ("add", "a,acc");
6481 if (sameRegs (AOP (left), AOP (result)) &&
6482 size >= MSB16 + offr && offr != LSB)
6483 emitcode ("xch", "a,%s",
6484 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6486 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6489 if (size >= MSB16 + offr)
6491 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6493 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6496 emitcode ("rlc", "a");
6497 if (sameRegs (AOP (left), AOP (result)) &&
6498 size >= MSB24 + offr && offr != LSB)
6499 emitcode ("xch", "a,%s",
6500 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6502 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6505 if (size >= MSB24 + offr)
6507 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6509 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6512 emitcode ("rlc", "a");
6513 if (sameRegs (AOP (left), AOP (result)) &&
6514 size >= MSB32 + offr && offr != LSB)
6515 emitcode ("xch", "a,%s",
6516 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6518 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6521 if (size > MSB32 + offr)
6523 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6525 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6528 emitcode ("rlc", "a");
6529 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6532 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6535 /*-----------------------------------------------------------------*/
6536 /* genlshFour - shift four byte by a known amount != 0 */
6537 /*-----------------------------------------------------------------*/
6539 genlshFour (operand * result, operand * left, int shCount)
6543 D(emitcode ("; genlshFour",""));
6545 size = AOP_SIZE (result);
6547 /* if shifting more that 3 bytes */
6552 /* lowest order of left goes to the highest
6553 order of the destination */
6554 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6556 movLeft2Result (left, LSB, result, MSB32, 0);
6557 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6558 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6559 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6563 /* more than two bytes */
6564 else if (shCount >= 16)
6566 /* lower order two bytes goes to higher order two bytes */
6568 /* if some more remaining */
6570 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6573 movLeft2Result (left, MSB16, result, MSB32, 0);
6574 movLeft2Result (left, LSB, result, MSB24, 0);
6576 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6577 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6581 /* if more than 1 byte */
6582 else if (shCount >= 8)
6584 /* lower order three bytes goes to higher order three bytes */
6589 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6591 movLeft2Result (left, LSB, result, MSB16, 0);
6597 movLeft2Result (left, MSB24, result, MSB32, 0);
6598 movLeft2Result (left, MSB16, result, MSB24, 0);
6599 movLeft2Result (left, LSB, result, MSB16, 0);
6600 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6602 else if (shCount == 1)
6603 shiftLLong (left, result, MSB16);
6606 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6607 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6608 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6609 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6614 /* 1 <= shCount <= 7 */
6615 else if (shCount <= 2)
6617 shiftLLong (left, result, LSB);
6619 shiftLLong (result, result, LSB);
6621 /* 3 <= shCount <= 7, optimize */
6624 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6625 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6626 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6630 /*-----------------------------------------------------------------*/
6631 /* genLeftShiftLiteral - left shifting by known count */
6632 /*-----------------------------------------------------------------*/
6634 genLeftShiftLiteral (operand * left,
6639 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6642 D(emitcode ("; genLeftShiftLiteral",""));
6644 freeAsmop (right, NULL, ic, TRUE);
6646 aopOp (left, ic, FALSE);
6647 aopOp (result, ic, FALSE);
6649 size = getSize (operandType (result));
6652 emitcode ("; shift left ", "result %d, left %d", size,
6656 /* I suppose that the left size >= result size */
6661 movLeft2Result (left, size, result, size, 0);
6665 else if (shCount >= (size * 8))
6667 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6673 genlshOne (result, left, shCount);
6677 genlshTwo (result, left, shCount);
6681 genlshFour (result, left, shCount);
6684 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6685 "*** ack! mystery literal shift!\n");
6689 freeAsmop (left, NULL, ic, TRUE);
6690 freeAsmop (result, NULL, ic, TRUE);
6693 /*-----------------------------------------------------------------*/
6694 /* genLeftShift - generates code for left shifting */
6695 /*-----------------------------------------------------------------*/
6697 genLeftShift (iCode * ic)
6699 operand *left, *right, *result;
6702 symbol *tlbl, *tlbl1;
6704 D(emitcode ("; genLeftShift",""));
6706 right = IC_RIGHT (ic);
6707 left = IC_LEFT (ic);
6708 result = IC_RESULT (ic);
6710 aopOp (right, ic, FALSE);
6712 /* if the shift count is known then do it
6713 as efficiently as possible */
6714 if (AOP_TYPE (right) == AOP_LIT)
6716 genLeftShiftLiteral (left, right, result, ic);
6720 /* shift count is unknown then we have to form
6721 a loop get the loop count in B : Note: we take
6722 only the lower order byte since shifting
6723 more that 32 bits make no sense anyway, ( the
6724 largest size of an object can be only 32 bits ) */
6726 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6727 emitcode ("inc", "b");
6728 freeAsmop (right, NULL, ic, TRUE);
6729 aopOp (left, ic, FALSE);
6730 aopOp (result, ic, FALSE);
6732 /* now move the left to the result if they are not the
6734 if (!sameRegs (AOP (left), AOP (result)) &&
6735 AOP_SIZE (result) > 1)
6738 size = AOP_SIZE (result);
6742 l = aopGet (AOP (left), offset, FALSE, TRUE);
6743 if (*l == '@' && (IS_AOP_PREG (result)))
6746 emitcode ("mov", "a,%s", l);
6747 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6750 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6755 tlbl = newiTempLabel (NULL);
6756 size = AOP_SIZE (result);
6758 tlbl1 = newiTempLabel (NULL);
6760 /* if it is only one byte then */
6763 symbol *tlbl1 = newiTempLabel (NULL);
6765 l = aopGet (AOP (left), 0, FALSE, FALSE);
6767 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6768 emitcode ("", "%05d$:", tlbl->key + 100);
6769 emitcode ("add", "a,acc");
6770 emitcode ("", "%05d$:", tlbl1->key + 100);
6771 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6772 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6776 reAdjustPreg (AOP (result));
6778 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6779 emitcode ("", "%05d$:", tlbl->key + 100);
6780 l = aopGet (AOP (result), offset, FALSE, FALSE);
6782 emitcode ("add", "a,acc");
6783 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6786 l = aopGet (AOP (result), offset, FALSE, FALSE);
6788 emitcode ("rlc", "a");
6789 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6791 reAdjustPreg (AOP (result));
6793 emitcode ("", "%05d$:", tlbl1->key + 100);
6794 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6796 freeAsmop (left, NULL, ic, TRUE);
6797 freeAsmop (result, NULL, ic, TRUE);
6800 /*-----------------------------------------------------------------*/
6801 /* genrshOne - right shift a one byte quantity by known count */
6802 /*-----------------------------------------------------------------*/
6804 genrshOne (operand * result, operand * left,
6805 int shCount, int sign)
6807 D(emitcode ("; genrshOne",""));
6809 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6812 /*-----------------------------------------------------------------*/
6813 /* genrshTwo - right shift two bytes by known amount != 0 */
6814 /*-----------------------------------------------------------------*/
6816 genrshTwo (operand * result, operand * left,
6817 int shCount, int sign)
6819 D(emitcode ("; genrshTwo",""));
6821 /* if shCount >= 8 */
6826 shiftR1Left2Result (left, MSB16, result, LSB,
6829 movLeft2Result (left, MSB16, result, LSB, sign);
6830 addSign (result, MSB16, sign);
6833 /* 1 <= shCount <= 7 */
6835 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6838 /*-----------------------------------------------------------------*/
6839 /* shiftRLong - shift right one long from left to result */
6840 /* offl = LSB or MSB16 */
6841 /*-----------------------------------------------------------------*/
6843 shiftRLong (operand * left, int offl,
6844 operand * result, int sign)
6846 int isSameRegs=sameRegs(AOP(left),AOP(result));
6848 if (isSameRegs && offl>1) {
6849 // we are in big trouble, but this shouldn't happen
6850 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6853 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6858 emitcode ("rlc", "a");
6859 emitcode ("subb", "a,acc");
6861 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6863 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6864 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6867 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6872 emitcode ("clr", "c");
6874 emitcode ("mov", "c,acc.7");
6877 emitcode ("rrc", "a");
6879 if (isSameRegs && offl==MSB16) {
6880 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6882 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6883 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6886 emitcode ("rrc", "a");
6887 if (isSameRegs && offl==1) {
6888 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6890 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6891 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6893 emitcode ("rrc", "a");
6894 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6898 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6899 emitcode ("rrc", "a");
6900 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6904 /*-----------------------------------------------------------------*/
6905 /* genrshFour - shift four byte by a known amount != 0 */
6906 /*-----------------------------------------------------------------*/
6908 genrshFour (operand * result, operand * left,
6909 int shCount, int sign)
6911 D(emitcode ("; genrshFour",""));
6913 /* if shifting more that 3 bytes */
6918 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6920 movLeft2Result (left, MSB32, result, LSB, sign);
6921 addSign (result, MSB16, sign);
6923 else if (shCount >= 16)
6927 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6930 movLeft2Result (left, MSB24, result, LSB, 0);
6931 movLeft2Result (left, MSB32, result, MSB16, sign);
6933 addSign (result, MSB24, sign);
6935 else if (shCount >= 8)
6939 shiftRLong (left, MSB16, result, sign);
6940 else if (shCount == 0)
6942 movLeft2Result (left, MSB16, result, LSB, 0);
6943 movLeft2Result (left, MSB24, result, MSB16, 0);
6944 movLeft2Result (left, MSB32, result, MSB24, sign);
6945 addSign (result, MSB32, sign);
6949 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6950 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6951 /* the last shift is signed */
6952 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6953 addSign (result, MSB32, sign);
6957 { /* 1 <= shCount <= 7 */
6960 shiftRLong (left, LSB, result, sign);
6962 shiftRLong (result, LSB, result, sign);
6966 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6967 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6968 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6973 /*-----------------------------------------------------------------*/
6974 /* genRightShiftLiteral - right shifting by known count */
6975 /*-----------------------------------------------------------------*/
6977 genRightShiftLiteral (operand * left,
6983 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6986 D(emitcode ("; genRightShiftLiteral",""));
6988 freeAsmop (right, NULL, ic, TRUE);
6990 aopOp (left, ic, FALSE);
6991 aopOp (result, ic, FALSE);
6994 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6998 size = getDataSize (left);
6999 /* test the LEFT size !!! */
7001 /* I suppose that the left size >= result size */
7004 size = getDataSize (result);
7006 movLeft2Result (left, size, result, size, 0);
7009 else if (shCount >= (size * 8))
7012 /* get sign in acc.7 */
7013 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7015 addSign (result, LSB, sign);
7022 genrshOne (result, left, shCount, sign);
7026 genrshTwo (result, left, shCount, sign);
7030 genrshFour (result, left, shCount, sign);
7036 freeAsmop (left, NULL, ic, TRUE);
7037 freeAsmop (result, NULL, ic, TRUE);
7040 /*-----------------------------------------------------------------*/
7041 /* genSignedRightShift - right shift of signed number */
7042 /*-----------------------------------------------------------------*/
7044 genSignedRightShift (iCode * ic)
7046 operand *right, *left, *result;
7049 symbol *tlbl, *tlbl1;
7051 D(emitcode ("; genSignedRightShift",""));
7053 /* we do it the hard way put the shift count in b
7054 and loop thru preserving the sign */
7056 right = IC_RIGHT (ic);
7057 left = IC_LEFT (ic);
7058 result = IC_RESULT (ic);
7060 aopOp (right, ic, FALSE);
7063 if (AOP_TYPE (right) == AOP_LIT)
7065 genRightShiftLiteral (left, right, result, ic, 1);
7068 /* shift count is unknown then we have to form
7069 a loop get the loop count in B : Note: we take
7070 only the lower order byte since shifting
7071 more that 32 bits make no sense anyway, ( the
7072 largest size of an object can be only 32 bits ) */
7074 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7075 emitcode ("inc", "b");
7076 freeAsmop (right, NULL, ic, TRUE);
7077 aopOp (left, ic, FALSE);
7078 aopOp (result, ic, FALSE);
7080 /* now move the left to the result if they are not the
7082 if (!sameRegs (AOP (left), AOP (result)) &&
7083 AOP_SIZE (result) > 1)
7086 size = AOP_SIZE (result);
7090 l = aopGet (AOP (left), offset, FALSE, TRUE);
7091 if (*l == '@' && IS_AOP_PREG (result))
7094 emitcode ("mov", "a,%s", l);
7095 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7098 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7103 /* mov the highest order bit to OVR */
7104 tlbl = newiTempLabel (NULL);
7105 tlbl1 = newiTempLabel (NULL);
7107 size = AOP_SIZE (result);
7109 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7110 emitcode ("rlc", "a");
7111 emitcode ("mov", "ov,c");
7112 /* if it is only one byte then */
7115 l = aopGet (AOP (left), 0, FALSE, FALSE);
7117 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7118 emitcode ("", "%05d$:", tlbl->key + 100);
7119 emitcode ("mov", "c,ov");
7120 emitcode ("rrc", "a");
7121 emitcode ("", "%05d$:", tlbl1->key + 100);
7122 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7123 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7127 reAdjustPreg (AOP (result));
7128 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7129 emitcode ("", "%05d$:", tlbl->key + 100);
7130 emitcode ("mov", "c,ov");
7133 l = aopGet (AOP (result), offset, FALSE, FALSE);
7135 emitcode ("rrc", "a");
7136 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7138 reAdjustPreg (AOP (result));
7139 emitcode ("", "%05d$:", tlbl1->key + 100);
7140 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7143 freeAsmop (left, NULL, ic, TRUE);
7144 freeAsmop (result, NULL, ic, TRUE);
7147 /*-----------------------------------------------------------------*/
7148 /* genRightShift - generate code for right shifting */
7149 /*-----------------------------------------------------------------*/
7151 genRightShift (iCode * ic)
7153 operand *right, *left, *result;
7157 symbol *tlbl, *tlbl1;
7159 D(emitcode ("; genRightShift",""));
7161 /* if signed then we do it the hard way preserve the
7162 sign bit moving it inwards */
7163 retype = getSpec (operandType (IC_RESULT (ic)));
7165 if (!SPEC_USIGN (retype))
7167 genSignedRightShift (ic);
7171 /* signed & unsigned types are treated the same : i.e. the
7172 signed is NOT propagated inwards : quoting from the
7173 ANSI - standard : "for E1 >> E2, is equivalent to division
7174 by 2**E2 if unsigned or if it has a non-negative value,
7175 otherwise the result is implementation defined ", MY definition
7176 is that the sign does not get propagated */
7178 right = IC_RIGHT (ic);
7179 left = IC_LEFT (ic);
7180 result = IC_RESULT (ic);
7182 aopOp (right, ic, FALSE);
7184 /* if the shift count is known then do it
7185 as efficiently as possible */
7186 if (AOP_TYPE (right) == AOP_LIT)
7188 genRightShiftLiteral (left, right, result, ic, 0);
7192 /* shift count is unknown then we have to form
7193 a loop get the loop count in B : Note: we take
7194 only the lower order byte since shifting
7195 more that 32 bits make no sense anyway, ( the
7196 largest size of an object can be only 32 bits ) */
7198 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7199 emitcode ("inc", "b");
7200 freeAsmop (right, NULL, ic, TRUE);
7201 aopOp (left, ic, FALSE);
7202 aopOp (result, ic, FALSE);
7204 /* now move the left to the result if they are not the
7206 if (!sameRegs (AOP (left), AOP (result)) &&
7207 AOP_SIZE (result) > 1)
7210 size = AOP_SIZE (result);
7214 l = aopGet (AOP (left), offset, FALSE, TRUE);
7215 if (*l == '@' && IS_AOP_PREG (result))
7218 emitcode ("mov", "a,%s", l);
7219 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7222 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7227 tlbl = newiTempLabel (NULL);
7228 tlbl1 = newiTempLabel (NULL);
7229 size = AOP_SIZE (result);
7232 /* if it is only one byte then */
7235 l = aopGet (AOP (left), 0, FALSE, FALSE);
7237 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7238 emitcode ("", "%05d$:", tlbl->key + 100);
7240 emitcode ("rrc", "a");
7241 emitcode ("", "%05d$:", tlbl1->key + 100);
7242 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7243 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7247 reAdjustPreg (AOP (result));
7248 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7249 emitcode ("", "%05d$:", tlbl->key + 100);
7253 l = aopGet (AOP (result), offset, FALSE, FALSE);
7255 emitcode ("rrc", "a");
7256 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7258 reAdjustPreg (AOP (result));
7260 emitcode ("", "%05d$:", tlbl1->key + 100);
7261 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7264 freeAsmop (left, NULL, ic, TRUE);
7265 freeAsmop (result, NULL, ic, TRUE);
7268 /*-----------------------------------------------------------------*/
7269 /* emitPtrByteGet - emits code to get a byte into A through a */
7270 /* pointer register (R0, R1, or DPTR). The */
7271 /* original value of A can be preserved in B. */
7272 /*-----------------------------------------------------------------*/
7274 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7281 emitcode ("mov", "b,a");
7282 emitcode ("mov", "a,@%s", rname);
7287 emitcode ("mov", "b,a");
7288 emitcode ("movx", "a,@%s", rname);
7293 emitcode ("mov", "b,a");
7294 emitcode ("movx", "a,@dptr");
7299 emitcode ("mov", "b,a");
7300 emitcode ("clr", "a");
7301 emitcode ("movc", "a,@a+dptr");
7307 emitcode ("push", "b");
7308 emitcode ("push", "acc");
7310 emitcode ("lcall", "__gptrget");
7312 emitcode ("pop", "b");
7317 /*-----------------------------------------------------------------*/
7318 /* emitPtrByteSet - emits code to set a byte from src through a */
7319 /* pointer register (R0, R1, or DPTR). */
7320 /*-----------------------------------------------------------------*/
7322 emitPtrByteSet (char *rname, int p_type, char *src)
7331 emitcode ("mov", "@%s,a", rname);
7334 emitcode ("mov", "@%s,%s", rname, src);
7339 emitcode ("movx", "@%s,a", rname);
7344 emitcode ("movx", "@dptr,a");
7349 emitcode ("lcall", "__gptrput");
7354 /*-----------------------------------------------------------------*/
7355 /* genUnpackBits - generates code for unpacking bits */
7356 /*-----------------------------------------------------------------*/
7358 genUnpackBits (operand * result, char *rname, int ptype)
7360 int offset = 0; /* result byte offset */
7361 int rsize; /* result size */
7362 int rlen = 0; /* remaining bitfield length */
7363 sym_link *etype; /* bitfield type information */
7364 int blen; /* bitfield length */
7365 int bstr; /* bitfield starting bit within byte */
7367 D(emitcode ("; genUnpackBits",""));
7369 etype = getSpec (operandType (result));
7370 rsize = getSize (operandType (result));
7371 blen = SPEC_BLEN (etype);
7372 bstr = SPEC_BSTR (etype);
7374 /* If the bitfield length is less than a byte */
7377 emitPtrByteGet (rname, ptype, FALSE);
7379 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7380 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7384 /* Bit field did not fit in a byte. Copy all
7385 but the partial byte at the end. */
7386 for (rlen=blen;rlen>=8;rlen-=8)
7388 emitPtrByteGet (rname, ptype, FALSE);
7389 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7391 emitcode ("inc", "%s", rname);
7394 /* Handle the partial byte at the end */
7397 emitPtrByteGet (rname, ptype, FALSE);
7398 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7399 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7407 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7412 /*-----------------------------------------------------------------*/
7413 /* genDataPointerGet - generates code when ptr offset is known */
7414 /*-----------------------------------------------------------------*/
7416 genDataPointerGet (operand * left,
7422 int size, offset = 0;
7424 D(emitcode ("; genDataPointerGet",""));
7426 aopOp (result, ic, TRUE);
7428 /* get the string representation of the name */
7429 l = aopGet (AOP (left), 0, FALSE, TRUE);
7430 size = AOP_SIZE (result);
7434 sprintf (buffer, "(%s + %d)", l + 1, offset);
7436 sprintf (buffer, "%s", l + 1);
7437 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7440 freeAsmop (left, NULL, ic, TRUE);
7441 freeAsmop (result, NULL, ic, TRUE);
7444 /*-----------------------------------------------------------------*/
7445 /* genNearPointerGet - emitcode for near pointer fetch */
7446 /*-----------------------------------------------------------------*/
7448 genNearPointerGet (operand * left,
7456 sym_link *rtype, *retype;
7457 sym_link *ltype = operandType (left);
7460 D(emitcode ("; genNearPointerGet",""));
7462 rtype = operandType (result);
7463 retype = getSpec (rtype);
7465 aopOp (left, ic, FALSE);
7467 /* if left is rematerialisable and
7468 result is not bit variable type and
7469 the left is pointer to data space i.e
7470 lower 128 bytes of space */
7471 if (AOP_TYPE (left) == AOP_IMMD &&
7472 !IS_BITVAR (retype) &&
7473 DCL_TYPE (ltype) == POINTER)
7475 genDataPointerGet (left, result, ic);
7479 /* if the value is already in a pointer register
7480 then don't need anything more */
7481 if (!AOP_INPREG (AOP (left)))
7483 if (IS_AOP_PREG (left))
7485 // Aha, it is a pointer, just in disguise.
7486 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7489 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7490 __FILE__, __LINE__);
7495 emitcode ("mov", "a%s,%s", rname + 1, rname);
7496 rname++; // skip the '@'.
7501 /* otherwise get a free pointer register */
7503 preg = getFreePtr (ic, &aop, FALSE);
7504 emitcode ("mov", "%s,%s",
7506 aopGet (AOP (left), 0, FALSE, TRUE));
7511 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7513 //aopOp (result, ic, FALSE);
7514 aopOp (result, ic, result?TRUE:FALSE);
7516 /* if bitfield then unpack the bits */
7517 if (IS_BITVAR (retype))
7518 genUnpackBits (result, rname, POINTER);
7521 /* we have can just get the values */
7522 int size = AOP_SIZE (result);
7527 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7530 emitcode ("mov", "a,@%s", rname);
7531 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7535 sprintf (buffer, "@%s", rname);
7536 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7540 emitcode ("inc", "%s", rname);
7544 /* now some housekeeping stuff */
7545 if (aop) /* we had to allocate for this iCode */
7547 if (pi) { /* post increment present */
7548 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7550 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7554 /* we did not allocate which means left
7555 already in a pointer register, then
7556 if size > 0 && this could be used again
7557 we have to point it back to where it
7559 if ((AOP_SIZE (result) > 1 &&
7560 !OP_SYMBOL (left)->remat &&
7561 (OP_SYMBOL (left)->liveTo > ic->seq ||
7565 int size = AOP_SIZE (result) - 1;
7567 emitcode ("dec", "%s", rname);
7572 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7573 freeAsmop (left, NULL, ic, TRUE);
7574 if (pi) pi->generated = 1;
7577 /*-----------------------------------------------------------------*/
7578 /* genPagedPointerGet - emitcode for paged pointer fetch */
7579 /*-----------------------------------------------------------------*/
7581 genPagedPointerGet (operand * left,
7589 sym_link *rtype, *retype;
7591 D(emitcode ("; genPagedPointerGet",""));
7593 rtype = operandType (result);
7594 retype = getSpec (rtype);
7596 aopOp (left, ic, FALSE);
7598 /* if the value is already in a pointer register
7599 then don't need anything more */
7600 if (!AOP_INPREG (AOP (left)))
7602 /* otherwise get a free pointer register */
7604 preg = getFreePtr (ic, &aop, FALSE);
7605 emitcode ("mov", "%s,%s",
7607 aopGet (AOP (left), 0, FALSE, TRUE));
7611 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7613 aopOp (result, ic, FALSE);
7615 /* if bitfield then unpack the bits */
7616 if (IS_BITVAR (retype))
7617 genUnpackBits (result, rname, PPOINTER);
7620 /* we have can just get the values */
7621 int size = AOP_SIZE (result);
7627 emitcode ("movx", "a,@%s", rname);
7628 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7633 emitcode ("inc", "%s", rname);
7637 /* now some housekeeping stuff */
7638 if (aop) /* we had to allocate for this iCode */
7640 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7641 freeAsmop (NULL, aop, ic, TRUE);
7645 /* we did not allocate which means left
7646 already in a pointer register, then
7647 if size > 0 && this could be used again
7648 we have to point it back to where it
7650 if ((AOP_SIZE (result) > 1 &&
7651 !OP_SYMBOL (left)->remat &&
7652 (OP_SYMBOL (left)->liveTo > ic->seq ||
7656 int size = AOP_SIZE (result) - 1;
7658 emitcode ("dec", "%s", rname);
7663 freeAsmop (left, NULL, ic, TRUE);
7664 freeAsmop (result, NULL, ic, TRUE);
7665 if (pi) pi->generated = 1;
7669 /*--------------------------------------------------------------------*/
7670 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7671 /*--------------------------------------------------------------------*/
7673 loadDptrFromOperand (operand *op, bool loadBToo)
7675 if (AOP_TYPE (op) != AOP_STR)
7677 /* if this is remateriazable */
7678 if (AOP_TYPE (op) == AOP_IMMD)
7680 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7683 if (AOP(op)->aopu.aop_immd.from_cast_remat)
7684 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7687 wassertl(FALSE, "need pointerCode");
7688 emitcode ("", "; mov b,???");
7689 /* genPointerGet and genPointerSet originally did different
7690 ** things for this case. Both seem wrong.
7691 ** from genPointerGet:
7692 ** emitcode ("mov", "b,#%d", pointerCode (retype));
7693 ** from genPointerSet:
7694 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7699 else if (AOP_TYPE (op) == AOP_DPTR)
7703 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7704 emitcode ("push", "acc");
7705 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7706 emitcode ("push", "acc");
7707 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7708 emitcode ("pop", "dph");
7709 emitcode ("pop", "dpl");
7713 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7714 emitcode ("push", "acc");
7715 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7716 emitcode ("pop", "dpl");
7720 { /* we need to get it byte by byte */
7721 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7722 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7724 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7729 /*-----------------------------------------------------------------*/
7730 /* genFarPointerGet - gget value from far space */
7731 /*-----------------------------------------------------------------*/
7733 genFarPointerGet (operand * left,
7734 operand * result, iCode * ic, iCode * pi)
7737 sym_link *retype = getSpec (operandType (result));
7739 D(emitcode ("; genFarPointerGet",""));
7741 aopOp (left, ic, FALSE);
7742 loadDptrFromOperand (left, FALSE);
7744 /* so dptr now contains the address */
7745 aopOp (result, ic, FALSE);
7747 /* if bit then unpack */
7748 if (IS_BITVAR (retype))
7749 genUnpackBits (result, "dptr", FPOINTER);
7752 size = AOP_SIZE (result);
7757 emitcode ("movx", "a,@dptr");
7758 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7760 emitcode ("inc", "dptr");
7764 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7765 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7766 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7769 freeAsmop (left, NULL, ic, TRUE);
7770 freeAsmop (result, NULL, ic, TRUE);
7773 /*-----------------------------------------------------------------*/
7774 /* genCodePointerGet - gget value from code space */
7775 /*-----------------------------------------------------------------*/
7777 genCodePointerGet (operand * left,
7778 operand * result, iCode * ic, iCode *pi)
7781 sym_link *retype = getSpec (operandType (result));
7783 D(emitcode ("; genCodePointerGet",""));
7785 aopOp (left, ic, FALSE);
7786 loadDptrFromOperand (left, FALSE);
7788 /* so dptr now contains the address */
7789 aopOp (result, ic, FALSE);
7791 /* if bit then unpack */
7792 if (IS_BITVAR (retype))
7793 genUnpackBits (result, "dptr", CPOINTER);
7796 size = AOP_SIZE (result);
7803 emitcode ("clr", "a");
7804 emitcode ("movc", "a,@a+dptr");
7805 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7806 emitcode ("inc", "dptr");
7810 emitcode ("mov", "a,#0x%02x", offset);
7811 emitcode ("movc", "a,@a+dptr");
7812 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7817 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7818 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7819 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7822 freeAsmop (left, NULL, ic, TRUE);
7823 freeAsmop (result, NULL, ic, TRUE);
7826 /*-----------------------------------------------------------------*/
7827 /* genGenPointerGet - gget value from generic pointer space */
7828 /*-----------------------------------------------------------------*/
7830 genGenPointerGet (operand * left,
7831 operand * result, iCode * ic, iCode *pi)
7834 sym_link *retype = getSpec (operandType (result));
7836 D(emitcode ("; genGenPointerGet",""));
7838 aopOp (left, ic, FALSE);
7839 loadDptrFromOperand (left, TRUE);
7841 /* so dptr know contains the address */
7842 aopOp (result, ic, FALSE);
7844 /* if bit then unpack */
7845 if (IS_BITVAR (retype))
7846 genUnpackBits (result, "dptr", GPOINTER);
7849 size = AOP_SIZE (result);
7854 emitcode ("lcall", "__gptrget");
7855 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7857 emitcode ("inc", "dptr");
7861 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7862 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7863 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7866 freeAsmop (left, NULL, ic, TRUE);
7867 freeAsmop (result, NULL, ic, TRUE);
7870 /*-----------------------------------------------------------------*/
7871 /* genPointerGet - generate code for pointer get */
7872 /*-----------------------------------------------------------------*/
7874 genPointerGet (iCode * ic, iCode *pi)
7876 operand *left, *result;
7877 sym_link *type, *etype;
7880 D(emitcode ("; genPointerGet",""));
7882 left = IC_LEFT (ic);
7883 result = IC_RESULT (ic);
7885 /* depending on the type of pointer we need to
7886 move it to the correct pointer register */
7887 type = operandType (left);
7888 etype = getSpec (type);
7889 /* if left is of type of pointer then it is simple */
7890 if (IS_PTR (type) && !IS_FUNC (type->next))
7891 p_type = DCL_TYPE (type);
7894 /* we have to go by the storage class */
7895 p_type = PTR_TYPE (SPEC_OCLS (etype));
7898 /* special case when cast remat */
7899 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7900 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7901 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7902 type = operandType (left);
7903 p_type = DCL_TYPE (type);
7905 /* now that we have the pointer type we assign
7906 the pointer values */
7912 genNearPointerGet (left, result, ic, pi);
7916 genPagedPointerGet (left, result, ic, pi);
7920 genFarPointerGet (left, result, ic, pi);
7924 genCodePointerGet (left, result, ic, pi);
7928 genGenPointerGet (left, result, ic, pi);
7936 /*-----------------------------------------------------------------*/
7937 /* genPackBits - generates code for packed bit storage */
7938 /*-----------------------------------------------------------------*/
7940 genPackBits (sym_link * etype,
7942 char *rname, int p_type)
7944 int offset = 0; /* source byte offset */
7945 int rlen = 0; /* remaining bitfield length */
7946 int blen; /* bitfield length */
7947 int bstr; /* bitfield starting bit within byte */
7948 int litval; /* source literal value (if AOP_LIT) */
7949 unsigned char mask; /* bitmask within current byte */
7951 D(emitcode ("; genPackBits",""));
7953 blen = SPEC_BLEN (etype);
7954 bstr = SPEC_BSTR (etype);
7956 /* If the bitfield length is less than a byte */
7959 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7960 (unsigned char) (0xFF >> (8 - bstr)));
7962 if (AOP_TYPE (right) == AOP_LIT)
7964 /* Case with a bitfield length <8 and literal source
7966 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7968 litval &= (~mask) & 0xff;
7969 emitPtrByteGet (rname, p_type, FALSE);
7970 if ((mask|litval)!=0xff)
7971 emitcode ("anl","a,#0x%02x", mask);
7973 emitcode ("orl","a,#0x%02x", litval);
7977 if ((blen==1) && (p_type!=GPOINTER))
7979 /* Case with a bitfield length == 1 and no generic pointer
7981 if (AOP_TYPE (right) == AOP_CRY)
7982 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7985 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7986 emitcode ("rrc","a");
7988 emitPtrByteGet (rname, p_type, FALSE);
7989 emitcode ("mov","acc.%d,c",bstr);
7993 /* Case with a bitfield length < 8 and arbitrary source
7995 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7996 /* shift and mask source value */
7998 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8000 /* transfer A to B and get next byte */
8001 emitPtrByteGet (rname, p_type, TRUE);
8003 emitcode ("anl", "a,#0x%02x", mask);
8004 emitcode ("orl", "a,b");
8005 if (p_type == GPOINTER)
8006 emitcode ("pop", "b");
8010 emitPtrByteSet (rname, p_type, "a");
8014 /* Bit length is greater than 7 bits. In this case, copy */
8015 /* all except the partial byte at the end */
8016 for (rlen=blen;rlen>=8;rlen-=8)
8018 emitPtrByteSet (rname, p_type,
8019 aopGet (AOP (right), offset++, FALSE, TRUE) );
8021 emitcode ("inc", "%s", rname);
8024 /* If there was a partial byte at the end */
8027 mask = (((unsigned char) -1 << rlen) & 0xff);
8029 if (AOP_TYPE (right) == AOP_LIT)
8031 /* Case with partial byte and literal source
8033 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8034 litval >>= (blen-rlen);
8035 litval &= (~mask) & 0xff;
8036 emitPtrByteGet (rname, p_type, FALSE);
8037 if ((mask|litval)!=0xff)
8038 emitcode ("anl","a,#0x%02x", mask);
8040 emitcode ("orl","a,#0x%02x", litval);
8044 /* Case with partial byte and arbitrary source
8046 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8047 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8049 /* transfer A to B and get next byte */
8050 emitPtrByteGet (rname, p_type, TRUE);
8052 emitcode ("anl", "a,#0x%02x", mask);
8053 emitcode ("orl", "a,b");
8054 if (p_type == GPOINTER)
8055 emitcode ("pop", "b");
8057 emitPtrByteSet (rname, p_type, "a");
8063 /*-----------------------------------------------------------------*/
8064 /* genDataPointerSet - remat pointer to data space */
8065 /*-----------------------------------------------------------------*/
8067 genDataPointerSet (operand * right,
8071 int size, offset = 0;
8072 char *l, buffer[256];
8074 D(emitcode ("; genDataPointerSet",""));
8076 aopOp (right, ic, FALSE);
8078 l = aopGet (AOP (result), 0, FALSE, TRUE);
8079 size = AOP_SIZE (right);
8083 sprintf (buffer, "(%s + %d)", l + 1, offset);
8085 sprintf (buffer, "%s", l + 1);
8086 emitcode ("mov", "%s,%s", buffer,
8087 aopGet (AOP (right), offset++, FALSE, FALSE));
8090 freeAsmop (right, NULL, ic, TRUE);
8091 freeAsmop (result, NULL, ic, TRUE);
8094 /*-----------------------------------------------------------------*/
8095 /* genNearPointerSet - emitcode for near pointer put */
8096 /*-----------------------------------------------------------------*/
8098 genNearPointerSet (operand * right,
8106 sym_link *retype, *letype;
8107 sym_link *ptype = operandType (result);
8109 D(emitcode ("; genNearPointerSet",""));
8111 retype = getSpec (operandType (right));
8112 letype = getSpec (ptype);
8113 aopOp (result, ic, FALSE);
8115 /* if the result is rematerializable &
8116 in data space & not a bit variable */
8117 if (AOP_TYPE (result) == AOP_IMMD &&
8118 DCL_TYPE (ptype) == POINTER &&
8119 !IS_BITVAR (retype) &&
8120 !IS_BITVAR (letype))
8122 genDataPointerSet (right, result, ic);
8126 /* if the value is already in a pointer register
8127 then don't need anything more */
8128 if (!AOP_INPREG (AOP (result)))
8131 //AOP_TYPE (result) == AOP_STK
8135 // Aha, it is a pointer, just in disguise.
8136 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8139 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8140 __FILE__, __LINE__);
8145 emitcode ("mov", "a%s,%s", rname + 1, rname);
8146 rname++; // skip the '@'.
8151 /* otherwise get a free pointer register */
8153 preg = getFreePtr (ic, &aop, FALSE);
8154 emitcode ("mov", "%s,%s",
8156 aopGet (AOP (result), 0, FALSE, TRUE));
8162 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8165 aopOp (right, ic, FALSE);
8167 /* if bitfield then unpack the bits */
8168 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8169 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8172 /* we have can just get the values */
8173 int size = AOP_SIZE (right);
8178 l = aopGet (AOP (right), offset, FALSE, TRUE);
8182 emitcode ("mov", "@%s,a", rname);
8185 emitcode ("mov", "@%s,%s", rname, l);
8187 emitcode ("inc", "%s", rname);
8192 /* now some housekeeping stuff */
8193 if (aop) /* we had to allocate for this iCode */
8196 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8197 freeAsmop (NULL, aop, ic, TRUE);
8201 /* we did not allocate which means left
8202 already in a pointer register, then
8203 if size > 0 && this could be used again
8204 we have to point it back to where it
8206 if ((AOP_SIZE (right) > 1 &&
8207 !OP_SYMBOL (result)->remat &&
8208 (OP_SYMBOL (result)->liveTo > ic->seq ||
8212 int size = AOP_SIZE (right) - 1;
8214 emitcode ("dec", "%s", rname);
8219 if (pi) pi->generated = 1;
8220 freeAsmop (result, NULL, ic, TRUE);
8221 freeAsmop (right, NULL, ic, TRUE);
8224 /*-----------------------------------------------------------------*/
8225 /* genPagedPointerSet - emitcode for Paged pointer put */
8226 /*-----------------------------------------------------------------*/
8228 genPagedPointerSet (operand * right,
8236 sym_link *retype, *letype;
8238 D(emitcode ("; genPagedPointerSet",""));
8240 retype = getSpec (operandType (right));
8241 letype = getSpec (operandType (result));
8243 aopOp (result, ic, FALSE);
8245 /* if the value is already in a pointer register
8246 then don't need anything more */
8247 if (!AOP_INPREG (AOP (result)))
8249 /* otherwise get a free pointer register */
8251 preg = getFreePtr (ic, &aop, FALSE);
8252 emitcode ("mov", "%s,%s",
8254 aopGet (AOP (result), 0, FALSE, TRUE));
8258 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8260 aopOp (right, ic, FALSE);
8262 /* if bitfield then unpack the bits */
8263 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8264 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8267 /* we have can just get the values */
8268 int size = AOP_SIZE (right);
8273 l = aopGet (AOP (right), offset, FALSE, TRUE);
8276 emitcode ("movx", "@%s,a", rname);
8279 emitcode ("inc", "%s", rname);
8285 /* now some housekeeping stuff */
8286 if (aop) /* we had to allocate for this iCode */
8289 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8290 freeAsmop (NULL, aop, ic, TRUE);
8294 /* we did not allocate which means left
8295 already in a pointer register, then
8296 if size > 0 && this could be used again
8297 we have to point it back to where it
8299 if (AOP_SIZE (right) > 1 &&
8300 !OP_SYMBOL (result)->remat &&
8301 (OP_SYMBOL (result)->liveTo > ic->seq ||
8304 int size = AOP_SIZE (right) - 1;
8306 emitcode ("dec", "%s", rname);
8311 if (pi) pi->generated = 1;
8312 freeAsmop (result, NULL, ic, TRUE);
8313 freeAsmop (right, NULL, ic, TRUE);
8318 /*-----------------------------------------------------------------*/
8319 /* genFarPointerSet - set value from far space */
8320 /*-----------------------------------------------------------------*/
8322 genFarPointerSet (operand * right,
8323 operand * result, iCode * ic, iCode * pi)
8326 sym_link *retype = getSpec (operandType (right));
8327 sym_link *letype = getSpec (operandType (result));
8329 D(emitcode ("; genFarPointerSet",""));
8331 aopOp (result, ic, FALSE);
8332 loadDptrFromOperand (result, FALSE);
8334 /* so dptr know contains the address */
8335 aopOp (right, ic, FALSE);
8337 /* if bit then unpack */
8338 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8339 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8342 size = AOP_SIZE (right);
8347 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8349 emitcode ("movx", "@dptr,a");
8351 emitcode ("inc", "dptr");
8354 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8355 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8356 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8359 freeAsmop (result, NULL, ic, TRUE);
8360 freeAsmop (right, NULL, ic, TRUE);
8363 /*-----------------------------------------------------------------*/
8364 /* genGenPointerSet - set value from generic pointer space */
8365 /*-----------------------------------------------------------------*/
8367 genGenPointerSet (operand * right,
8368 operand * result, iCode * ic, iCode * pi)
8371 sym_link *retype = getSpec (operandType (right));
8372 sym_link *letype = getSpec (operandType (result));
8374 D(emitcode ("; genGenPointerSet",""));
8376 aopOp (result, ic, FALSE);
8377 loadDptrFromOperand (result, TRUE);
8379 /* so dptr know contains the address */
8380 aopOp (right, ic, FALSE);
8382 /* if bit then unpack */
8383 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8384 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8387 size = AOP_SIZE (right);
8392 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8394 emitcode ("lcall", "__gptrput");
8396 emitcode ("inc", "dptr");
8400 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8401 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8402 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8405 freeAsmop (result, NULL, ic, TRUE);
8406 freeAsmop (right, NULL, ic, TRUE);
8409 /*-----------------------------------------------------------------*/
8410 /* genPointerSet - stores the value into a pointer location */
8411 /*-----------------------------------------------------------------*/
8413 genPointerSet (iCode * ic, iCode *pi)
8415 operand *right, *result;
8416 sym_link *type, *etype;
8419 D(emitcode ("; genPointerSet",""));
8421 right = IC_RIGHT (ic);
8422 result = IC_RESULT (ic);
8424 /* depending on the type of pointer we need to
8425 move it to the correct pointer register */
8426 type = operandType (result);
8427 etype = getSpec (type);
8428 /* if left is of type of pointer then it is simple */
8429 if (IS_PTR (type) && !IS_FUNC (type->next))
8431 p_type = DCL_TYPE (type);
8435 /* we have to go by the storage class */
8436 p_type = PTR_TYPE (SPEC_OCLS (etype));
8439 /* special case when cast remat */
8440 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8441 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8442 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8443 type = operandType (result);
8444 p_type = DCL_TYPE (type);
8446 /* now that we have the pointer type we assign
8447 the pointer values */
8453 genNearPointerSet (right, result, ic, pi);
8457 genPagedPointerSet (right, result, ic, pi);
8461 genFarPointerSet (right, result, ic, pi);
8465 genGenPointerSet (right, result, ic, pi);
8469 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8470 "genPointerSet: illegal pointer type");
8475 /*-----------------------------------------------------------------*/
8476 /* genIfx - generate code for Ifx statement */
8477 /*-----------------------------------------------------------------*/
8479 genIfx (iCode * ic, iCode * popIc)
8481 operand *cond = IC_COND (ic);
8484 D(emitcode ("; genIfx",""));
8486 aopOp (cond, ic, FALSE);
8488 /* get the value into acc */
8489 if (AOP_TYPE (cond) != AOP_CRY)
8493 /* the result is now in the accumulator */
8494 freeAsmop (cond, NULL, ic, TRUE);
8496 /* if there was something to be popped then do it */
8500 /* if the condition is a bit variable */
8501 if (isbit && IS_ITEMP (cond) &&
8503 genIfxJump (ic, SPIL_LOC (cond)->rname);
8504 else if (isbit && !IS_ITEMP (cond))
8505 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8507 genIfxJump (ic, "a");
8512 /*-----------------------------------------------------------------*/
8513 /* genAddrOf - generates code for address of */
8514 /*-----------------------------------------------------------------*/
8516 genAddrOf (iCode * ic)
8518 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8521 D(emitcode ("; genAddrOf",""));
8523 aopOp (IC_RESULT (ic), ic, FALSE);
8525 /* if the operand is on the stack then we
8526 need to get the stack offset of this
8530 /* if it has an offset then we need to compute
8534 emitcode ("mov", "a,_bp");
8535 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8536 ((char) (sym->stack - _G.nRegsSaved)) :
8537 ((char) sym->stack)) & 0xff);
8538 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8542 /* we can just move _bp */
8543 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8545 /* fill the result with zero */
8546 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8551 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8557 /* object not on stack then we need the name */
8558 size = AOP_SIZE (IC_RESULT (ic));
8563 char s[SDCC_NAME_MAX];
8565 sprintf (s, "#(%s >> %d)",
8569 sprintf (s, "#%s", sym->rname);
8570 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8574 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8578 /*-----------------------------------------------------------------*/
8579 /* genFarFarAssign - assignment when both are in far space */
8580 /*-----------------------------------------------------------------*/
8582 genFarFarAssign (operand * result, operand * right, iCode * ic)
8584 int size = AOP_SIZE (right);
8588 D(emitcode ("; genFarFarAssign",""));
8590 /* first push the right side on to the stack */
8593 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8595 emitcode ("push", "acc");
8598 freeAsmop (right, NULL, ic, FALSE);
8599 /* now assign DPTR to result */
8600 aopOp (result, ic, FALSE);
8601 size = AOP_SIZE (result);
8604 emitcode ("pop", "acc");
8605 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8607 freeAsmop (result, NULL, ic, FALSE);
8611 /*-----------------------------------------------------------------*/
8612 /* genAssign - generate code for assignment */
8613 /*-----------------------------------------------------------------*/
8615 genAssign (iCode * ic)
8617 operand *result, *right;
8619 unsigned long lit = 0L;
8621 D(emitcode("; genAssign",""));
8623 result = IC_RESULT (ic);
8624 right = IC_RIGHT (ic);
8626 /* if they are the same */
8627 if (operandsEqu (result, right) &&
8628 !isOperandVolatile (result, FALSE) &&
8629 !isOperandVolatile (right, FALSE))
8632 aopOp (right, ic, FALSE);
8634 /* special case both in far space */
8635 if (AOP_TYPE (right) == AOP_DPTR &&
8636 IS_TRUE_SYMOP (result) &&
8637 isOperandInFarSpace (result))
8640 genFarFarAssign (result, right, ic);
8644 aopOp (result, ic, TRUE);
8646 /* if they are the same registers */
8647 if (sameRegs (AOP (right), AOP (result)) &&
8648 !isOperandVolatile (result, FALSE) &&
8649 !isOperandVolatile (right, FALSE))
8652 /* if the result is a bit */
8653 if (AOP_TYPE (result) == AOP_CRY)
8656 /* if the right size is a literal then
8657 we know what the value is */
8658 if (AOP_TYPE (right) == AOP_LIT)
8660 if (((int) operandLitValue (right)))
8661 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8663 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8667 /* the right is also a bit variable */
8668 if (AOP_TYPE (right) == AOP_CRY)
8670 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8671 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8677 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8681 /* bit variables done */
8683 size = AOP_SIZE (result);
8685 if (AOP_TYPE (right) == AOP_LIT)
8686 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8688 (AOP_TYPE (result) != AOP_REG) &&
8689 (AOP_TYPE (right) == AOP_LIT) &&
8690 !IS_FLOAT (operandType (right)) &&
8693 emitcode ("clr", "a");
8696 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8697 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8699 aopPut (AOP (result),
8700 aopGet (AOP (right), size, FALSE, FALSE),
8702 isOperandVolatile (result, FALSE));
8709 aopPut (AOP (result),
8710 aopGet (AOP (right), offset, FALSE, FALSE),
8712 isOperandVolatile (result, FALSE));
8718 freeAsmop (right, NULL, ic, TRUE);
8719 freeAsmop (result, NULL, ic, TRUE);
8722 /*-----------------------------------------------------------------*/
8723 /* genJumpTab - genrates code for jump table */
8724 /*-----------------------------------------------------------------*/
8726 genJumpTab (iCode * ic)
8731 D(emitcode ("; genJumpTab",""));
8733 aopOp (IC_JTCOND (ic), ic, FALSE);
8734 /* get the condition into accumulator */
8735 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8737 /* multiply by three */
8738 emitcode ("add", "a,acc");
8739 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8740 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8742 jtab = newiTempLabel (NULL);
8743 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8744 emitcode ("jmp", "@a+dptr");
8745 emitcode ("", "%05d$:", jtab->key + 100);
8746 /* now generate the jump labels */
8747 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8748 jtab = setNextItem (IC_JTLABELS (ic)))
8749 emitcode ("ljmp", "%05d$", jtab->key + 100);
8753 /*-----------------------------------------------------------------*/
8754 /* genCast - gen code for casting */
8755 /*-----------------------------------------------------------------*/
8757 genCast (iCode * ic)
8759 operand *result = IC_RESULT (ic);
8760 sym_link *ctype = operandType (IC_LEFT (ic));
8761 sym_link *rtype = operandType (IC_RIGHT (ic));
8762 operand *right = IC_RIGHT (ic);
8765 D(emitcode("; genCast",""));
8767 /* if they are equivalent then do nothing */
8768 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8771 aopOp (right, ic, FALSE);
8772 aopOp (result, ic, FALSE);
8774 /* if the result is a bit (and not a bitfield) */
8775 // if (AOP_TYPE (result) == AOP_CRY)
8776 if (IS_BITVAR (OP_SYMBOL (result)->type)
8777 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8779 /* if the right size is a literal then
8780 we know what the value is */
8781 if (AOP_TYPE (right) == AOP_LIT)
8783 if (((int) operandLitValue (right)))
8784 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8786 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8791 /* the right is also a bit variable */
8792 if (AOP_TYPE (right) == AOP_CRY)
8794 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8795 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8801 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8806 /* if they are the same size : or less */
8807 if (AOP_SIZE (result) <= AOP_SIZE (right))
8810 /* if they are in the same place */
8811 if (sameRegs (AOP (right), AOP (result)))
8814 /* if they in different places then copy */
8815 size = AOP_SIZE (result);
8819 aopPut (AOP (result),
8820 aopGet (AOP (right), offset, FALSE, FALSE),
8822 isOperandVolatile (result, FALSE));
8829 /* if the result is of type pointer */
8834 sym_link *type = operandType (right);
8835 sym_link *etype = getSpec (type);
8837 /* pointer to generic pointer */
8838 if (IS_GENPTR (ctype))
8841 p_type = DCL_TYPE (type);
8844 if (SPEC_SCLS(etype)==S_REGISTER) {
8845 // let's assume it is a generic pointer
8848 /* we have to go by the storage class */
8849 p_type = PTR_TYPE (SPEC_OCLS (etype));
8853 /* the first two bytes are known */
8854 size = GPTRSIZE - 1;
8858 aopPut (AOP (result),
8859 aopGet (AOP (right), offset, FALSE, FALSE),
8861 isOperandVolatile (result, FALSE));
8864 /* the last byte depending on type */
8866 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8871 // pointerTypeToGPByte will have bitched.
8875 sprintf(gpValStr, "#0x%d", gpVal);
8876 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8881 /* just copy the pointers */
8882 size = AOP_SIZE (result);
8886 aopPut (AOP (result),
8887 aopGet (AOP (right), offset, FALSE, FALSE),
8889 isOperandVolatile (result, FALSE));
8895 /* so we now know that the size of destination is greater
8896 than the size of the source */
8897 /* we move to result for the size of source */
8898 size = AOP_SIZE (right);
8902 aopPut (AOP (result),
8903 aopGet (AOP (right), offset, FALSE, FALSE),
8905 isOperandVolatile (result, FALSE));
8909 /* now depending on the sign of the source && destination */
8910 size = AOP_SIZE (result) - AOP_SIZE (right);
8911 /* if unsigned or not an integral type */
8912 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8915 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8919 /* we need to extend the sign :{ */
8920 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8923 emitcode ("rlc", "a");
8924 emitcode ("subb", "a,acc");
8926 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8929 /* we are done hurray !!!! */
8932 freeAsmop (right, NULL, ic, TRUE);
8933 freeAsmop (result, NULL, ic, TRUE);
8937 /*-----------------------------------------------------------------*/
8938 /* genDjnz - generate decrement & jump if not zero instrucion */
8939 /*-----------------------------------------------------------------*/
8941 genDjnz (iCode * ic, iCode * ifx)
8947 D(emitcode ("; genDjnz",""));
8949 /* if the if condition has a false label
8950 then we cannot save */
8954 /* if the minus is not of the form
8956 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8957 !IS_OP_LITERAL (IC_RIGHT (ic)))
8960 if (operandLitValue (IC_RIGHT (ic)) != 1)
8963 /* if the size of this greater than one then no
8965 if (getSize (operandType (IC_RESULT (ic))) > 1)
8968 /* otherwise we can save BIG */
8969 lbl = newiTempLabel (NULL);
8970 lbl1 = newiTempLabel (NULL);
8972 aopOp (IC_RESULT (ic), ic, FALSE);
8974 if (AOP_NEEDSACC(IC_RESULT(ic)))
8976 /* If the result is accessed indirectly via
8977 * the accumulator, we must explicitly write
8978 * it back after the decrement.
8980 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8982 if (strcmp(rByte, "a"))
8984 /* Something is hopelessly wrong */
8985 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8986 __FILE__, __LINE__);
8987 /* We can just give up; the generated code will be inefficient,
8990 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8993 emitcode ("dec", "%s", rByte);
8994 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8995 emitcode ("jnz", "%05d$", lbl->key + 100);
8997 else if (IS_AOP_PREG (IC_RESULT (ic)))
8999 emitcode ("dec", "%s",
9000 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9001 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9002 emitcode ("jnz", "%05d$", lbl->key + 100);
9006 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9009 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9010 emitcode ("", "%05d$:", lbl->key + 100);
9011 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9012 emitcode ("", "%05d$:", lbl1->key + 100);
9014 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9019 /*-----------------------------------------------------------------*/
9020 /* genReceive - generate code for a receive iCode */
9021 /*-----------------------------------------------------------------*/
9023 genReceive (iCode * ic)
9025 int size = getSize (operandType (IC_RESULT (ic)));
9027 D(emitcode ("; genReceive",""));
9029 if (ic->argreg == 1) { /* first parameter */
9030 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9031 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9032 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9034 offset = fReturnSizeMCS51 - size;
9036 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9037 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9040 aopOp (IC_RESULT (ic), ic, FALSE);
9041 size = AOP_SIZE (IC_RESULT (ic));
9044 emitcode ("pop", "acc");
9045 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9050 aopOp (IC_RESULT (ic), ic, FALSE);
9052 assignResultValue (IC_RESULT (ic));
9054 } else { /* second receive onwards */
9056 aopOp (IC_RESULT (ic), ic, FALSE);
9057 rb1off = ic->argreg;
9059 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9062 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9065 /*-----------------------------------------------------------------*/
9066 /* genDummyRead - generate code for dummy read of volatiles */
9067 /*-----------------------------------------------------------------*/
9069 genDummyRead (iCode * ic)
9074 D(emitcode("; genDummyRead",""));
9076 right = IC_RIGHT (ic);
9078 aopOp (right, ic, FALSE);
9080 /* if the result is a bit */
9081 if (AOP_TYPE (right) == AOP_CRY)
9083 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9087 /* bit variables done */
9089 size = AOP_SIZE (right);
9093 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
9098 freeAsmop (right, NULL, ic, TRUE);
9101 /*-----------------------------------------------------------------*/
9102 /* genCritical - generate code for start of a critical sequence */
9103 /*-----------------------------------------------------------------*/
9105 genCritical (iCode *ic)
9107 symbol *tlbl = newiTempLabel (NULL);
9109 D(emitcode("; genCritical",""));
9112 aopOp (IC_RESULT (ic), ic, TRUE);
9114 emitcode ("setb", "c");
9115 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9116 emitcode ("clr", "c");
9117 emitcode ("", "%05d$:", (tlbl->key + 100));
9120 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9122 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9125 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9128 /*-----------------------------------------------------------------*/
9129 /* genEndCritical - generate code for end of a critical sequence */
9130 /*-----------------------------------------------------------------*/
9132 genEndCritical (iCode *ic)
9134 D(emitcode("; genEndCritical",""));
9138 aopOp (IC_RIGHT (ic), ic, FALSE);
9139 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9141 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9142 emitcode ("mov", "ea,c");
9146 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9147 emitcode ("rrc", "a");
9148 emitcode ("mov", "ea,c");
9150 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9154 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9155 emitcode ("mov", "ea,c");
9160 /*-----------------------------------------------------------------*/
9161 /* gen51Code - generate code for 8051 based controllers */
9162 /*-----------------------------------------------------------------*/
9164 gen51Code (iCode * lic)
9169 lineHead = lineCurr = NULL;
9171 /* print the allocation information */
9172 if (allocInfo && currFunc)
9173 printAllocInfo (currFunc, codeOutFile);
9174 /* if debug information required */
9175 if (options.debug && currFunc)
9177 debugFile->writeFunction(currFunc);
9179 if (IS_STATIC (currFunc->etype))
9180 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9182 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9185 /* stack pointer name */
9186 if (options.useXstack)
9192 for (ic = lic; ic; ic = ic->next)
9194 _G.current_iCode = ic;
9196 if (ic->lineno && cln != ic->lineno)
9201 emitcode ("", "C$%s$%d$%d$%d ==.",
9202 FileBaseName (ic->filename), ic->lineno,
9203 ic->level, ic->block);
9206 if (!options.noCcodeInAsm) {
9207 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9208 printCLine(ic->filename, ic->lineno));
9212 if (options.iCodeInAsm) {
9216 for (i=0; i<8; i++) {
9217 sprintf (®sInUse[i],
9218 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9221 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9223 /* if the result is marked as
9224 spilt and rematerializable or code for
9225 this has already been generated then
9227 if (resultRemat (ic) || ic->generated)
9230 /* depending on the operation */
9250 /* IPOP happens only when trying to restore a
9251 spilt live range, if there is an ifx statement
9252 following this pop then the if statement might
9253 be using some of the registers being popped which
9254 would destory the contents of the register so
9255 we need to check for this condition and handle it */
9257 ic->next->op == IFX &&
9258 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9259 genIfx (ic->next, ic);
9277 genEndFunction (ic);
9297 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9314 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9318 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9325 /* note these two are xlated by algebraic equivalence
9326 during parsing SDCC.y */
9327 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9328 "got '>=' or '<=' shouldn't have come here");
9332 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9344 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9348 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9352 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9379 case GET_VALUE_AT_ADDRESS:
9380 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9384 if (POINTER_SET (ic))
9385 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9411 addSet (&_G.sendSet, ic);
9414 case DUMMY_READ_VOLATILE:
9423 genEndCritical (ic);
9435 _G.current_iCode = NULL;
9437 /* now we are ready to call the
9438 peep hole optimizer */
9439 if (!options.nopeep)
9440 peepHole (&lineHead);
9442 /* now do the actual printing */
9443 printLine (lineHead, codeOutFile);