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);
4926 emitcode ("", "%05d$:", tlbl->key + 100);
4934 /* if left is same as result */
4935 if (sameRegs (AOP (result), AOP (left)))
4937 for (; size--; offset++)
4939 if (AOP_TYPE (right) == AOP_LIT)
4941 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4943 else if (bytelit == 0)
4945 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4947 else if (IS_AOP_PREG (result))
4949 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4950 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4951 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4954 emitcode ("anl", "%s,%s",
4955 aopGet (AOP (left), offset, FALSE, TRUE),
4956 aopGet (AOP (right), offset, FALSE, FALSE));
4960 if (AOP_TYPE (left) == AOP_ACC)
4961 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4964 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4965 if (IS_AOP_PREG (result))
4967 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4968 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4972 emitcode ("anl", "%s,a",
4973 aopGet (AOP (left), offset, FALSE, TRUE));
4980 // left & result in different registers
4981 if (AOP_TYPE (result) == AOP_CRY)
4984 // if(size), result in bit
4985 // if(!size && ifx), conditional oper: if(left & right)
4986 symbol *tlbl = newiTempLabel (NULL);
4987 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4989 emitcode ("setb", "c");
4992 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4993 emitcode ("anl", "a,%s",
4994 aopGet (AOP (right), offset, FALSE, FALSE));
4996 if (AOP_TYPE(left)==AOP_ACC) {
4997 emitcode("mov", "b,a");
4998 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4999 emitcode("anl", "a,b");
5001 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5002 emitcode ("anl", "a,%s",
5003 aopGet (AOP (left), offset, FALSE, FALSE));
5006 emitcode ("jnz", "%05d$", tlbl->key + 100);
5012 emitcode ("", "%05d$:", tlbl->key + 100);
5016 jmpTrueOrFalse (ifx, tlbl);
5018 emitcode ("", "%05d$:", tlbl->key + 100);
5022 for (; (size--); offset++)
5025 // result = left & right
5026 if (AOP_TYPE (right) == AOP_LIT)
5028 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5030 aopPut (AOP (result),
5031 aopGet (AOP (left), offset, FALSE, FALSE),
5033 isOperandVolatile (result, FALSE));
5036 else if (bytelit == 0)
5038 /* dummy read of volatile operand */
5039 if (isOperandVolatile (left, FALSE))
5040 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5041 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5045 // faster than result <- left, anl result,right
5046 // and better if result is SFR
5047 if (AOP_TYPE (left) == AOP_ACC)
5048 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5051 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5052 emitcode ("anl", "a,%s",
5053 aopGet (AOP (left), offset, FALSE, FALSE));
5055 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5061 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5062 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5063 freeAsmop (result, NULL, ic, TRUE);
5066 /*-----------------------------------------------------------------*/
5067 /* genOr - code for or */
5068 /*-----------------------------------------------------------------*/
5070 genOr (iCode * ic, iCode * ifx)
5072 operand *left, *right, *result;
5073 int size, offset = 0;
5074 unsigned long lit = 0L;
5076 D(emitcode ("; genOr",""));
5078 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5079 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5080 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5083 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5085 AOP_TYPE (left), AOP_TYPE (right));
5086 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5088 AOP_SIZE (left), AOP_SIZE (right));
5091 /* if left is a literal & right is not then exchange them */
5092 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5093 AOP_NEEDSACC (left))
5095 operand *tmp = right;
5100 /* if result = right then exchange them */
5101 if (sameRegs (AOP (result), AOP (right)))
5103 operand *tmp = right;
5108 /* if right is bit then exchange them */
5109 if (AOP_TYPE (right) == AOP_CRY &&
5110 AOP_TYPE (left) != AOP_CRY)
5112 operand *tmp = right;
5116 if (AOP_TYPE (right) == AOP_LIT)
5117 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5119 size = AOP_SIZE (result);
5123 if (AOP_TYPE (left) == AOP_CRY)
5125 if (AOP_TYPE (right) == AOP_LIT)
5127 // c = bit | literal;
5130 // lit != 0 => result = 1
5131 if (AOP_TYPE (result) == AOP_CRY)
5134 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5136 continueIfTrue (ifx);
5139 emitcode ("setb", "c");
5143 // lit == 0 => result = left
5144 if (size && sameRegs (AOP (result), AOP (left)))
5146 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5151 if (AOP_TYPE (right) == AOP_CRY)
5154 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5155 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5160 symbol *tlbl = newiTempLabel (NULL);
5161 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5162 emitcode ("setb", "c");
5163 emitcode ("jb", "%s,%05d$",
5164 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5166 emitcode ("jnz", "%05d$", tlbl->key + 100);
5167 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5169 jmpTrueOrFalse (ifx, tlbl);
5175 emitcode ("", "%05d$:", tlbl->key + 100);
5184 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5185 genIfxJump (ifx, "c");
5189 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5190 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5191 if ((AOP_TYPE (right) == AOP_LIT) &&
5192 (AOP_TYPE (result) == AOP_CRY) &&
5193 (AOP_TYPE (left) != AOP_CRY))
5199 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5201 continueIfTrue (ifx);
5206 // lit = 0, result = boolean(left)
5208 emitcode ("setb", "c");
5212 symbol *tlbl = newiTempLabel (NULL);
5213 emitcode ("jnz", "%05d$", tlbl->key + 100);
5215 emitcode ("", "%05d$:", tlbl->key + 100);
5219 genIfxJump (ifx, "a");
5227 /* if left is same as result */
5228 if (sameRegs (AOP (result), AOP (left)))
5230 for (; size--; offset++)
5232 if (AOP_TYPE (right) == AOP_LIT)
5234 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5236 /* dummy read of volatile operand */
5237 if (isOperandVolatile (left, FALSE))
5238 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5242 else if (IS_AOP_PREG (left))
5244 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5245 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5246 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5249 emitcode ("orl", "%s,%s",
5250 aopGet (AOP (left), offset, FALSE, TRUE),
5251 aopGet (AOP (right), offset, FALSE, FALSE));
5255 if (AOP_TYPE (left) == AOP_ACC)
5256 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5259 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5260 if (IS_AOP_PREG (left))
5262 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5263 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5266 emitcode ("orl", "%s,a",
5267 aopGet (AOP (left), offset, FALSE, TRUE));
5274 // left & result in different registers
5275 if (AOP_TYPE (result) == AOP_CRY)
5278 // if(size), result in bit
5279 // if(!size && ifx), conditional oper: if(left | right)
5280 symbol *tlbl = newiTempLabel (NULL);
5281 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5283 emitcode ("setb", "c");
5286 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5287 emitcode ("orl", "a,%s",
5288 aopGet (AOP (right), offset, FALSE, FALSE));
5290 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5291 emitcode ("orl", "a,%s",
5292 aopGet (AOP (left), offset, FALSE, FALSE));
5294 emitcode ("jnz", "%05d$", tlbl->key + 100);
5300 emitcode ("", "%05d$:", tlbl->key + 100);
5304 jmpTrueOrFalse (ifx, tlbl);
5306 emitcode ("", "%05d$:", tlbl->key + 100);
5309 for (; (size--); offset++)
5312 // result = left & right
5313 if (AOP_TYPE (right) == AOP_LIT)
5315 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5317 aopPut (AOP (result),
5318 aopGet (AOP (left), offset, FALSE, FALSE),
5320 isOperandVolatile (result, FALSE));
5324 // faster than result <- left, anl result,right
5325 // and better if result is SFR
5326 if (AOP_TYPE (left) == AOP_ACC)
5327 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5330 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5331 emitcode ("orl", "a,%s",
5332 aopGet (AOP (left), offset, FALSE, FALSE));
5334 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5339 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5340 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5341 freeAsmop (result, NULL, ic, TRUE);
5344 /*-----------------------------------------------------------------*/
5345 /* genXor - code for xclusive or */
5346 /*-----------------------------------------------------------------*/
5348 genXor (iCode * ic, iCode * ifx)
5350 operand *left, *right, *result;
5351 int size, offset = 0;
5352 unsigned long lit = 0L;
5354 D(emitcode ("; genXor",""));
5356 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5357 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5358 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5361 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5363 AOP_TYPE (left), AOP_TYPE (right));
5364 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5366 AOP_SIZE (left), AOP_SIZE (right));
5369 /* if left is a literal & right is not ||
5370 if left needs acc & right does not */
5371 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5372 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5374 operand *tmp = right;
5379 /* if result = right then exchange them */
5380 if (sameRegs (AOP (result), AOP (right)))
5382 operand *tmp = right;
5387 /* if right is bit then exchange them */
5388 if (AOP_TYPE (right) == AOP_CRY &&
5389 AOP_TYPE (left) != AOP_CRY)
5391 operand *tmp = right;
5395 if (AOP_TYPE (right) == AOP_LIT)
5396 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5398 size = AOP_SIZE (result);
5402 if (AOP_TYPE (left) == AOP_CRY)
5404 if (AOP_TYPE (right) == AOP_LIT)
5406 // c = bit & literal;
5409 // lit>>1 != 0 => result = 1
5410 if (AOP_TYPE (result) == AOP_CRY)
5413 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5415 continueIfTrue (ifx);
5418 emitcode ("setb", "c");
5425 // lit == 0, result = left
5426 if (size && sameRegs (AOP (result), AOP (left)))
5428 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5432 // lit == 1, result = not(left)
5433 if (size && sameRegs (AOP (result), AOP (left)))
5435 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5440 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5441 emitcode ("cpl", "c");
5450 symbol *tlbl = newiTempLabel (NULL);
5451 if (AOP_TYPE (right) == AOP_CRY)
5454 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5458 int sizer = AOP_SIZE (right);
5460 // if val>>1 != 0, result = 1
5461 emitcode ("setb", "c");
5464 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5466 // test the msb of the lsb
5467 emitcode ("anl", "a,#0xfe");
5468 emitcode ("jnz", "%05d$", tlbl->key + 100);
5472 emitcode ("rrc", "a");
5474 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5475 emitcode ("cpl", "c");
5476 emitcode ("", "%05d$:", (tlbl->key + 100));
5483 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5484 genIfxJump (ifx, "c");
5488 if (sameRegs (AOP (result), AOP (left)))
5490 /* if left is same as result */
5491 for (; size--; offset++)
5493 if (AOP_TYPE (right) == AOP_LIT)
5495 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5497 else if (IS_AOP_PREG (left))
5499 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5500 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5501 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5504 emitcode ("xrl", "%s,%s",
5505 aopGet (AOP (left), offset, FALSE, TRUE),
5506 aopGet (AOP (right), offset, FALSE, FALSE));
5510 if (AOP_TYPE (left) == AOP_ACC)
5511 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5514 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5515 if (IS_AOP_PREG (left))
5517 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5518 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5521 emitcode ("xrl", "%s,a",
5522 aopGet (AOP (left), offset, FALSE, TRUE));
5529 // left & result in different registers
5530 if (AOP_TYPE (result) == AOP_CRY)
5533 // if(size), result in bit
5534 // if(!size && ifx), conditional oper: if(left ^ right)
5535 symbol *tlbl = newiTempLabel (NULL);
5536 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5538 emitcode ("setb", "c");
5541 if ((AOP_TYPE (right) == AOP_LIT) &&
5542 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5544 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5548 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5549 emitcode ("xrl", "a,%s",
5550 aopGet (AOP (right), offset, FALSE, FALSE));
5552 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5553 emitcode ("xrl", "a,%s",
5554 aopGet (AOP (left), offset, FALSE, FALSE));
5557 emitcode ("jnz", "%05d$", tlbl->key + 100);
5563 emitcode ("", "%05d$:", tlbl->key + 100);
5567 jmpTrueOrFalse (ifx, tlbl);
5570 for (; (size--); offset++)
5573 // result = left & right
5574 if (AOP_TYPE (right) == AOP_LIT)
5576 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5578 aopPut (AOP (result),
5579 aopGet (AOP (left), offset, FALSE, FALSE),
5581 isOperandVolatile (result, FALSE));
5585 // faster than result <- left, anl result,right
5586 // and better if result is SFR
5587 if (AOP_TYPE (left) == AOP_ACC)
5588 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5591 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5592 emitcode ("xrl", "a,%s",
5593 aopGet (AOP (left), offset, FALSE, TRUE));
5595 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5600 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5601 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5602 freeAsmop (result, NULL, ic, TRUE);
5605 /*-----------------------------------------------------------------*/
5606 /* genInline - write the inline code out */
5607 /*-----------------------------------------------------------------*/
5609 genInline (iCode * ic)
5611 char *buffer, *bp, *bp1;
5613 D(emitcode ("; genInline",""));
5615 _G.inLine += (!options.asmpeep);
5617 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5618 strcpy (buffer, IC_INLINE (ic));
5620 /* emit each line as a code */
5645 /* emitcode("",buffer); */
5646 _G.inLine -= (!options.asmpeep);
5649 /*-----------------------------------------------------------------*/
5650 /* genRRC - rotate right with carry */
5651 /*-----------------------------------------------------------------*/
5655 operand *left, *result;
5656 int size, offset = 0;
5659 D(emitcode ("; genRRC",""));
5661 /* rotate right with carry */
5662 left = IC_LEFT (ic);
5663 result = IC_RESULT (ic);
5664 aopOp (left, ic, FALSE);
5665 aopOp (result, ic, FALSE);
5667 /* move it to the result */
5668 size = AOP_SIZE (result);
5670 if (size == 1) { /* special case for 1 byte */
5671 l = aopGet (AOP (left), offset, FALSE, FALSE);
5673 emitcode ("rr", "a");
5679 l = aopGet (AOP (left), offset, FALSE, FALSE);
5681 emitcode ("rrc", "a");
5682 if (AOP_SIZE (result) > 1)
5683 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5685 /* now we need to put the carry into the
5686 highest order byte of the result */
5687 if (AOP_SIZE (result) > 1)
5689 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5692 emitcode ("mov", "acc.7,c");
5694 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5695 freeAsmop (left, NULL, ic, TRUE);
5696 freeAsmop (result, NULL, ic, TRUE);
5699 /*-----------------------------------------------------------------*/
5700 /* genRLC - generate code for rotate left with carry */
5701 /*-----------------------------------------------------------------*/
5705 operand *left, *result;
5706 int size, offset = 0;
5709 D(emitcode ("; genRLC",""));
5711 /* rotate right with carry */
5712 left = IC_LEFT (ic);
5713 result = IC_RESULT (ic);
5714 aopOp (left, ic, FALSE);
5715 aopOp (result, ic, FALSE);
5717 /* move it to the result */
5718 size = AOP_SIZE (result);
5722 l = aopGet (AOP (left), offset, FALSE, FALSE);
5724 if (size == 0) { /* special case for 1 byte */
5728 emitcode ("add", "a,acc");
5729 if (AOP_SIZE (result) > 1)
5730 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5733 l = aopGet (AOP (left), offset, FALSE, FALSE);
5735 emitcode ("rlc", "a");
5736 if (AOP_SIZE (result) > 1)
5737 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5740 /* now we need to put the carry into the
5741 highest order byte of the result */
5742 if (AOP_SIZE (result) > 1)
5744 l = aopGet (AOP (result), 0, FALSE, FALSE);
5747 emitcode ("mov", "acc.0,c");
5749 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5750 freeAsmop (left, NULL, ic, TRUE);
5751 freeAsmop (result, NULL, ic, TRUE);
5754 /*-----------------------------------------------------------------*/
5755 /* genGetHbit - generates code get highest order bit */
5756 /*-----------------------------------------------------------------*/
5758 genGetHbit (iCode * ic)
5760 operand *left, *result;
5762 D(emitcode ("; genGetHbit",""));
5764 left = IC_LEFT (ic);
5765 result = IC_RESULT (ic);
5766 aopOp (left, ic, FALSE);
5767 aopOp (result, ic, FALSE);
5769 /* get the highest order byte into a */
5770 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5771 if (AOP_TYPE (result) == AOP_CRY)
5773 emitcode ("rlc", "a");
5778 emitcode ("rl", "a");
5779 emitcode ("anl", "a,#0x01");
5784 freeAsmop (left, NULL, ic, TRUE);
5785 freeAsmop (result, NULL, ic, TRUE);
5788 /*-----------------------------------------------------------------*/
5789 /* genSwap - generates code to swap nibbles or bytes */
5790 /*-----------------------------------------------------------------*/
5792 genSwap (iCode * ic)
5794 operand *left, *result;
5796 D(emitcode ("; genSwap",""));
5798 left = IC_LEFT (ic);
5799 result = IC_RESULT (ic);
5800 aopOp (left, ic, FALSE);
5801 aopOp (result, ic, FALSE);
5803 switch (AOP_SIZE (left))
5805 case 1: /* swap nibbles in byte */
5806 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5807 emitcode ("swap", "a");
5808 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5810 case 2: /* swap bytes in word */
5811 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
5813 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5814 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5815 0, isOperandVolatile (result, FALSE));
5816 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
5818 else if (operandsEqu (left, result))
5821 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5822 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
5824 emitcode ("mov", "b,a");
5827 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5828 0, isOperandVolatile (result, FALSE));
5829 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
5833 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5834 0, isOperandVolatile (result, FALSE));
5835 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
5836 1, isOperandVolatile (result, FALSE));
5840 wassertl(FALSE, "unsupported SWAP operand size");
5843 freeAsmop (left, NULL, ic, TRUE);
5844 freeAsmop (result, NULL, ic, TRUE);
5848 /*-----------------------------------------------------------------*/
5849 /* AccRol - rotate left accumulator by known count */
5850 /*-----------------------------------------------------------------*/
5852 AccRol (int shCount)
5854 shCount &= 0x0007; // shCount : 0..7
5861 emitcode ("rl", "a");
5864 emitcode ("rl", "a");
5865 emitcode ("rl", "a");
5868 emitcode ("swap", "a");
5869 emitcode ("rr", "a");
5872 emitcode ("swap", "a");
5875 emitcode ("swap", "a");
5876 emitcode ("rl", "a");
5879 emitcode ("rr", "a");
5880 emitcode ("rr", "a");
5883 emitcode ("rr", "a");
5888 /*-----------------------------------------------------------------*/
5889 /* AccLsh - left shift accumulator by known count */
5890 /*-----------------------------------------------------------------*/
5892 AccLsh (int shCount)
5897 emitcode ("add", "a,acc");
5898 else if (shCount == 2)
5900 emitcode ("add", "a,acc");
5901 emitcode ("add", "a,acc");
5905 /* rotate left accumulator */
5907 /* and kill the lower order bits */
5908 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5913 /*-----------------------------------------------------------------*/
5914 /* AccRsh - right shift accumulator by known count */
5915 /*-----------------------------------------------------------------*/
5917 AccRsh (int shCount)
5924 emitcode ("rrc", "a");
5928 /* rotate right accumulator */
5929 AccRol (8 - shCount);
5930 /* and kill the higher order bits */
5931 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5936 /*-----------------------------------------------------------------*/
5937 /* AccSRsh - signed right shift accumulator by known count */
5938 /*-----------------------------------------------------------------*/
5940 AccSRsh (int shCount)
5947 emitcode ("mov", "c,acc.7");
5948 emitcode ("rrc", "a");
5950 else if (shCount == 2)
5952 emitcode ("mov", "c,acc.7");
5953 emitcode ("rrc", "a");
5954 emitcode ("mov", "c,acc.7");
5955 emitcode ("rrc", "a");
5959 tlbl = newiTempLabel (NULL);
5960 /* rotate right accumulator */
5961 AccRol (8 - shCount);
5962 /* and kill the higher order bits */
5963 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5964 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5965 emitcode ("orl", "a,#0x%02x",
5966 (unsigned char) ~SRMask[shCount]);
5967 emitcode ("", "%05d$:", tlbl->key + 100);
5972 /*-----------------------------------------------------------------*/
5973 /* shiftR1Left2Result - shift right one byte from left to result */
5974 /*-----------------------------------------------------------------*/
5976 shiftR1Left2Result (operand * left, int offl,
5977 operand * result, int offr,
5978 int shCount, int sign)
5980 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5981 /* shift right accumulator */
5986 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5989 /*-----------------------------------------------------------------*/
5990 /* shiftL1Left2Result - shift left one byte from left to result */
5991 /*-----------------------------------------------------------------*/
5993 shiftL1Left2Result (operand * left, int offl,
5994 operand * result, int offr, int shCount)
5997 l = aopGet (AOP (left), offl, FALSE, FALSE);
5999 /* shift left accumulator */
6001 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6004 /*-----------------------------------------------------------------*/
6005 /* movLeft2Result - move byte from left to result */
6006 /*-----------------------------------------------------------------*/
6008 movLeft2Result (operand * left, int offl,
6009 operand * result, int offr, int sign)
6012 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6014 l = aopGet (AOP (left), offl, FALSE, FALSE);
6016 if (*l == '@' && (IS_AOP_PREG (result)))
6018 emitcode ("mov", "a,%s", l);
6019 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6024 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6027 /* MSB sign in acc.7 ! */
6028 if (getDataSize (left) == offl + 1)
6030 emitcode ("mov", "a,%s", l);
6031 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6038 /*-----------------------------------------------------------------*/
6039 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6040 /*-----------------------------------------------------------------*/
6044 emitcode ("rrc", "a");
6045 emitcode ("xch", "a,%s", x);
6046 emitcode ("rrc", "a");
6047 emitcode ("xch", "a,%s", x);
6050 /*-----------------------------------------------------------------*/
6051 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6052 /*-----------------------------------------------------------------*/
6056 emitcode ("xch", "a,%s", x);
6057 emitcode ("rlc", "a");
6058 emitcode ("xch", "a,%s", x);
6059 emitcode ("rlc", "a");
6062 /*-----------------------------------------------------------------*/
6063 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6064 /*-----------------------------------------------------------------*/
6068 emitcode ("xch", "a,%s", x);
6069 emitcode ("add", "a,acc");
6070 emitcode ("xch", "a,%s", x);
6071 emitcode ("rlc", "a");
6074 /*-----------------------------------------------------------------*/
6075 /* AccAXLsh - left shift a:x by known count (0..7) */
6076 /*-----------------------------------------------------------------*/
6078 AccAXLsh (char *x, int shCount)
6093 case 5: // AAAAABBB:CCCCCDDD
6095 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6097 emitcode ("anl", "a,#0x%02x",
6098 SLMask[shCount]); // BBB00000:CCCCCDDD
6100 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6102 AccRol (shCount); // DDDCCCCC:BBB00000
6104 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6106 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6108 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6110 emitcode ("anl", "a,#0x%02x",
6111 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6113 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6115 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6118 case 6: // AAAAAABB:CCCCCCDD
6119 emitcode ("anl", "a,#0x%02x",
6120 SRMask[shCount]); // 000000BB:CCCCCCDD
6121 emitcode ("mov", "c,acc.0"); // c = B
6122 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6124 AccAXRrl1 (x); // BCCCCCCD:D000000B
6125 AccAXRrl1 (x); // BBCCCCCC:DD000000
6127 emitcode("rrc","a");
6128 emitcode("xch","a,%s", x);
6129 emitcode("rrc","a");
6130 emitcode("mov","c,acc.0"); //<< get correct bit
6131 emitcode("xch","a,%s", x);
6133 emitcode("rrc","a");
6134 emitcode("xch","a,%s", x);
6135 emitcode("rrc","a");
6136 emitcode("xch","a,%s", x);
6139 case 7: // a:x <<= 7
6141 emitcode ("anl", "a,#0x%02x",
6142 SRMask[shCount]); // 0000000B:CCCCCCCD
6144 emitcode ("mov", "c,acc.0"); // c = B
6146 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6148 AccAXRrl1 (x); // BCCCCCCC:D0000000
6156 /*-----------------------------------------------------------------*/
6157 /* AccAXRsh - right shift a:x known count (0..7) */
6158 /*-----------------------------------------------------------------*/
6160 AccAXRsh (char *x, int shCount)
6168 AccAXRrl1 (x); // 0->a:x
6173 AccAXRrl1 (x); // 0->a:x
6176 AccAXRrl1 (x); // 0->a:x
6181 case 5: // AAAAABBB:CCCCCDDD = a:x
6183 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6185 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6187 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6189 emitcode ("anl", "a,#0x%02x",
6190 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6192 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6194 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6196 emitcode ("anl", "a,#0x%02x",
6197 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6199 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6201 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6203 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6206 case 6: // AABBBBBB:CCDDDDDD
6208 emitcode ("mov", "c,acc.7");
6209 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6211 emitcode ("mov", "c,acc.7");
6212 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6214 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6216 emitcode ("anl", "a,#0x%02x",
6217 SRMask[shCount]); // 000000AA:BBBBBBCC
6220 case 7: // ABBBBBBB:CDDDDDDD
6222 emitcode ("mov", "c,acc.7"); // c = A
6224 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6226 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6228 emitcode ("anl", "a,#0x%02x",
6229 SRMask[shCount]); // 0000000A:BBBBBBBC
6237 /*-----------------------------------------------------------------*/
6238 /* AccAXRshS - right shift signed a:x known count (0..7) */
6239 /*-----------------------------------------------------------------*/
6241 AccAXRshS (char *x, int shCount)
6249 emitcode ("mov", "c,acc.7");
6250 AccAXRrl1 (x); // s->a:x
6254 emitcode ("mov", "c,acc.7");
6255 AccAXRrl1 (x); // s->a:x
6257 emitcode ("mov", "c,acc.7");
6258 AccAXRrl1 (x); // s->a:x
6263 case 5: // AAAAABBB:CCCCCDDD = a:x
6265 tlbl = newiTempLabel (NULL);
6266 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6268 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6270 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6272 emitcode ("anl", "a,#0x%02x",
6273 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6275 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6277 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6279 emitcode ("anl", "a,#0x%02x",
6280 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6282 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6284 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6286 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6288 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6289 emitcode ("orl", "a,#0x%02x",
6290 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6292 emitcode ("", "%05d$:", tlbl->key + 100);
6293 break; // SSSSAAAA:BBBCCCCC
6295 case 6: // AABBBBBB:CCDDDDDD
6297 tlbl = newiTempLabel (NULL);
6298 emitcode ("mov", "c,acc.7");
6299 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6301 emitcode ("mov", "c,acc.7");
6302 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6304 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6306 emitcode ("anl", "a,#0x%02x",
6307 SRMask[shCount]); // 000000AA:BBBBBBCC
6309 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6310 emitcode ("orl", "a,#0x%02x",
6311 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6313 emitcode ("", "%05d$:", tlbl->key + 100);
6315 case 7: // ABBBBBBB:CDDDDDDD
6317 tlbl = newiTempLabel (NULL);
6318 emitcode ("mov", "c,acc.7"); // c = A
6320 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6322 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6324 emitcode ("anl", "a,#0x%02x",
6325 SRMask[shCount]); // 0000000A:BBBBBBBC
6327 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6328 emitcode ("orl", "a,#0x%02x",
6329 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6331 emitcode ("", "%05d$:", tlbl->key + 100);
6338 /*-----------------------------------------------------------------*/
6339 /* shiftL2Left2Result - shift left two bytes from left to result */
6340 /*-----------------------------------------------------------------*/
6342 shiftL2Left2Result (operand * left, int offl,
6343 operand * result, int offr, int shCount)
6345 if (sameRegs (AOP (result), AOP (left)) &&
6346 ((offl + MSB16) == offr))
6348 /* don't crash result[offr] */
6349 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6350 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6354 movLeft2Result (left, offl, result, offr, 0);
6355 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6357 /* ax << shCount (x = lsb(result)) */
6358 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6359 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6363 /*-----------------------------------------------------------------*/
6364 /* shiftR2Left2Result - shift right two bytes from left to result */
6365 /*-----------------------------------------------------------------*/
6367 shiftR2Left2Result (operand * left, int offl,
6368 operand * result, int offr,
6369 int shCount, int sign)
6371 if (sameRegs (AOP (result), AOP (left)) &&
6372 ((offl + MSB16) == offr))
6374 /* don't crash result[offr] */
6375 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6376 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6380 movLeft2Result (left, offl, result, offr, 0);
6381 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6383 /* a:x >> shCount (x = lsb(result)) */
6385 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6387 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6388 if (getDataSize (result) > 1)
6389 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6392 /*-----------------------------------------------------------------*/
6393 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6394 /*-----------------------------------------------------------------*/
6396 shiftLLeftOrResult (operand * left, int offl,
6397 operand * result, int offr, int shCount)
6399 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6400 /* shift left accumulator */
6402 /* or with result */
6403 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6404 /* back to result */
6405 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6408 /*-----------------------------------------------------------------*/
6409 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6410 /*-----------------------------------------------------------------*/
6412 shiftRLeftOrResult (operand * left, int offl,
6413 operand * result, int offr, int shCount)
6415 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6416 /* shift right accumulator */
6418 /* or with result */
6419 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6420 /* back to result */
6421 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6424 /*-----------------------------------------------------------------*/
6425 /* genlshOne - left shift a one byte quantity by known count */
6426 /*-----------------------------------------------------------------*/
6428 genlshOne (operand * result, operand * left, int shCount)
6430 D(emitcode ("; genlshOne",""));
6432 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6435 /*-----------------------------------------------------------------*/
6436 /* genlshTwo - left shift two bytes by known amount != 0 */
6437 /*-----------------------------------------------------------------*/
6439 genlshTwo (operand * result, operand * left, int shCount)
6443 D(emitcode ("; genlshTwo",""));
6445 size = getDataSize (result);
6447 /* if shCount >= 8 */
6455 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6457 movLeft2Result (left, LSB, result, MSB16, 0);
6459 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6462 /* 1 <= shCount <= 7 */
6466 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6468 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6472 /*-----------------------------------------------------------------*/
6473 /* shiftLLong - shift left one long from left to result */
6474 /* offl = LSB or MSB16 */
6475 /*-----------------------------------------------------------------*/
6477 shiftLLong (operand * left, operand * result, int offr)
6480 int size = AOP_SIZE (result);
6482 if (size >= LSB + offr)
6484 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6486 emitcode ("add", "a,acc");
6487 if (sameRegs (AOP (left), AOP (result)) &&
6488 size >= MSB16 + offr && offr != LSB)
6489 emitcode ("xch", "a,%s",
6490 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6492 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6495 if (size >= MSB16 + offr)
6497 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6499 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6502 emitcode ("rlc", "a");
6503 if (sameRegs (AOP (left), AOP (result)) &&
6504 size >= MSB24 + offr && offr != LSB)
6505 emitcode ("xch", "a,%s",
6506 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6508 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6511 if (size >= MSB24 + offr)
6513 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6515 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6518 emitcode ("rlc", "a");
6519 if (sameRegs (AOP (left), AOP (result)) &&
6520 size >= MSB32 + offr && offr != LSB)
6521 emitcode ("xch", "a,%s",
6522 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6524 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6527 if (size > MSB32 + offr)
6529 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6531 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6534 emitcode ("rlc", "a");
6535 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6538 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6541 /*-----------------------------------------------------------------*/
6542 /* genlshFour - shift four byte by a known amount != 0 */
6543 /*-----------------------------------------------------------------*/
6545 genlshFour (operand * result, operand * left, int shCount)
6549 D(emitcode ("; genlshFour",""));
6551 size = AOP_SIZE (result);
6553 /* if shifting more that 3 bytes */
6558 /* lowest order of left goes to the highest
6559 order of the destination */
6560 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6562 movLeft2Result (left, LSB, result, MSB32, 0);
6563 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6564 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6565 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6569 /* more than two bytes */
6570 else if (shCount >= 16)
6572 /* lower order two bytes goes to higher order two bytes */
6574 /* if some more remaining */
6576 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6579 movLeft2Result (left, MSB16, result, MSB32, 0);
6580 movLeft2Result (left, LSB, result, MSB24, 0);
6582 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6583 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6587 /* if more than 1 byte */
6588 else if (shCount >= 8)
6590 /* lower order three bytes goes to higher order three bytes */
6595 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6597 movLeft2Result (left, LSB, result, MSB16, 0);
6603 movLeft2Result (left, MSB24, result, MSB32, 0);
6604 movLeft2Result (left, MSB16, result, MSB24, 0);
6605 movLeft2Result (left, LSB, result, MSB16, 0);
6606 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6608 else if (shCount == 1)
6609 shiftLLong (left, result, MSB16);
6612 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6613 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6614 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6615 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6620 /* 1 <= shCount <= 7 */
6621 else if (shCount <= 2)
6623 shiftLLong (left, result, LSB);
6625 shiftLLong (result, result, LSB);
6627 /* 3 <= shCount <= 7, optimize */
6630 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6631 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6632 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6636 /*-----------------------------------------------------------------*/
6637 /* genLeftShiftLiteral - left shifting by known count */
6638 /*-----------------------------------------------------------------*/
6640 genLeftShiftLiteral (operand * left,
6645 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6648 D(emitcode ("; genLeftShiftLiteral",""));
6650 freeAsmop (right, NULL, ic, TRUE);
6652 aopOp (left, ic, FALSE);
6653 aopOp (result, ic, FALSE);
6655 size = getSize (operandType (result));
6658 emitcode ("; shift left ", "result %d, left %d", size,
6662 /* I suppose that the left size >= result size */
6667 movLeft2Result (left, size, result, size, 0);
6671 else if (shCount >= (size * 8))
6673 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6679 genlshOne (result, left, shCount);
6683 genlshTwo (result, left, shCount);
6687 genlshFour (result, left, shCount);
6690 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6691 "*** ack! mystery literal shift!\n");
6695 freeAsmop (left, NULL, ic, TRUE);
6696 freeAsmop (result, NULL, ic, TRUE);
6699 /*-----------------------------------------------------------------*/
6700 /* genLeftShift - generates code for left shifting */
6701 /*-----------------------------------------------------------------*/
6703 genLeftShift (iCode * ic)
6705 operand *left, *right, *result;
6708 symbol *tlbl, *tlbl1;
6710 D(emitcode ("; genLeftShift",""));
6712 right = IC_RIGHT (ic);
6713 left = IC_LEFT (ic);
6714 result = IC_RESULT (ic);
6716 aopOp (right, ic, FALSE);
6718 /* if the shift count is known then do it
6719 as efficiently as possible */
6720 if (AOP_TYPE (right) == AOP_LIT)
6722 genLeftShiftLiteral (left, right, result, ic);
6726 /* shift count is unknown then we have to form
6727 a loop get the loop count in B : Note: we take
6728 only the lower order byte since shifting
6729 more that 32 bits make no sense anyway, ( the
6730 largest size of an object can be only 32 bits ) */
6732 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6733 emitcode ("inc", "b");
6734 freeAsmop (right, NULL, ic, TRUE);
6735 aopOp (left, ic, FALSE);
6736 aopOp (result, ic, FALSE);
6738 /* now move the left to the result if they are not the
6740 if (!sameRegs (AOP (left), AOP (result)) &&
6741 AOP_SIZE (result) > 1)
6744 size = AOP_SIZE (result);
6748 l = aopGet (AOP (left), offset, FALSE, TRUE);
6749 if (*l == '@' && (IS_AOP_PREG (result)))
6752 emitcode ("mov", "a,%s", l);
6753 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6756 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6761 tlbl = newiTempLabel (NULL);
6762 size = AOP_SIZE (result);
6764 tlbl1 = newiTempLabel (NULL);
6766 /* if it is only one byte then */
6769 symbol *tlbl1 = newiTempLabel (NULL);
6771 l = aopGet (AOP (left), 0, FALSE, FALSE);
6773 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6774 emitcode ("", "%05d$:", tlbl->key + 100);
6775 emitcode ("add", "a,acc");
6776 emitcode ("", "%05d$:", tlbl1->key + 100);
6777 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6778 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6782 reAdjustPreg (AOP (result));
6784 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6785 emitcode ("", "%05d$:", tlbl->key + 100);
6786 l = aopGet (AOP (result), offset, FALSE, FALSE);
6788 emitcode ("add", "a,acc");
6789 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6792 l = aopGet (AOP (result), offset, FALSE, FALSE);
6794 emitcode ("rlc", "a");
6795 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6797 reAdjustPreg (AOP (result));
6799 emitcode ("", "%05d$:", tlbl1->key + 100);
6800 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6802 freeAsmop (left, NULL, ic, TRUE);
6803 freeAsmop (result, NULL, ic, TRUE);
6806 /*-----------------------------------------------------------------*/
6807 /* genrshOne - right shift a one byte quantity by known count */
6808 /*-----------------------------------------------------------------*/
6810 genrshOne (operand * result, operand * left,
6811 int shCount, int sign)
6813 D(emitcode ("; genrshOne",""));
6815 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6818 /*-----------------------------------------------------------------*/
6819 /* genrshTwo - right shift two bytes by known amount != 0 */
6820 /*-----------------------------------------------------------------*/
6822 genrshTwo (operand * result, operand * left,
6823 int shCount, int sign)
6825 D(emitcode ("; genrshTwo",""));
6827 /* if shCount >= 8 */
6832 shiftR1Left2Result (left, MSB16, result, LSB,
6835 movLeft2Result (left, MSB16, result, LSB, sign);
6836 addSign (result, MSB16, sign);
6839 /* 1 <= shCount <= 7 */
6841 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6844 /*-----------------------------------------------------------------*/
6845 /* shiftRLong - shift right one long from left to result */
6846 /* offl = LSB or MSB16 */
6847 /*-----------------------------------------------------------------*/
6849 shiftRLong (operand * left, int offl,
6850 operand * result, int sign)
6852 int isSameRegs=sameRegs(AOP(left),AOP(result));
6854 if (isSameRegs && offl>1) {
6855 // we are in big trouble, but this shouldn't happen
6856 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6859 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6864 emitcode ("rlc", "a");
6865 emitcode ("subb", "a,acc");
6867 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6869 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6870 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6873 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6878 emitcode ("clr", "c");
6880 emitcode ("mov", "c,acc.7");
6883 emitcode ("rrc", "a");
6885 if (isSameRegs && offl==MSB16) {
6886 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6888 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6889 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6892 emitcode ("rrc", "a");
6893 if (isSameRegs && offl==1) {
6894 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6896 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6897 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6899 emitcode ("rrc", "a");
6900 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6904 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6905 emitcode ("rrc", "a");
6906 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6910 /*-----------------------------------------------------------------*/
6911 /* genrshFour - shift four byte by a known amount != 0 */
6912 /*-----------------------------------------------------------------*/
6914 genrshFour (operand * result, operand * left,
6915 int shCount, int sign)
6917 D(emitcode ("; genrshFour",""));
6919 /* if shifting more that 3 bytes */
6924 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6926 movLeft2Result (left, MSB32, result, LSB, sign);
6927 addSign (result, MSB16, sign);
6929 else if (shCount >= 16)
6933 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6936 movLeft2Result (left, MSB24, result, LSB, 0);
6937 movLeft2Result (left, MSB32, result, MSB16, sign);
6939 addSign (result, MSB24, sign);
6941 else if (shCount >= 8)
6945 shiftRLong (left, MSB16, result, sign);
6946 else if (shCount == 0)
6948 movLeft2Result (left, MSB16, result, LSB, 0);
6949 movLeft2Result (left, MSB24, result, MSB16, 0);
6950 movLeft2Result (left, MSB32, result, MSB24, sign);
6951 addSign (result, MSB32, sign);
6955 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6956 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6957 /* the last shift is signed */
6958 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6959 addSign (result, MSB32, sign);
6963 { /* 1 <= shCount <= 7 */
6966 shiftRLong (left, LSB, result, sign);
6968 shiftRLong (result, LSB, result, sign);
6972 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6973 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6974 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6979 /*-----------------------------------------------------------------*/
6980 /* genRightShiftLiteral - right shifting by known count */
6981 /*-----------------------------------------------------------------*/
6983 genRightShiftLiteral (operand * left,
6989 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6992 D(emitcode ("; genRightShiftLiteral",""));
6994 freeAsmop (right, NULL, ic, TRUE);
6996 aopOp (left, ic, FALSE);
6997 aopOp (result, ic, FALSE);
7000 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7004 size = getDataSize (left);
7005 /* test the LEFT size !!! */
7007 /* I suppose that the left size >= result size */
7010 size = getDataSize (result);
7012 movLeft2Result (left, size, result, size, 0);
7015 else if (shCount >= (size * 8))
7018 /* get sign in acc.7 */
7019 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7021 addSign (result, LSB, sign);
7028 genrshOne (result, left, shCount, sign);
7032 genrshTwo (result, left, shCount, sign);
7036 genrshFour (result, left, shCount, sign);
7042 freeAsmop (left, NULL, ic, TRUE);
7043 freeAsmop (result, NULL, ic, TRUE);
7046 /*-----------------------------------------------------------------*/
7047 /* genSignedRightShift - right shift of signed number */
7048 /*-----------------------------------------------------------------*/
7050 genSignedRightShift (iCode * ic)
7052 operand *right, *left, *result;
7055 symbol *tlbl, *tlbl1;
7057 D(emitcode ("; genSignedRightShift",""));
7059 /* we do it the hard way put the shift count in b
7060 and loop thru preserving the sign */
7062 right = IC_RIGHT (ic);
7063 left = IC_LEFT (ic);
7064 result = IC_RESULT (ic);
7066 aopOp (right, ic, FALSE);
7069 if (AOP_TYPE (right) == AOP_LIT)
7071 genRightShiftLiteral (left, right, result, ic, 1);
7074 /* shift count is unknown then we have to form
7075 a loop get the loop count in B : Note: we take
7076 only the lower order byte since shifting
7077 more that 32 bits make no sense anyway, ( the
7078 largest size of an object can be only 32 bits ) */
7080 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7081 emitcode ("inc", "b");
7082 freeAsmop (right, NULL, ic, TRUE);
7083 aopOp (left, ic, FALSE);
7084 aopOp (result, ic, FALSE);
7086 /* now move the left to the result if they are not the
7088 if (!sameRegs (AOP (left), AOP (result)) &&
7089 AOP_SIZE (result) > 1)
7092 size = AOP_SIZE (result);
7096 l = aopGet (AOP (left), offset, FALSE, TRUE);
7097 if (*l == '@' && IS_AOP_PREG (result))
7100 emitcode ("mov", "a,%s", l);
7101 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7104 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7109 /* mov the highest order bit to OVR */
7110 tlbl = newiTempLabel (NULL);
7111 tlbl1 = newiTempLabel (NULL);
7113 size = AOP_SIZE (result);
7115 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7116 emitcode ("rlc", "a");
7117 emitcode ("mov", "ov,c");
7118 /* if it is only one byte then */
7121 l = aopGet (AOP (left), 0, FALSE, FALSE);
7123 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7124 emitcode ("", "%05d$:", tlbl->key + 100);
7125 emitcode ("mov", "c,ov");
7126 emitcode ("rrc", "a");
7127 emitcode ("", "%05d$:", tlbl1->key + 100);
7128 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7129 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7133 reAdjustPreg (AOP (result));
7134 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7135 emitcode ("", "%05d$:", tlbl->key + 100);
7136 emitcode ("mov", "c,ov");
7139 l = aopGet (AOP (result), offset, FALSE, FALSE);
7141 emitcode ("rrc", "a");
7142 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7144 reAdjustPreg (AOP (result));
7145 emitcode ("", "%05d$:", tlbl1->key + 100);
7146 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7149 freeAsmop (left, NULL, ic, TRUE);
7150 freeAsmop (result, NULL, ic, TRUE);
7153 /*-----------------------------------------------------------------*/
7154 /* genRightShift - generate code for right shifting */
7155 /*-----------------------------------------------------------------*/
7157 genRightShift (iCode * ic)
7159 operand *right, *left, *result;
7163 symbol *tlbl, *tlbl1;
7165 D(emitcode ("; genRightShift",""));
7167 /* if signed then we do it the hard way preserve the
7168 sign bit moving it inwards */
7169 retype = getSpec (operandType (IC_RESULT (ic)));
7171 if (!SPEC_USIGN (retype))
7173 genSignedRightShift (ic);
7177 /* signed & unsigned types are treated the same : i.e. the
7178 signed is NOT propagated inwards : quoting from the
7179 ANSI - standard : "for E1 >> E2, is equivalent to division
7180 by 2**E2 if unsigned or if it has a non-negative value,
7181 otherwise the result is implementation defined ", MY definition
7182 is that the sign does not get propagated */
7184 right = IC_RIGHT (ic);
7185 left = IC_LEFT (ic);
7186 result = IC_RESULT (ic);
7188 aopOp (right, ic, FALSE);
7190 /* if the shift count is known then do it
7191 as efficiently as possible */
7192 if (AOP_TYPE (right) == AOP_LIT)
7194 genRightShiftLiteral (left, right, result, ic, 0);
7198 /* shift count is unknown then we have to form
7199 a loop get the loop count in B : Note: we take
7200 only the lower order byte since shifting
7201 more that 32 bits make no sense anyway, ( the
7202 largest size of an object can be only 32 bits ) */
7204 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7205 emitcode ("inc", "b");
7206 freeAsmop (right, NULL, ic, TRUE);
7207 aopOp (left, ic, FALSE);
7208 aopOp (result, ic, FALSE);
7210 /* now move the left to the result if they are not the
7212 if (!sameRegs (AOP (left), AOP (result)) &&
7213 AOP_SIZE (result) > 1)
7216 size = AOP_SIZE (result);
7220 l = aopGet (AOP (left), offset, FALSE, TRUE);
7221 if (*l == '@' && IS_AOP_PREG (result))
7224 emitcode ("mov", "a,%s", l);
7225 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7228 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7233 tlbl = newiTempLabel (NULL);
7234 tlbl1 = newiTempLabel (NULL);
7235 size = AOP_SIZE (result);
7238 /* if it is only one byte then */
7241 l = aopGet (AOP (left), 0, FALSE, FALSE);
7243 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7244 emitcode ("", "%05d$:", tlbl->key + 100);
7246 emitcode ("rrc", "a");
7247 emitcode ("", "%05d$:", tlbl1->key + 100);
7248 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7249 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7253 reAdjustPreg (AOP (result));
7254 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7255 emitcode ("", "%05d$:", tlbl->key + 100);
7259 l = aopGet (AOP (result), offset, FALSE, FALSE);
7261 emitcode ("rrc", "a");
7262 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7264 reAdjustPreg (AOP (result));
7266 emitcode ("", "%05d$:", tlbl1->key + 100);
7267 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7270 freeAsmop (left, NULL, ic, TRUE);
7271 freeAsmop (result, NULL, ic, TRUE);
7274 /*-----------------------------------------------------------------*/
7275 /* emitPtrByteGet - emits code to get a byte into A through a */
7276 /* pointer register (R0, R1, or DPTR). The */
7277 /* original value of A can be preserved in B. */
7278 /*-----------------------------------------------------------------*/
7280 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7287 emitcode ("mov", "b,a");
7288 emitcode ("mov", "a,@%s", rname);
7293 emitcode ("mov", "b,a");
7294 emitcode ("movx", "a,@%s", rname);
7299 emitcode ("mov", "b,a");
7300 emitcode ("movx", "a,@dptr");
7305 emitcode ("mov", "b,a");
7306 emitcode ("clr", "a");
7307 emitcode ("movc", "a,@a+dptr");
7313 emitcode ("push", "b");
7314 emitcode ("push", "acc");
7316 emitcode ("lcall", "__gptrget");
7318 emitcode ("pop", "b");
7323 /*-----------------------------------------------------------------*/
7324 /* emitPtrByteSet - emits code to set a byte from src through a */
7325 /* pointer register (R0, R1, or DPTR). */
7326 /*-----------------------------------------------------------------*/
7328 emitPtrByteSet (char *rname, int p_type, char *src)
7337 emitcode ("mov", "@%s,a", rname);
7340 emitcode ("mov", "@%s,%s", rname, src);
7345 emitcode ("movx", "@%s,a", rname);
7350 emitcode ("movx", "@dptr,a");
7355 emitcode ("lcall", "__gptrput");
7360 /*-----------------------------------------------------------------*/
7361 /* genUnpackBits - generates code for unpacking bits */
7362 /*-----------------------------------------------------------------*/
7364 genUnpackBits (operand * result, char *rname, int ptype)
7366 int offset = 0; /* result byte offset */
7367 int rsize; /* result size */
7368 int rlen = 0; /* remaining bitfield length */
7369 sym_link *etype; /* bitfield type information */
7370 int blen; /* bitfield length */
7371 int bstr; /* bitfield starting bit within byte */
7373 D(emitcode ("; genUnpackBits",""));
7375 etype = getSpec (operandType (result));
7376 rsize = getSize (operandType (result));
7377 blen = SPEC_BLEN (etype);
7378 bstr = SPEC_BSTR (etype);
7380 /* If the bitfield length is less than a byte */
7383 emitPtrByteGet (rname, ptype, FALSE);
7385 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7386 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7390 /* Bit field did not fit in a byte. Copy all
7391 but the partial byte at the end. */
7392 for (rlen=blen;rlen>=8;rlen-=8)
7394 emitPtrByteGet (rname, ptype, FALSE);
7395 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7397 emitcode ("inc", "%s", rname);
7400 /* Handle the partial byte at the end */
7403 emitPtrByteGet (rname, ptype, FALSE);
7404 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7405 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7413 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7418 /*-----------------------------------------------------------------*/
7419 /* genDataPointerGet - generates code when ptr offset is known */
7420 /*-----------------------------------------------------------------*/
7422 genDataPointerGet (operand * left,
7428 int size, offset = 0;
7430 D(emitcode ("; genDataPointerGet",""));
7432 aopOp (result, ic, TRUE);
7434 /* get the string representation of the name */
7435 l = aopGet (AOP (left), 0, FALSE, TRUE);
7436 size = AOP_SIZE (result);
7440 sprintf (buffer, "(%s + %d)", l + 1, offset);
7442 sprintf (buffer, "%s", l + 1);
7443 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7446 freeAsmop (left, NULL, ic, TRUE);
7447 freeAsmop (result, NULL, ic, TRUE);
7450 /*-----------------------------------------------------------------*/
7451 /* genNearPointerGet - emitcode for near pointer fetch */
7452 /*-----------------------------------------------------------------*/
7454 genNearPointerGet (operand * left,
7462 sym_link *rtype, *retype;
7463 sym_link *ltype = operandType (left);
7466 D(emitcode ("; genNearPointerGet",""));
7468 rtype = operandType (result);
7469 retype = getSpec (rtype);
7471 aopOp (left, ic, FALSE);
7473 /* if left is rematerialisable and
7474 result is not bit variable type and
7475 the left is pointer to data space i.e
7476 lower 128 bytes of space */
7477 if (AOP_TYPE (left) == AOP_IMMD &&
7478 !IS_BITVAR (retype) &&
7479 DCL_TYPE (ltype) == POINTER)
7481 genDataPointerGet (left, result, ic);
7485 /* if the value is already in a pointer register
7486 then don't need anything more */
7487 if (!AOP_INPREG (AOP (left)))
7489 if (IS_AOP_PREG (left))
7491 // Aha, it is a pointer, just in disguise.
7492 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7495 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7496 __FILE__, __LINE__);
7501 emitcode ("mov", "a%s,%s", rname + 1, rname);
7502 rname++; // skip the '@'.
7507 /* otherwise get a free pointer register */
7509 preg = getFreePtr (ic, &aop, FALSE);
7510 emitcode ("mov", "%s,%s",
7512 aopGet (AOP (left), 0, FALSE, TRUE));
7517 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7519 //aopOp (result, ic, FALSE);
7520 aopOp (result, ic, result?TRUE:FALSE);
7522 /* if bitfield then unpack the bits */
7523 if (IS_BITVAR (retype))
7524 genUnpackBits (result, rname, POINTER);
7527 /* we have can just get the values */
7528 int size = AOP_SIZE (result);
7533 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7536 emitcode ("mov", "a,@%s", rname);
7537 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7541 sprintf (buffer, "@%s", rname);
7542 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7546 emitcode ("inc", "%s", rname);
7550 /* now some housekeeping stuff */
7551 if (aop) /* we had to allocate for this iCode */
7553 if (pi) { /* post increment present */
7554 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7556 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7560 /* we did not allocate which means left
7561 already in a pointer register, then
7562 if size > 0 && this could be used again
7563 we have to point it back to where it
7565 if ((AOP_SIZE (result) > 1 &&
7566 !OP_SYMBOL (left)->remat &&
7567 (OP_SYMBOL (left)->liveTo > ic->seq ||
7571 int size = AOP_SIZE (result) - 1;
7573 emitcode ("dec", "%s", rname);
7578 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7579 freeAsmop (left, NULL, ic, TRUE);
7580 if (pi) pi->generated = 1;
7583 /*-----------------------------------------------------------------*/
7584 /* genPagedPointerGet - emitcode for paged pointer fetch */
7585 /*-----------------------------------------------------------------*/
7587 genPagedPointerGet (operand * left,
7595 sym_link *rtype, *retype;
7597 D(emitcode ("; genPagedPointerGet",""));
7599 rtype = operandType (result);
7600 retype = getSpec (rtype);
7602 aopOp (left, ic, FALSE);
7604 /* if the value is already in a pointer register
7605 then don't need anything more */
7606 if (!AOP_INPREG (AOP (left)))
7608 /* otherwise get a free pointer register */
7610 preg = getFreePtr (ic, &aop, FALSE);
7611 emitcode ("mov", "%s,%s",
7613 aopGet (AOP (left), 0, FALSE, TRUE));
7617 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7619 aopOp (result, ic, FALSE);
7621 /* if bitfield then unpack the bits */
7622 if (IS_BITVAR (retype))
7623 genUnpackBits (result, rname, PPOINTER);
7626 /* we have can just get the values */
7627 int size = AOP_SIZE (result);
7633 emitcode ("movx", "a,@%s", rname);
7634 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7639 emitcode ("inc", "%s", rname);
7643 /* now some housekeeping stuff */
7644 if (aop) /* we had to allocate for this iCode */
7646 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7647 freeAsmop (NULL, aop, ic, TRUE);
7651 /* we did not allocate which means left
7652 already in a pointer register, then
7653 if size > 0 && this could be used again
7654 we have to point it back to where it
7656 if ((AOP_SIZE (result) > 1 &&
7657 !OP_SYMBOL (left)->remat &&
7658 (OP_SYMBOL (left)->liveTo > ic->seq ||
7662 int size = AOP_SIZE (result) - 1;
7664 emitcode ("dec", "%s", rname);
7669 freeAsmop (left, NULL, ic, TRUE);
7670 freeAsmop (result, NULL, ic, TRUE);
7671 if (pi) pi->generated = 1;
7675 /*--------------------------------------------------------------------*/
7676 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7677 /*--------------------------------------------------------------------*/
7679 loadDptrFromOperand (operand *op, bool loadBToo)
7681 if (AOP_TYPE (op) != AOP_STR)
7683 /* if this is remateriazable */
7684 if (AOP_TYPE (op) == AOP_IMMD)
7686 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7689 if (AOP(op)->aopu.aop_immd.from_cast_remat)
7690 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7693 wassertl(FALSE, "need pointerCode");
7694 emitcode ("", "; mov b,???");
7695 /* genPointerGet and genPointerSet originally did different
7696 ** things for this case. Both seem wrong.
7697 ** from genPointerGet:
7698 ** emitcode ("mov", "b,#%d", pointerCode (retype));
7699 ** from genPointerSet:
7700 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7705 else if (AOP_TYPE (op) == AOP_DPTR)
7709 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7710 emitcode ("push", "acc");
7711 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7712 emitcode ("push", "acc");
7713 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7714 emitcode ("pop", "dph");
7715 emitcode ("pop", "dpl");
7719 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7720 emitcode ("push", "acc");
7721 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7722 emitcode ("pop", "dpl");
7726 { /* we need to get it byte by byte */
7727 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7728 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7730 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7735 /*-----------------------------------------------------------------*/
7736 /* genFarPointerGet - gget value from far space */
7737 /*-----------------------------------------------------------------*/
7739 genFarPointerGet (operand * left,
7740 operand * result, iCode * ic, iCode * pi)
7743 sym_link *retype = getSpec (operandType (result));
7745 D(emitcode ("; genFarPointerGet",""));
7747 aopOp (left, ic, FALSE);
7748 loadDptrFromOperand (left, FALSE);
7750 /* so dptr now contains the address */
7751 aopOp (result, ic, FALSE);
7753 /* if bit then unpack */
7754 if (IS_BITVAR (retype))
7755 genUnpackBits (result, "dptr", FPOINTER);
7758 size = AOP_SIZE (result);
7763 emitcode ("movx", "a,@dptr");
7764 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7766 emitcode ("inc", "dptr");
7770 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7771 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7772 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7775 freeAsmop (left, NULL, ic, TRUE);
7776 freeAsmop (result, NULL, ic, TRUE);
7779 /*-----------------------------------------------------------------*/
7780 /* genCodePointerGet - gget value from code space */
7781 /*-----------------------------------------------------------------*/
7783 genCodePointerGet (operand * left,
7784 operand * result, iCode * ic, iCode *pi)
7787 sym_link *retype = getSpec (operandType (result));
7789 D(emitcode ("; genCodePointerGet",""));
7791 aopOp (left, ic, FALSE);
7792 loadDptrFromOperand (left, FALSE);
7794 /* so dptr now contains the address */
7795 aopOp (result, ic, FALSE);
7797 /* if bit then unpack */
7798 if (IS_BITVAR (retype))
7799 genUnpackBits (result, "dptr", CPOINTER);
7802 size = AOP_SIZE (result);
7809 emitcode ("clr", "a");
7810 emitcode ("movc", "a,@a+dptr");
7811 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7812 emitcode ("inc", "dptr");
7816 emitcode ("mov", "a,#0x%02x", offset);
7817 emitcode ("movc", "a,@a+dptr");
7818 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7823 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7824 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7825 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7828 freeAsmop (left, NULL, ic, TRUE);
7829 freeAsmop (result, NULL, ic, TRUE);
7832 /*-----------------------------------------------------------------*/
7833 /* genGenPointerGet - gget value from generic pointer space */
7834 /*-----------------------------------------------------------------*/
7836 genGenPointerGet (operand * left,
7837 operand * result, iCode * ic, iCode *pi)
7840 sym_link *retype = getSpec (operandType (result));
7842 D(emitcode ("; genGenPointerGet",""));
7844 aopOp (left, ic, FALSE);
7845 loadDptrFromOperand (left, TRUE);
7847 /* so dptr know contains the address */
7848 aopOp (result, ic, FALSE);
7850 /* if bit then unpack */
7851 if (IS_BITVAR (retype))
7852 genUnpackBits (result, "dptr", GPOINTER);
7855 size = AOP_SIZE (result);
7860 emitcode ("lcall", "__gptrget");
7861 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7863 emitcode ("inc", "dptr");
7867 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7868 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7869 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7872 freeAsmop (left, NULL, ic, TRUE);
7873 freeAsmop (result, NULL, ic, TRUE);
7876 /*-----------------------------------------------------------------*/
7877 /* genPointerGet - generate code for pointer get */
7878 /*-----------------------------------------------------------------*/
7880 genPointerGet (iCode * ic, iCode *pi)
7882 operand *left, *result;
7883 sym_link *type, *etype;
7886 D(emitcode ("; genPointerGet",""));
7888 left = IC_LEFT (ic);
7889 result = IC_RESULT (ic);
7891 /* depending on the type of pointer we need to
7892 move it to the correct pointer register */
7893 type = operandType (left);
7894 etype = getSpec (type);
7895 /* if left is of type of pointer then it is simple */
7896 if (IS_PTR (type) && !IS_FUNC (type->next))
7897 p_type = DCL_TYPE (type);
7900 /* we have to go by the storage class */
7901 p_type = PTR_TYPE (SPEC_OCLS (etype));
7904 /* special case when cast remat */
7905 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7906 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7907 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7908 type = operandType (left);
7909 p_type = DCL_TYPE (type);
7911 /* now that we have the pointer type we assign
7912 the pointer values */
7918 genNearPointerGet (left, result, ic, pi);
7922 genPagedPointerGet (left, result, ic, pi);
7926 genFarPointerGet (left, result, ic, pi);
7930 genCodePointerGet (left, result, ic, pi);
7934 genGenPointerGet (left, result, ic, pi);
7942 /*-----------------------------------------------------------------*/
7943 /* genPackBits - generates code for packed bit storage */
7944 /*-----------------------------------------------------------------*/
7946 genPackBits (sym_link * etype,
7948 char *rname, int p_type)
7950 int offset = 0; /* source byte offset */
7951 int rlen = 0; /* remaining bitfield length */
7952 int blen; /* bitfield length */
7953 int bstr; /* bitfield starting bit within byte */
7954 int litval; /* source literal value (if AOP_LIT) */
7955 unsigned char mask; /* bitmask within current byte */
7957 D(emitcode ("; genPackBits",""));
7959 blen = SPEC_BLEN (etype);
7960 bstr = SPEC_BSTR (etype);
7962 /* If the bitfield length is less than a byte */
7965 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7966 (unsigned char) (0xFF >> (8 - bstr)));
7968 if (AOP_TYPE (right) == AOP_LIT)
7970 /* Case with a bitfield length <8 and literal source
7972 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7974 litval &= (~mask) & 0xff;
7975 emitPtrByteGet (rname, p_type, FALSE);
7976 if ((mask|litval)!=0xff)
7977 emitcode ("anl","a,#0x%02x", mask);
7979 emitcode ("orl","a,#0x%02x", litval);
7983 if ((blen==1) && (p_type!=GPOINTER))
7985 /* Case with a bitfield length == 1 and no generic pointer
7987 if (AOP_TYPE (right) == AOP_CRY)
7988 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7991 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7992 emitcode ("rrc","a");
7994 emitPtrByteGet (rname, p_type, FALSE);
7995 emitcode ("mov","acc.%d,c",bstr);
7999 /* Case with a bitfield length < 8 and arbitrary source
8001 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8002 /* shift and mask source value */
8004 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8006 /* transfer A to B and get next byte */
8007 emitPtrByteGet (rname, p_type, TRUE);
8009 emitcode ("anl", "a,#0x%02x", mask);
8010 emitcode ("orl", "a,b");
8011 if (p_type == GPOINTER)
8012 emitcode ("pop", "b");
8016 emitPtrByteSet (rname, p_type, "a");
8020 /* Bit length is greater than 7 bits. In this case, copy */
8021 /* all except the partial byte at the end */
8022 for (rlen=blen;rlen>=8;rlen-=8)
8024 emitPtrByteSet (rname, p_type,
8025 aopGet (AOP (right), offset++, FALSE, TRUE) );
8027 emitcode ("inc", "%s", rname);
8030 /* If there was a partial byte at the end */
8033 mask = (((unsigned char) -1 << rlen) & 0xff);
8035 if (AOP_TYPE (right) == AOP_LIT)
8037 /* Case with partial byte and literal source
8039 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8040 litval >>= (blen-rlen);
8041 litval &= (~mask) & 0xff;
8042 emitPtrByteGet (rname, p_type, FALSE);
8043 if ((mask|litval)!=0xff)
8044 emitcode ("anl","a,#0x%02x", mask);
8046 emitcode ("orl","a,#0x%02x", litval);
8050 /* Case with partial byte and arbitrary source
8052 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8053 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8055 /* transfer A to B and get next byte */
8056 emitPtrByteGet (rname, p_type, TRUE);
8058 emitcode ("anl", "a,#0x%02x", mask);
8059 emitcode ("orl", "a,b");
8060 if (p_type == GPOINTER)
8061 emitcode ("pop", "b");
8063 emitPtrByteSet (rname, p_type, "a");
8069 /*-----------------------------------------------------------------*/
8070 /* genDataPointerSet - remat pointer to data space */
8071 /*-----------------------------------------------------------------*/
8073 genDataPointerSet (operand * right,
8077 int size, offset = 0;
8078 char *l, buffer[256];
8080 D(emitcode ("; genDataPointerSet",""));
8082 aopOp (right, ic, FALSE);
8084 l = aopGet (AOP (result), 0, FALSE, TRUE);
8085 size = AOP_SIZE (right);
8089 sprintf (buffer, "(%s + %d)", l + 1, offset);
8091 sprintf (buffer, "%s", l + 1);
8092 emitcode ("mov", "%s,%s", buffer,
8093 aopGet (AOP (right), offset++, FALSE, FALSE));
8096 freeAsmop (right, NULL, ic, TRUE);
8097 freeAsmop (result, NULL, ic, TRUE);
8100 /*-----------------------------------------------------------------*/
8101 /* genNearPointerSet - emitcode for near pointer put */
8102 /*-----------------------------------------------------------------*/
8104 genNearPointerSet (operand * right,
8112 sym_link *retype, *letype;
8113 sym_link *ptype = operandType (result);
8115 D(emitcode ("; genNearPointerSet",""));
8117 retype = getSpec (operandType (right));
8118 letype = getSpec (ptype);
8119 aopOp (result, ic, FALSE);
8121 /* if the result is rematerializable &
8122 in data space & not a bit variable */
8123 if (AOP_TYPE (result) == AOP_IMMD &&
8124 DCL_TYPE (ptype) == POINTER &&
8125 !IS_BITVAR (retype) &&
8126 !IS_BITVAR (letype))
8128 genDataPointerSet (right, result, ic);
8132 /* if the value is already in a pointer register
8133 then don't need anything more */
8134 if (!AOP_INPREG (AOP (result)))
8137 //AOP_TYPE (result) == AOP_STK
8141 // Aha, it is a pointer, just in disguise.
8142 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8145 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8146 __FILE__, __LINE__);
8151 emitcode ("mov", "a%s,%s", rname + 1, rname);
8152 rname++; // skip the '@'.
8157 /* otherwise get a free pointer register */
8159 preg = getFreePtr (ic, &aop, FALSE);
8160 emitcode ("mov", "%s,%s",
8162 aopGet (AOP (result), 0, FALSE, TRUE));
8168 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8171 aopOp (right, ic, FALSE);
8173 /* if bitfield then unpack the bits */
8174 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8175 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8178 /* we have can just get the values */
8179 int size = AOP_SIZE (right);
8184 l = aopGet (AOP (right), offset, FALSE, TRUE);
8188 emitcode ("mov", "@%s,a", rname);
8191 emitcode ("mov", "@%s,%s", rname, l);
8193 emitcode ("inc", "%s", rname);
8198 /* now some housekeeping stuff */
8199 if (aop) /* we had to allocate for this iCode */
8202 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8203 freeAsmop (NULL, aop, ic, TRUE);
8207 /* we did not allocate which means left
8208 already in a pointer register, then
8209 if size > 0 && this could be used again
8210 we have to point it back to where it
8212 if ((AOP_SIZE (right) > 1 &&
8213 !OP_SYMBOL (result)->remat &&
8214 (OP_SYMBOL (result)->liveTo > ic->seq ||
8218 int size = AOP_SIZE (right) - 1;
8220 emitcode ("dec", "%s", rname);
8225 if (pi) pi->generated = 1;
8226 freeAsmop (result, NULL, ic, TRUE);
8227 freeAsmop (right, NULL, ic, TRUE);
8230 /*-----------------------------------------------------------------*/
8231 /* genPagedPointerSet - emitcode for Paged pointer put */
8232 /*-----------------------------------------------------------------*/
8234 genPagedPointerSet (operand * right,
8242 sym_link *retype, *letype;
8244 D(emitcode ("; genPagedPointerSet",""));
8246 retype = getSpec (operandType (right));
8247 letype = getSpec (operandType (result));
8249 aopOp (result, ic, FALSE);
8251 /* if the value is already in a pointer register
8252 then don't need anything more */
8253 if (!AOP_INPREG (AOP (result)))
8255 /* otherwise get a free pointer register */
8257 preg = getFreePtr (ic, &aop, FALSE);
8258 emitcode ("mov", "%s,%s",
8260 aopGet (AOP (result), 0, FALSE, TRUE));
8264 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8266 aopOp (right, ic, FALSE);
8268 /* if bitfield then unpack the bits */
8269 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8270 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8273 /* we have can just get the values */
8274 int size = AOP_SIZE (right);
8279 l = aopGet (AOP (right), offset, FALSE, TRUE);
8282 emitcode ("movx", "@%s,a", rname);
8285 emitcode ("inc", "%s", rname);
8291 /* now some housekeeping stuff */
8292 if (aop) /* we had to allocate for this iCode */
8295 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8296 freeAsmop (NULL, aop, ic, TRUE);
8300 /* we did not allocate which means left
8301 already in a pointer register, then
8302 if size > 0 && this could be used again
8303 we have to point it back to where it
8305 if (AOP_SIZE (right) > 1 &&
8306 !OP_SYMBOL (result)->remat &&
8307 (OP_SYMBOL (result)->liveTo > ic->seq ||
8310 int size = AOP_SIZE (right) - 1;
8312 emitcode ("dec", "%s", rname);
8317 if (pi) pi->generated = 1;
8318 freeAsmop (result, NULL, ic, TRUE);
8319 freeAsmop (right, NULL, ic, TRUE);
8324 /*-----------------------------------------------------------------*/
8325 /* genFarPointerSet - set value from far space */
8326 /*-----------------------------------------------------------------*/
8328 genFarPointerSet (operand * right,
8329 operand * result, iCode * ic, iCode * pi)
8332 sym_link *retype = getSpec (operandType (right));
8333 sym_link *letype = getSpec (operandType (result));
8335 D(emitcode ("; genFarPointerSet",""));
8337 aopOp (result, ic, FALSE);
8338 loadDptrFromOperand (result, FALSE);
8340 /* so dptr know contains the address */
8341 aopOp (right, ic, FALSE);
8343 /* if bit then unpack */
8344 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8345 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8348 size = AOP_SIZE (right);
8353 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8355 emitcode ("movx", "@dptr,a");
8357 emitcode ("inc", "dptr");
8360 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8361 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8362 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8365 freeAsmop (result, NULL, ic, TRUE);
8366 freeAsmop (right, NULL, ic, TRUE);
8369 /*-----------------------------------------------------------------*/
8370 /* genGenPointerSet - set value from generic pointer space */
8371 /*-----------------------------------------------------------------*/
8373 genGenPointerSet (operand * right,
8374 operand * result, iCode * ic, iCode * pi)
8377 sym_link *retype = getSpec (operandType (right));
8378 sym_link *letype = getSpec (operandType (result));
8380 D(emitcode ("; genGenPointerSet",""));
8382 aopOp (result, ic, FALSE);
8383 loadDptrFromOperand (result, TRUE);
8385 /* so dptr know contains the address */
8386 aopOp (right, ic, FALSE);
8388 /* if bit then unpack */
8389 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8390 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8393 size = AOP_SIZE (right);
8398 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8400 emitcode ("lcall", "__gptrput");
8402 emitcode ("inc", "dptr");
8406 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8407 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8408 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8411 freeAsmop (result, NULL, ic, TRUE);
8412 freeAsmop (right, NULL, ic, TRUE);
8415 /*-----------------------------------------------------------------*/
8416 /* genPointerSet - stores the value into a pointer location */
8417 /*-----------------------------------------------------------------*/
8419 genPointerSet (iCode * ic, iCode *pi)
8421 operand *right, *result;
8422 sym_link *type, *etype;
8425 D(emitcode ("; genPointerSet",""));
8427 right = IC_RIGHT (ic);
8428 result = IC_RESULT (ic);
8430 /* depending on the type of pointer we need to
8431 move it to the correct pointer register */
8432 type = operandType (result);
8433 etype = getSpec (type);
8434 /* if left is of type of pointer then it is simple */
8435 if (IS_PTR (type) && !IS_FUNC (type->next))
8437 p_type = DCL_TYPE (type);
8441 /* we have to go by the storage class */
8442 p_type = PTR_TYPE (SPEC_OCLS (etype));
8445 /* special case when cast remat */
8446 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8447 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8448 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8449 type = operandType (result);
8450 p_type = DCL_TYPE (type);
8452 /* now that we have the pointer type we assign
8453 the pointer values */
8459 genNearPointerSet (right, result, ic, pi);
8463 genPagedPointerSet (right, result, ic, pi);
8467 genFarPointerSet (right, result, ic, pi);
8471 genGenPointerSet (right, result, ic, pi);
8475 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8476 "genPointerSet: illegal pointer type");
8481 /*-----------------------------------------------------------------*/
8482 /* genIfx - generate code for Ifx statement */
8483 /*-----------------------------------------------------------------*/
8485 genIfx (iCode * ic, iCode * popIc)
8487 operand *cond = IC_COND (ic);
8490 D(emitcode ("; genIfx",""));
8492 aopOp (cond, ic, FALSE);
8494 /* get the value into acc */
8495 if (AOP_TYPE (cond) != AOP_CRY)
8499 /* the result is now in the accumulator */
8500 freeAsmop (cond, NULL, ic, TRUE);
8502 /* if there was something to be popped then do it */
8506 /* if the condition is a bit variable */
8507 if (isbit && IS_ITEMP (cond) &&
8509 genIfxJump (ic, SPIL_LOC (cond)->rname);
8510 else if (isbit && !IS_ITEMP (cond))
8511 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8513 genIfxJump (ic, "a");
8518 /*-----------------------------------------------------------------*/
8519 /* genAddrOf - generates code for address of */
8520 /*-----------------------------------------------------------------*/
8522 genAddrOf (iCode * ic)
8524 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8527 D(emitcode ("; genAddrOf",""));
8529 aopOp (IC_RESULT (ic), ic, FALSE);
8531 /* if the operand is on the stack then we
8532 need to get the stack offset of this
8536 /* if it has an offset then we need to compute
8540 emitcode ("mov", "a,_bp");
8541 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8542 ((char) (sym->stack - _G.nRegsSaved)) :
8543 ((char) sym->stack)) & 0xff);
8544 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8548 /* we can just move _bp */
8549 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8551 /* fill the result with zero */
8552 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8557 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8563 /* object not on stack then we need the name */
8564 size = AOP_SIZE (IC_RESULT (ic));
8569 char s[SDCC_NAME_MAX];
8571 sprintf (s, "#(%s >> %d)",
8575 sprintf (s, "#%s", sym->rname);
8576 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8580 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8584 /*-----------------------------------------------------------------*/
8585 /* genFarFarAssign - assignment when both are in far space */
8586 /*-----------------------------------------------------------------*/
8588 genFarFarAssign (operand * result, operand * right, iCode * ic)
8590 int size = AOP_SIZE (right);
8594 D(emitcode ("; genFarFarAssign",""));
8596 /* first push the right side on to the stack */
8599 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8601 emitcode ("push", "acc");
8604 freeAsmop (right, NULL, ic, FALSE);
8605 /* now assign DPTR to result */
8606 aopOp (result, ic, FALSE);
8607 size = AOP_SIZE (result);
8610 emitcode ("pop", "acc");
8611 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8613 freeAsmop (result, NULL, ic, FALSE);
8617 /*-----------------------------------------------------------------*/
8618 /* genAssign - generate code for assignment */
8619 /*-----------------------------------------------------------------*/
8621 genAssign (iCode * ic)
8623 operand *result, *right;
8625 unsigned long lit = 0L;
8627 D(emitcode("; genAssign",""));
8629 result = IC_RESULT (ic);
8630 right = IC_RIGHT (ic);
8632 /* if they are the same */
8633 if (operandsEqu (result, right) &&
8634 !isOperandVolatile (result, FALSE) &&
8635 !isOperandVolatile (right, FALSE))
8638 aopOp (right, ic, FALSE);
8640 /* special case both in far space */
8641 if (AOP_TYPE (right) == AOP_DPTR &&
8642 IS_TRUE_SYMOP (result) &&
8643 isOperandInFarSpace (result))
8646 genFarFarAssign (result, right, ic);
8650 aopOp (result, ic, TRUE);
8652 /* if they are the same registers */
8653 if (sameRegs (AOP (right), AOP (result)) &&
8654 !isOperandVolatile (result, FALSE) &&
8655 !isOperandVolatile (right, FALSE))
8658 /* if the result is a bit */
8659 if (AOP_TYPE (result) == AOP_CRY)
8662 /* if the right size is a literal then
8663 we know what the value is */
8664 if (AOP_TYPE (right) == AOP_LIT)
8666 if (((int) operandLitValue (right)))
8667 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8669 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8673 /* the right is also a bit variable */
8674 if (AOP_TYPE (right) == AOP_CRY)
8676 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8677 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8683 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8687 /* bit variables done */
8689 size = AOP_SIZE (result);
8691 if (AOP_TYPE (right) == AOP_LIT)
8692 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8694 (AOP_TYPE (result) != AOP_REG) &&
8695 (AOP_TYPE (right) == AOP_LIT) &&
8696 !IS_FLOAT (operandType (right)) &&
8699 emitcode ("clr", "a");
8702 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8703 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8705 aopPut (AOP (result),
8706 aopGet (AOP (right), size, FALSE, FALSE),
8708 isOperandVolatile (result, FALSE));
8715 aopPut (AOP (result),
8716 aopGet (AOP (right), offset, FALSE, FALSE),
8718 isOperandVolatile (result, FALSE));
8724 freeAsmop (right, NULL, ic, TRUE);
8725 freeAsmop (result, NULL, ic, TRUE);
8728 /*-----------------------------------------------------------------*/
8729 /* genJumpTab - genrates code for jump table */
8730 /*-----------------------------------------------------------------*/
8732 genJumpTab (iCode * ic)
8737 D(emitcode ("; genJumpTab",""));
8739 aopOp (IC_JTCOND (ic), ic, FALSE);
8740 /* get the condition into accumulator */
8741 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8743 /* multiply by three */
8744 emitcode ("add", "a,acc");
8745 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8746 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8748 jtab = newiTempLabel (NULL);
8749 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8750 emitcode ("jmp", "@a+dptr");
8751 emitcode ("", "%05d$:", jtab->key + 100);
8752 /* now generate the jump labels */
8753 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8754 jtab = setNextItem (IC_JTLABELS (ic)))
8755 emitcode ("ljmp", "%05d$", jtab->key + 100);
8759 /*-----------------------------------------------------------------*/
8760 /* genCast - gen code for casting */
8761 /*-----------------------------------------------------------------*/
8763 genCast (iCode * ic)
8765 operand *result = IC_RESULT (ic);
8766 sym_link *ctype = operandType (IC_LEFT (ic));
8767 sym_link *rtype = operandType (IC_RIGHT (ic));
8768 operand *right = IC_RIGHT (ic);
8771 D(emitcode("; genCast",""));
8773 /* if they are equivalent then do nothing */
8774 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8777 aopOp (right, ic, FALSE);
8778 aopOp (result, ic, FALSE);
8780 /* if the result is a bit (and not a bitfield) */
8781 // if (AOP_TYPE (result) == AOP_CRY)
8782 if (IS_BITVAR (OP_SYMBOL (result)->type)
8783 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8785 /* if the right size is a literal then
8786 we know what the value is */
8787 if (AOP_TYPE (right) == AOP_LIT)
8789 if (((int) operandLitValue (right)))
8790 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8792 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8797 /* the right is also a bit variable */
8798 if (AOP_TYPE (right) == AOP_CRY)
8800 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8801 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8807 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8812 /* if they are the same size : or less */
8813 if (AOP_SIZE (result) <= AOP_SIZE (right))
8816 /* if they are in the same place */
8817 if (sameRegs (AOP (right), AOP (result)))
8820 /* if they in different places then copy */
8821 size = AOP_SIZE (result);
8825 aopPut (AOP (result),
8826 aopGet (AOP (right), offset, FALSE, FALSE),
8828 isOperandVolatile (result, FALSE));
8835 /* if the result is of type pointer */
8840 sym_link *type = operandType (right);
8841 sym_link *etype = getSpec (type);
8843 /* pointer to generic pointer */
8844 if (IS_GENPTR (ctype))
8847 p_type = DCL_TYPE (type);
8850 if (SPEC_SCLS(etype)==S_REGISTER) {
8851 // let's assume it is a generic pointer
8854 /* we have to go by the storage class */
8855 p_type = PTR_TYPE (SPEC_OCLS (etype));
8859 /* the first two bytes are known */
8860 size = GPTRSIZE - 1;
8864 aopPut (AOP (result),
8865 aopGet (AOP (right), offset, FALSE, FALSE),
8867 isOperandVolatile (result, FALSE));
8870 /* the last byte depending on type */
8872 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8877 // pointerTypeToGPByte will have bitched.
8881 sprintf(gpValStr, "#0x%d", gpVal);
8882 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8887 /* just copy the pointers */
8888 size = AOP_SIZE (result);
8892 aopPut (AOP (result),
8893 aopGet (AOP (right), offset, FALSE, FALSE),
8895 isOperandVolatile (result, FALSE));
8901 /* so we now know that the size of destination is greater
8902 than the size of the source */
8903 /* we move to result for the size of source */
8904 size = AOP_SIZE (right);
8908 aopPut (AOP (result),
8909 aopGet (AOP (right), offset, FALSE, FALSE),
8911 isOperandVolatile (result, FALSE));
8915 /* now depending on the sign of the source && destination */
8916 size = AOP_SIZE (result) - AOP_SIZE (right);
8917 /* if unsigned or not an integral type */
8918 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8921 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8925 /* we need to extend the sign :{ */
8926 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8929 emitcode ("rlc", "a");
8930 emitcode ("subb", "a,acc");
8932 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8935 /* we are done hurray !!!! */
8938 freeAsmop (right, NULL, ic, TRUE);
8939 freeAsmop (result, NULL, ic, TRUE);
8943 /*-----------------------------------------------------------------*/
8944 /* genDjnz - generate decrement & jump if not zero instrucion */
8945 /*-----------------------------------------------------------------*/
8947 genDjnz (iCode * ic, iCode * ifx)
8953 D(emitcode ("; genDjnz",""));
8955 /* if the if condition has a false label
8956 then we cannot save */
8960 /* if the minus is not of the form
8962 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8963 !IS_OP_LITERAL (IC_RIGHT (ic)))
8966 if (operandLitValue (IC_RIGHT (ic)) != 1)
8969 /* if the size of this greater than one then no
8971 if (getSize (operandType (IC_RESULT (ic))) > 1)
8974 /* otherwise we can save BIG */
8975 lbl = newiTempLabel (NULL);
8976 lbl1 = newiTempLabel (NULL);
8978 aopOp (IC_RESULT (ic), ic, FALSE);
8980 if (AOP_NEEDSACC(IC_RESULT(ic)))
8982 /* If the result is accessed indirectly via
8983 * the accumulator, we must explicitly write
8984 * it back after the decrement.
8986 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8988 if (strcmp(rByte, "a"))
8990 /* Something is hopelessly wrong */
8991 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8992 __FILE__, __LINE__);
8993 /* We can just give up; the generated code will be inefficient,
8996 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8999 emitcode ("dec", "%s", rByte);
9000 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9001 emitcode ("jnz", "%05d$", lbl->key + 100);
9003 else if (IS_AOP_PREG (IC_RESULT (ic)))
9005 emitcode ("dec", "%s",
9006 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9007 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9008 emitcode ("jnz", "%05d$", lbl->key + 100);
9012 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9015 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9016 emitcode ("", "%05d$:", lbl->key + 100);
9017 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9018 emitcode ("", "%05d$:", lbl1->key + 100);
9020 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9025 /*-----------------------------------------------------------------*/
9026 /* genReceive - generate code for a receive iCode */
9027 /*-----------------------------------------------------------------*/
9029 genReceive (iCode * ic)
9031 int size = getSize (operandType (IC_RESULT (ic)));
9033 D(emitcode ("; genReceive",""));
9035 if (ic->argreg == 1) { /* first parameter */
9036 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9037 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9038 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9040 offset = fReturnSizeMCS51 - size;
9042 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9043 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9046 aopOp (IC_RESULT (ic), ic, FALSE);
9047 size = AOP_SIZE (IC_RESULT (ic));
9050 emitcode ("pop", "acc");
9051 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9056 aopOp (IC_RESULT (ic), ic, FALSE);
9058 assignResultValue (IC_RESULT (ic));
9060 } else { /* second receive onwards */
9062 aopOp (IC_RESULT (ic), ic, FALSE);
9063 rb1off = ic->argreg;
9065 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9068 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9071 /*-----------------------------------------------------------------*/
9072 /* genDummyRead - generate code for dummy read of volatiles */
9073 /*-----------------------------------------------------------------*/
9075 genDummyRead (iCode * ic)
9080 D(emitcode("; genDummyRead",""));
9082 right = IC_RIGHT (ic);
9084 aopOp (right, ic, FALSE);
9086 /* if the result is a bit */
9087 if (AOP_TYPE (right) == AOP_CRY)
9089 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9093 /* bit variables done */
9095 size = AOP_SIZE (right);
9099 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
9104 freeAsmop (right, NULL, ic, TRUE);
9107 /*-----------------------------------------------------------------*/
9108 /* genCritical - generate code for start of a critical sequence */
9109 /*-----------------------------------------------------------------*/
9111 genCritical (iCode *ic)
9113 symbol *tlbl = newiTempLabel (NULL);
9115 D(emitcode("; genCritical",""));
9118 aopOp (IC_RESULT (ic), ic, TRUE);
9120 emitcode ("setb", "c");
9121 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9122 emitcode ("clr", "c");
9123 emitcode ("", "%05d$:", (tlbl->key + 100));
9126 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9128 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9131 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9134 /*-----------------------------------------------------------------*/
9135 /* genEndCritical - generate code for end of a critical sequence */
9136 /*-----------------------------------------------------------------*/
9138 genEndCritical (iCode *ic)
9140 D(emitcode("; genEndCritical",""));
9144 aopOp (IC_RIGHT (ic), ic, FALSE);
9145 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9147 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9148 emitcode ("mov", "ea,c");
9152 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9153 emitcode ("rrc", "a");
9154 emitcode ("mov", "ea,c");
9156 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9160 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9161 emitcode ("mov", "ea,c");
9166 /*-----------------------------------------------------------------*/
9167 /* gen51Code - generate code for 8051 based controllers */
9168 /*-----------------------------------------------------------------*/
9170 gen51Code (iCode * lic)
9175 lineHead = lineCurr = NULL;
9177 /* print the allocation information */
9178 if (allocInfo && currFunc)
9179 printAllocInfo (currFunc, codeOutFile);
9180 /* if debug information required */
9181 if (options.debug && currFunc)
9183 debugFile->writeFunction(currFunc);
9185 if (IS_STATIC (currFunc->etype))
9186 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9188 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9191 /* stack pointer name */
9192 if (options.useXstack)
9198 for (ic = lic; ic; ic = ic->next)
9200 _G.current_iCode = ic;
9202 if (ic->lineno && cln != ic->lineno)
9207 emitcode ("", "C$%s$%d$%d$%d ==.",
9208 FileBaseName (ic->filename), ic->lineno,
9209 ic->level, ic->block);
9212 if (!options.noCcodeInAsm) {
9213 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9214 printCLine(ic->filename, ic->lineno));
9218 if (options.iCodeInAsm) {
9222 for (i=0; i<8; i++) {
9223 sprintf (®sInUse[i],
9224 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9227 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9229 /* if the result is marked as
9230 spilt and rematerializable or code for
9231 this has already been generated then
9233 if (resultRemat (ic) || ic->generated)
9236 /* depending on the operation */
9256 /* IPOP happens only when trying to restore a
9257 spilt live range, if there is an ifx statement
9258 following this pop then the if statement might
9259 be using some of the registers being popped which
9260 would destory the contents of the register so
9261 we need to check for this condition and handle it */
9263 ic->next->op == IFX &&
9264 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9265 genIfx (ic->next, ic);
9283 genEndFunction (ic);
9303 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9320 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9324 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9331 /* note these two are xlated by algebraic equivalence
9332 during parsing SDCC.y */
9333 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9334 "got '>=' or '<=' shouldn't have come here");
9338 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9350 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9354 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9358 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9385 case GET_VALUE_AT_ADDRESS:
9386 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9390 if (POINTER_SET (ic))
9391 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9417 addSet (&_G.sendSet, ic);
9420 case DUMMY_READ_VOLATILE:
9429 genEndCritical (ic);
9441 _G.current_iCode = NULL;
9443 /* now we are ready to call the
9444 peep hole optimizer */
9445 if (!options.nopeep)
9446 peepHole (&lineHead);
9448 /* now do the actual printing */
9449 printLine (lineHead, codeOutFile);