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;
3200 /* special cases :- */
3202 D(emitcode ("; genPlus",""));
3204 aopOp (IC_LEFT (ic), ic, FALSE);
3205 aopOp (IC_RIGHT (ic), ic, FALSE);
3206 aopOp (IC_RESULT (ic), ic, TRUE);
3208 /* if literal, literal on the right or
3209 if left requires ACC or right is already
3211 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3212 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3213 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3215 operand *t = IC_RIGHT (ic);
3216 IC_RIGHT (ic) = IC_LEFT (ic);
3220 /* if both left & right are in bit
3222 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3223 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3229 /* if left in bit space & right literal */
3230 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3231 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3233 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3234 /* if result in bit space */
3235 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3237 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3238 emitcode ("cpl", "c");
3239 outBitC (IC_RESULT (ic));
3243 size = getDataSize (IC_RESULT (ic));
3246 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3247 emitcode ("addc", "a,#00");
3248 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3254 /* if I can do an increment instead
3255 of add then GOOD for ME */
3256 if (genPlusIncr (ic) == TRUE)
3259 size = getDataSize (IC_RESULT (ic));
3260 leftOp = AOP(IC_LEFT(ic));
3261 rightOp = AOP(IC_RIGHT(ic));
3264 /* if this is an add for an array access
3265 at a 256 byte boundary */
3267 && AOP_TYPE (op) == AOP_IMMD
3269 && IS_SPEC (OP_SYM_ETYPE (op))
3270 && SPEC_ABSA (OP_SYM_ETYPE (op))
3271 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3274 D(emitcode ("; genPlus aligned array",""));
3275 aopPut (AOP (IC_RESULT (ic)),
3276 aopGet (rightOp, 0, FALSE, FALSE),
3278 isOperandVolatile (IC_RESULT (ic), FALSE));
3280 if( 1 == getDataSize (IC_RIGHT (ic)) )
3282 aopPut (AOP (IC_RESULT (ic)),
3283 aopGet (leftOp, 1, FALSE, FALSE),
3285 isOperandVolatile (IC_RESULT (ic), FALSE));
3289 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3290 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3291 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3296 /* if the lower bytes of a literal are zero skip the addition */
3297 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3299 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3300 (skip_bytes+1 < size))
3305 D(emitcode ("; genPlus shortcut",""));
3310 if( offset >= skip_bytes )
3312 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3314 emitcode("mov", "b,a");
3315 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3316 emitcode("xch", "a,b");
3317 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3318 emitcode (add, "a,b");
3320 else if (aopGetUsesAcc (leftOp, offset))
3322 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3323 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3327 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3328 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3330 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3331 add = "addc"; /* further adds must propagate carry */
3335 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3336 isOperandVolatile (IC_RESULT (ic), FALSE))
3339 aopPut (AOP (IC_RESULT (ic)),
3340 aopGet (leftOp, offset, FALSE, FALSE),
3342 isOperandVolatile (IC_RESULT (ic), FALSE));
3348 adjustArithmeticResult (ic);
3351 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3352 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3353 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3356 /*-----------------------------------------------------------------*/
3357 /* genMinusDec :- does subtraction with deccrement if possible */
3358 /*-----------------------------------------------------------------*/
3360 genMinusDec (iCode * ic)
3362 unsigned int icount;
3363 unsigned int size = getDataSize (IC_RESULT (ic));
3365 /* will try to generate an increment */
3366 /* if the right side is not a literal
3368 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3371 /* if the literal value of the right hand side
3372 is greater than 4 then it is not worth it */
3373 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3376 D(emitcode ("; genMinusDec",""));
3378 /* if decrement >=16 bits in register or direct space */
3379 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3380 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3388 /* If the next instruction is a goto and the goto target
3389 * is <= 10 instructions previous to this, we can generate
3390 * jumps straight to that target.
3392 if (ic->next && ic->next->op == GOTO
3393 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3394 && labelRange <= 10)
3396 emitcode (";", "tail decrement optimized");
3397 tlbl = IC_LABEL (ic->next);
3402 tlbl = newiTempLabel (NULL);
3406 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3407 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3408 IS_AOP_PREG (IC_RESULT (ic)))
3409 emitcode ("cjne", "%s,#0xff,%05d$"
3410 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3414 emitcode ("mov", "a,#0xff");
3415 emitcode ("cjne", "a,%s,%05d$"
3416 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3419 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3422 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3423 IS_AOP_PREG (IC_RESULT (ic)))
3424 emitcode ("cjne", "%s,#0xff,%05d$"
3425 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3429 emitcode ("cjne", "a,%s,%05d$"
3430 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3433 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3437 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3438 IS_AOP_PREG (IC_RESULT (ic)))
3439 emitcode ("cjne", "%s,#0xff,%05d$"
3440 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3444 emitcode ("cjne", "a,%s,%05d$"
3445 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3448 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3452 emitcode ("", "%05d$:", tlbl->key + 100);
3457 /* if the sizes are greater than 1 then we cannot */
3458 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3459 AOP_SIZE (IC_LEFT (ic)) > 1)
3462 /* we can if the aops of the left & result match or
3463 if they are in registers and the registers are the
3465 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3469 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3477 /*-----------------------------------------------------------------*/
3478 /* addSign - complete with sign */
3479 /*-----------------------------------------------------------------*/
3481 addSign (operand * result, int offset, int sign)
3483 int size = (getDataSize (result) - offset);
3488 emitcode ("rlc", "a");
3489 emitcode ("subb", "a,acc");
3491 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3495 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3499 /*-----------------------------------------------------------------*/
3500 /* genMinusBits - generates code for subtraction of two bits */
3501 /*-----------------------------------------------------------------*/
3503 genMinusBits (iCode * ic)
3505 symbol *lbl = newiTempLabel (NULL);
3507 D(emitcode ("; genMinusBits",""));
3509 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3511 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3512 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3513 emitcode ("cpl", "c");
3514 emitcode ("", "%05d$:", (lbl->key + 100));
3515 outBitC (IC_RESULT (ic));
3519 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3520 emitcode ("subb", "a,acc");
3521 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3522 emitcode ("inc", "a");
3523 emitcode ("", "%05d$:", (lbl->key + 100));
3524 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3525 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3529 /*-----------------------------------------------------------------*/
3530 /* genMinus - generates code for subtraction */
3531 /*-----------------------------------------------------------------*/
3533 genMinus (iCode * ic)
3535 int size, offset = 0;
3537 D(emitcode ("; genMinus",""));
3539 aopOp (IC_LEFT (ic), ic, FALSE);
3540 aopOp (IC_RIGHT (ic), ic, FALSE);
3541 aopOp (IC_RESULT (ic), ic, TRUE);
3543 /* special cases :- */
3544 /* if both left & right are in bit space */
3545 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3546 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3552 /* if I can do an decrement instead
3553 of subtract then GOOD for ME */
3554 if (genMinusDec (ic) == TRUE)
3557 size = getDataSize (IC_RESULT (ic));
3559 /* if literal, add a,#-lit, else normal subb */
3560 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3562 unsigned long lit = 0L;
3564 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3569 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3570 /* first add without previous c */
3572 if (!size && lit== (unsigned long) -1) {
3573 emitcode ("dec", "a");
3575 emitcode ("add", "a,#0x%02x",
3576 (unsigned int) (lit & 0x0FFL));
3579 emitcode ("addc", "a,#0x%02x",
3580 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3582 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3587 asmop *leftOp, *rightOp;
3589 leftOp = AOP(IC_LEFT(ic));
3590 rightOp = AOP(IC_RIGHT(ic));
3594 if (aopGetUsesAcc(rightOp, offset)) {
3595 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3596 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3598 emitcode( "setb", "c");
3600 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3601 emitcode("cpl", "a");
3603 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3606 emitcode ("subb", "a,%s",
3607 aopGet(rightOp, offset, FALSE, TRUE));
3610 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3615 adjustArithmeticResult (ic);
3618 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3619 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3620 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3624 /*-----------------------------------------------------------------*/
3625 /* genMultbits :- multiplication of bits */
3626 /*-----------------------------------------------------------------*/
3628 genMultbits (operand * left,
3632 D(emitcode ("; genMultbits",""));
3634 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3635 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3640 /*-----------------------------------------------------------------*/
3641 /* genMultOneByte : 8*8=8/16 bit multiplication */
3642 /*-----------------------------------------------------------------*/
3644 genMultOneByte (operand * left,
3648 sym_link *opetype = operandType (result);
3650 int size=AOP_SIZE(result);
3652 D(emitcode ("; genMultOneByte",""));
3654 if (size<1 || size>2) {
3655 // this should never happen
3656 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3657 AOP_SIZE(result), __FILE__, lineno);
3661 /* (if two literals: the value is computed before) */
3662 /* if one literal, literal on the right */
3663 if (AOP_TYPE (left) == AOP_LIT)
3668 //emitcode (";", "swapped left and right");
3671 if (SPEC_USIGN(opetype)
3672 // ignore the sign of left and right, what else can we do?
3673 || (SPEC_USIGN(operandType(left)) &&
3674 SPEC_USIGN(operandType(right)))) {
3675 // just an unsigned 8*8=8/16 multiply
3676 //emitcode (";","unsigned");
3677 // TODO: check for accumulator clash between left & right aops?
3679 if( AOP_TYPE(right)==AOP_LIT ){
3680 // moving to accumulator first helps peepholes
3681 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3682 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3684 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3685 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3688 emitcode ("mul", "ab");
3689 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3691 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3696 // we have to do a signed multiply
3698 //emitcode (";", "signed");
3699 emitcode ("clr", "F0"); // reset sign flag
3700 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3702 lbl=newiTempLabel(NULL);
3703 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3704 // left side is negative, 8-bit two's complement, this fails for -128
3705 emitcode ("setb", "F0"); // set sign flag
3706 emitcode ("cpl", "a");
3707 emitcode ("inc", "a");
3709 emitcode ("", "%05d$:", lbl->key+100);
3712 if (AOP_TYPE(right)==AOP_LIT) {
3713 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3714 /* AND literal negative */
3716 emitcode ("cpl", "F0"); // complement sign flag
3717 emitcode ("mov", "b,#0x%02x", -val);
3719 emitcode ("mov", "b,#0x%02x", val);
3722 lbl=newiTempLabel(NULL);
3723 emitcode ("mov", "b,a");
3724 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3725 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3726 // right side is negative, 8-bit two's complement
3727 emitcode ("cpl", "F0"); // complement sign flag
3728 emitcode ("cpl", "a");
3729 emitcode ("inc", "a");
3730 emitcode ("", "%05d$:", lbl->key+100);
3732 emitcode ("mul", "ab");
3734 lbl=newiTempLabel(NULL);
3735 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3736 // only ONE op was negative, we have to do a 8/16-bit two's complement
3737 emitcode ("cpl", "a"); // lsb
3739 emitcode ("inc", "a");
3741 emitcode ("add", "a,#1");
3742 emitcode ("xch", "a,b");
3743 emitcode ("cpl", "a"); // msb
3744 emitcode ("addc", "a,#0");
3745 emitcode ("xch", "a,b");
3748 emitcode ("", "%05d$:", lbl->key+100);
3749 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3751 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3755 /*-----------------------------------------------------------------*/
3756 /* genMult - generates code for multiplication */
3757 /*-----------------------------------------------------------------*/
3759 genMult (iCode * ic)
3761 operand *left = IC_LEFT (ic);
3762 operand *right = IC_RIGHT (ic);
3763 operand *result = IC_RESULT (ic);
3765 D(emitcode ("; genMult",""));
3767 /* assign the amsops */
3768 aopOp (left, ic, FALSE);
3769 aopOp (right, ic, FALSE);
3770 aopOp (result, ic, TRUE);
3772 /* special cases first */
3774 if (AOP_TYPE (left) == AOP_CRY &&
3775 AOP_TYPE (right) == AOP_CRY)
3777 genMultbits (left, right, result);
3781 /* if both are of size == 1 */
3782 #if 0 // one of them can be a sloc shared with the result
3783 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3785 if (getSize(operandType(left)) == 1 &&
3786 getSize(operandType(right)) == 1)
3789 genMultOneByte (left, right, result);
3793 /* should have been converted to function call */
3794 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3795 getSize(OP_SYMBOL(right)->type));
3799 freeAsmop (result, NULL, ic, TRUE);
3800 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3801 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3804 /*-----------------------------------------------------------------*/
3805 /* genDivbits :- division of bits */
3806 /*-----------------------------------------------------------------*/
3808 genDivbits (operand * left,
3815 D(emitcode ("; genDivbits",""));
3817 /* the result must be bit */
3818 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3819 l = aopGet (AOP (left), 0, FALSE, FALSE);
3823 emitcode ("div", "ab");
3824 emitcode ("rrc", "a");
3825 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3828 /*-----------------------------------------------------------------*/
3829 /* genDivOneByte : 8 bit division */
3830 /*-----------------------------------------------------------------*/
3832 genDivOneByte (operand * left,
3836 sym_link *opetype = operandType (result);
3841 D(emitcode ("; genDivOneByte",""));
3843 size = AOP_SIZE (result) - 1;
3845 /* signed or unsigned */
3846 if (SPEC_USIGN (opetype))
3848 /* unsigned is easy */
3849 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3850 l = aopGet (AOP (left), 0, FALSE, FALSE);
3852 emitcode ("div", "ab");
3853 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3855 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3859 /* signed is a little bit more difficult */
3861 /* save the signs of the operands */
3862 l = aopGet (AOP (left), 0, FALSE, FALSE);
3864 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3865 emitcode ("push", "acc"); /* save it on the stack */
3867 /* now sign adjust for both left & right */
3868 l = aopGet (AOP (right), 0, FALSE, FALSE);
3870 lbl = newiTempLabel (NULL);
3871 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3872 emitcode ("cpl", "a");
3873 emitcode ("inc", "a");
3874 emitcode ("", "%05d$:", (lbl->key + 100));
3875 emitcode ("mov", "b,a");
3877 /* sign adjust left side */
3878 l = aopGet (AOP (left), 0, FALSE, FALSE);
3881 lbl = newiTempLabel (NULL);
3882 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3883 emitcode ("cpl", "a");
3884 emitcode ("inc", "a");
3885 emitcode ("", "%05d$:", (lbl->key + 100));
3887 /* now the division */
3888 emitcode ("div", "ab");
3889 /* we are interested in the lower order
3891 emitcode ("mov", "b,a");
3892 lbl = newiTempLabel (NULL);
3893 emitcode ("pop", "acc");
3894 /* if there was an over flow we don't
3895 adjust the sign of the result */
3896 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3897 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3899 emitcode ("clr", "a");
3900 emitcode ("subb", "a,b");
3901 emitcode ("mov", "b,a");
3902 emitcode ("", "%05d$:", (lbl->key + 100));
3904 /* now we are done */
3905 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3908 emitcode ("mov", "c,b.7");
3909 emitcode ("subb", "a,acc");
3912 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3916 /*-----------------------------------------------------------------*/
3917 /* genDiv - generates code for division */
3918 /*-----------------------------------------------------------------*/
3922 operand *left = IC_LEFT (ic);
3923 operand *right = IC_RIGHT (ic);
3924 operand *result = IC_RESULT (ic);
3926 D(emitcode ("; genDiv",""));
3928 /* assign the amsops */
3929 aopOp (left, ic, FALSE);
3930 aopOp (right, ic, FALSE);
3931 aopOp (result, ic, TRUE);
3933 /* special cases first */
3935 if (AOP_TYPE (left) == AOP_CRY &&
3936 AOP_TYPE (right) == AOP_CRY)
3938 genDivbits (left, right, result);
3942 /* if both are of size == 1 */
3943 if (AOP_SIZE (left) == 1 &&
3944 AOP_SIZE (right) == 1)
3946 genDivOneByte (left, right, result);
3950 /* should have been converted to function call */
3953 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3954 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3955 freeAsmop (result, NULL, ic, TRUE);
3958 /*-----------------------------------------------------------------*/
3959 /* genModbits :- modulus of bits */
3960 /*-----------------------------------------------------------------*/
3962 genModbits (operand * left,
3969 D(emitcode ("; genModbits",""));
3971 /* the result must be bit */
3972 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3973 l = aopGet (AOP (left), 0, FALSE, FALSE);
3977 emitcode ("div", "ab");
3978 emitcode ("mov", "a,b");
3979 emitcode ("rrc", "a");
3980 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3983 /*-----------------------------------------------------------------*/
3984 /* genModOneByte : 8 bit modulus */
3985 /*-----------------------------------------------------------------*/
3987 genModOneByte (operand * left,
3991 sym_link *opetype = operandType (result);
3995 D(emitcode ("; genModOneByte",""));
3997 /* signed or unsigned */
3998 if (SPEC_USIGN (opetype))
4000 /* unsigned is easy */
4001 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4002 l = aopGet (AOP (left), 0, FALSE, FALSE);
4004 emitcode ("div", "ab");
4005 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4009 /* signed is a little bit more difficult */
4011 /* save the signs of the operands */
4012 l = aopGet (AOP (left), 0, FALSE, FALSE);
4015 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4016 emitcode ("push", "acc"); /* save it on the stack */
4018 /* now sign adjust for both left & right */
4019 l = aopGet (AOP (right), 0, FALSE, FALSE);
4022 lbl = newiTempLabel (NULL);
4023 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4024 emitcode ("cpl", "a");
4025 emitcode ("inc", "a");
4026 emitcode ("", "%05d$:", (lbl->key + 100));
4027 emitcode ("mov", "b,a");
4029 /* sign adjust left side */
4030 l = aopGet (AOP (left), 0, FALSE, FALSE);
4033 lbl = newiTempLabel (NULL);
4034 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4035 emitcode ("cpl", "a");
4036 emitcode ("inc", "a");
4037 emitcode ("", "%05d$:", (lbl->key + 100));
4039 /* now the multiplication */
4040 emitcode ("div", "ab");
4041 /* we are interested in the lower order
4043 lbl = newiTempLabel (NULL);
4044 emitcode ("pop", "acc");
4045 /* if there was an over flow we don't
4046 adjust the sign of the result */
4047 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4048 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4050 emitcode ("clr", "a");
4051 emitcode ("subb", "a,b");
4052 emitcode ("mov", "b,a");
4053 emitcode ("", "%05d$:", (lbl->key + 100));
4055 /* now we are done */
4056 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4060 /*-----------------------------------------------------------------*/
4061 /* genMod - generates code for division */
4062 /*-----------------------------------------------------------------*/
4066 operand *left = IC_LEFT (ic);
4067 operand *right = IC_RIGHT (ic);
4068 operand *result = IC_RESULT (ic);
4070 D(emitcode ("; genMod",""));
4072 /* assign the amsops */
4073 aopOp (left, ic, FALSE);
4074 aopOp (right, ic, FALSE);
4075 aopOp (result, ic, TRUE);
4077 /* special cases first */
4079 if (AOP_TYPE (left) == AOP_CRY &&
4080 AOP_TYPE (right) == AOP_CRY)
4082 genModbits (left, right, result);
4086 /* if both are of size == 1 */
4087 if (AOP_SIZE (left) == 1 &&
4088 AOP_SIZE (right) == 1)
4090 genModOneByte (left, right, result);
4094 /* should have been converted to function call */
4098 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4099 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4100 freeAsmop (result, NULL, ic, TRUE);
4103 /*-----------------------------------------------------------------*/
4104 /* genIfxJump :- will create a jump depending on the ifx */
4105 /*-----------------------------------------------------------------*/
4107 genIfxJump (iCode * ic, char *jval)
4110 symbol *tlbl = newiTempLabel (NULL);
4113 D(emitcode ("; genIfxJump",""));
4115 /* if true label then we jump if condition
4119 jlbl = IC_TRUE (ic);
4120 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4121 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4125 /* false label is present */
4126 jlbl = IC_FALSE (ic);
4127 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4128 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4130 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4131 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4133 emitcode (inst, "%05d$", tlbl->key + 100);
4134 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4135 emitcode ("", "%05d$:", tlbl->key + 100);
4137 /* mark the icode as generated */
4141 /*-----------------------------------------------------------------*/
4142 /* genCmp :- greater or less than comparison */
4143 /*-----------------------------------------------------------------*/
4145 genCmp (operand * left, operand * right,
4146 operand * result, iCode * ifx, int sign, iCode *ic)
4148 int size, offset = 0;
4149 unsigned long lit = 0L;
4152 D(emitcode ("; genCmp",""));
4154 /* if left & right are bit variables */
4155 if (AOP_TYPE (left) == AOP_CRY &&
4156 AOP_TYPE (right) == AOP_CRY)
4158 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4159 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4163 /* subtract right from left if at the
4164 end the carry flag is set then we know that
4165 left is greater than right */
4166 size = max (AOP_SIZE (left), AOP_SIZE (right));
4168 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4169 if ((size == 1) && !sign &&
4170 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4172 symbol *lbl = newiTempLabel (NULL);
4173 emitcode ("cjne", "%s,%s,%05d$",
4174 aopGet (AOP (left), offset, FALSE, FALSE),
4175 aopGet (AOP (right), offset, FALSE, FALSE),
4177 emitcode ("", "%05d$:", lbl->key + 100);
4181 if (AOP_TYPE (right) == AOP_LIT)
4183 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4184 /* optimize if(x < 0) or if(x >= 0) */
4193 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4194 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4196 genIfxJump (ifx, "acc.7");
4200 emitcode ("rlc", "a");
4208 rightInB = aopGetUsesAcc(AOP (right), offset);
4210 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4211 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4212 if (sign && size == 0)
4214 emitcode ("xrl", "a,#0x80");
4215 if (AOP_TYPE (right) == AOP_LIT)
4217 unsigned long lit = (unsigned long)
4218 floatFromVal (AOP (right)->aopu.aop_lit);
4219 emitcode ("subb", "a,#0x%02x",
4220 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4225 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4226 emitcode ("xrl", "b,#0x80");
4227 emitcode ("subb", "a,b");
4233 emitcode ("subb", "a,b");
4235 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4243 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4244 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4245 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4251 /* if the result is used in the next
4252 ifx conditional branch then generate
4253 code a little differently */
4255 genIfxJump (ifx, "c");
4258 /* leave the result in acc */
4262 /*-----------------------------------------------------------------*/
4263 /* genCmpGt :- greater than comparison */
4264 /*-----------------------------------------------------------------*/
4266 genCmpGt (iCode * ic, iCode * ifx)
4268 operand *left, *right, *result;
4269 sym_link *letype, *retype;
4272 D(emitcode ("; genCmpGt",""));
4274 left = IC_LEFT (ic);
4275 right = IC_RIGHT (ic);
4276 result = IC_RESULT (ic);
4278 letype = getSpec (operandType (left));
4279 retype = getSpec (operandType (right));
4280 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4281 /* assign the amsops */
4282 aopOp (left, ic, FALSE);
4283 aopOp (right, ic, FALSE);
4284 aopOp (result, ic, TRUE);
4286 genCmp (right, left, result, ifx, sign,ic);
4288 freeAsmop (result, NULL, ic, TRUE);
4291 /*-----------------------------------------------------------------*/
4292 /* genCmpLt - less than comparisons */
4293 /*-----------------------------------------------------------------*/
4295 genCmpLt (iCode * ic, iCode * ifx)
4297 operand *left, *right, *result;
4298 sym_link *letype, *retype;
4301 D(emitcode ("; genCmpLt",""));
4303 left = IC_LEFT (ic);
4304 right = IC_RIGHT (ic);
4305 result = IC_RESULT (ic);
4307 letype = getSpec (operandType (left));
4308 retype = getSpec (operandType (right));
4309 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4311 /* assign the amsops */
4312 aopOp (left, ic, FALSE);
4313 aopOp (right, ic, FALSE);
4314 aopOp (result, ic, TRUE);
4316 genCmp (left, right, result, ifx, sign,ic);
4318 freeAsmop (result, NULL, ic, TRUE);
4321 /*-----------------------------------------------------------------*/
4322 /* gencjneshort - compare and jump if not equal */
4323 /*-----------------------------------------------------------------*/
4325 gencjneshort (operand * left, operand * right, symbol * lbl)
4327 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4329 unsigned long lit = 0L;
4331 /* if the left side is a literal or
4332 if the right is in a pointer register and left
4334 if ((AOP_TYPE (left) == AOP_LIT) ||
4335 (AOP_TYPE (left) == AOP_IMMD) ||
4336 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4343 if (AOP_TYPE (right) == AOP_LIT)
4344 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4346 /* if the right side is a literal then anything goes */
4347 if (AOP_TYPE (right) == AOP_LIT &&
4348 AOP_TYPE (left) != AOP_DIR &&
4349 AOP_TYPE (left) != AOP_IMMD)
4353 emitcode ("cjne", "%s,%s,%05d$",
4354 aopGet (AOP (left), offset, FALSE, FALSE),
4355 aopGet (AOP (right), offset, FALSE, FALSE),
4361 /* if the right side is in a register or in direct space or
4362 if the left is a pointer register & right is not */
4363 else if (AOP_TYPE (right) == AOP_REG ||
4364 AOP_TYPE (right) == AOP_DIR ||
4365 AOP_TYPE (right) == AOP_LIT ||
4366 AOP_TYPE (right) == AOP_IMMD ||
4367 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4368 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4372 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4373 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4374 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4375 emitcode ("jnz", "%05d$", lbl->key + 100);
4377 emitcode ("cjne", "a,%s,%05d$",
4378 aopGet (AOP (right), offset, FALSE, TRUE),
4385 /* right is a pointer reg need both a & b */
4388 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4389 if (strcmp (l, "b"))
4390 emitcode ("mov", "b,%s", l);
4391 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4392 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4398 /*-----------------------------------------------------------------*/
4399 /* gencjne - compare and jump if not equal */
4400 /*-----------------------------------------------------------------*/
4402 gencjne (operand * left, operand * right, symbol * lbl)
4404 symbol *tlbl = newiTempLabel (NULL);
4406 gencjneshort (left, right, lbl);
4408 emitcode ("mov", "a,%s", one);
4409 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4410 emitcode ("", "%05d$:", lbl->key + 100);
4411 emitcode ("clr", "a");
4412 emitcode ("", "%05d$:", tlbl->key + 100);
4415 /*-----------------------------------------------------------------*/
4416 /* genCmpEq - generates code for equal to */
4417 /*-----------------------------------------------------------------*/
4419 genCmpEq (iCode * ic, iCode * ifx)
4421 operand *left, *right, *result;
4423 D(emitcode ("; genCmpEq",""));
4425 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4426 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4427 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4429 /* if literal, literal on the right or
4430 if the right is in a pointer register and left
4432 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4433 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4435 operand *t = IC_RIGHT (ic);
4436 IC_RIGHT (ic) = IC_LEFT (ic);
4440 if (ifx && !AOP_SIZE (result))
4443 /* if they are both bit variables */
4444 if (AOP_TYPE (left) == AOP_CRY &&
4445 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4447 if (AOP_TYPE (right) == AOP_LIT)
4449 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4452 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4453 emitcode ("cpl", "c");
4457 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4461 emitcode ("clr", "c");
4463 /* AOP_TYPE(right) == AOP_CRY */
4467 symbol *lbl = newiTempLabel (NULL);
4468 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4469 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4470 emitcode ("cpl", "c");
4471 emitcode ("", "%05d$:", (lbl->key + 100));
4473 /* if true label then we jump if condition
4475 tlbl = newiTempLabel (NULL);
4478 emitcode ("jnc", "%05d$", tlbl->key + 100);
4479 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4483 emitcode ("jc", "%05d$", tlbl->key + 100);
4484 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4486 emitcode ("", "%05d$:", tlbl->key + 100);
4490 tlbl = newiTempLabel (NULL);
4491 gencjneshort (left, right, tlbl);
4494 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4495 emitcode ("", "%05d$:", tlbl->key + 100);
4499 symbol *lbl = newiTempLabel (NULL);
4500 emitcode ("sjmp", "%05d$", lbl->key + 100);
4501 emitcode ("", "%05d$:", tlbl->key + 100);
4502 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4503 emitcode ("", "%05d$:", lbl->key + 100);
4506 /* mark the icode as generated */
4511 /* if they are both bit variables */
4512 if (AOP_TYPE (left) == AOP_CRY &&
4513 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4515 if (AOP_TYPE (right) == AOP_LIT)
4517 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4520 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4521 emitcode ("cpl", "c");
4525 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4529 emitcode ("clr", "c");
4531 /* AOP_TYPE(right) == AOP_CRY */
4535 symbol *lbl = newiTempLabel (NULL);
4536 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4537 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4538 emitcode ("cpl", "c");
4539 emitcode ("", "%05d$:", (lbl->key + 100));
4542 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4549 genIfxJump (ifx, "c");
4552 /* if the result is used in an arithmetic operation
4553 then put the result in place */
4558 gencjne (left, right, newiTempLabel (NULL));
4559 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4561 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4566 genIfxJump (ifx, "a");
4569 /* if the result is used in an arithmetic operation
4570 then put the result in place */
4571 if (AOP_TYPE (result) != AOP_CRY)
4573 /* leave the result in acc */
4577 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4578 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4579 freeAsmop (result, NULL, ic, TRUE);
4582 /*-----------------------------------------------------------------*/
4583 /* ifxForOp - returns the icode containing the ifx for operand */
4584 /*-----------------------------------------------------------------*/
4586 ifxForOp (operand * op, iCode * ic)
4588 /* if true symbol then needs to be assigned */
4589 if (IS_TRUE_SYMOP (op))
4592 /* if this has register type condition and
4593 the next instruction is ifx with the same operand
4594 and live to of the operand is upto the ifx only then */
4596 ic->next->op == IFX &&
4597 IC_COND (ic->next)->key == op->key &&
4598 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4604 /*-----------------------------------------------------------------*/
4605 /* hasInc - operand is incremented before any other use */
4606 /*-----------------------------------------------------------------*/
4608 hasInc (operand *op, iCode *ic,int osize)
4610 sym_link *type = operandType(op);
4611 sym_link *retype = getSpec (type);
4612 iCode *lic = ic->next;
4615 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4616 if (!IS_SYMOP(op)) return NULL;
4618 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4619 if (IS_AGGREGATE(type->next)) return NULL;
4620 if (osize != (isize = getSize(type->next))) return NULL;
4623 /* if operand of the form op = op + <sizeof *op> */
4624 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4625 isOperandEqual(IC_RESULT(lic),op) &&
4626 isOperandLiteral(IC_RIGHT(lic)) &&
4627 operandLitValue(IC_RIGHT(lic)) == isize) {
4630 /* if the operand used or deffed */
4631 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4634 /* if GOTO or IFX */
4635 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4641 /*-----------------------------------------------------------------*/
4642 /* genAndOp - for && operation */
4643 /*-----------------------------------------------------------------*/
4645 genAndOp (iCode * ic)
4647 operand *left, *right, *result;
4650 D(emitcode ("; genAndOp",""));
4652 /* note here that && operations that are in an
4653 if statement are taken away by backPatchLabels
4654 only those used in arthmetic operations remain */
4655 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4656 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4657 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4659 /* if both are bit variables */
4660 if (AOP_TYPE (left) == AOP_CRY &&
4661 AOP_TYPE (right) == AOP_CRY)
4663 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4664 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4669 tlbl = newiTempLabel (NULL);
4671 emitcode ("jz", "%05d$", tlbl->key + 100);
4673 emitcode ("", "%05d$:", tlbl->key + 100);
4677 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4678 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4679 freeAsmop (result, NULL, ic, TRUE);
4683 /*-----------------------------------------------------------------*/
4684 /* genOrOp - for || operation */
4685 /*-----------------------------------------------------------------*/
4687 genOrOp (iCode * ic)
4689 operand *left, *right, *result;
4692 D(emitcode ("; genOrOp",""));
4694 /* note here that || operations that are in an
4695 if statement are taken away by backPatchLabels
4696 only those used in arthmetic operations remain */
4697 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4698 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4699 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4701 /* if both are bit variables */
4702 if (AOP_TYPE (left) == AOP_CRY &&
4703 AOP_TYPE (right) == AOP_CRY)
4705 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4706 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4711 tlbl = newiTempLabel (NULL);
4713 emitcode ("jnz", "%05d$", tlbl->key + 100);
4715 emitcode ("", "%05d$:", tlbl->key + 100);
4719 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4720 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4721 freeAsmop (result, NULL, ic, TRUE);
4724 /*-----------------------------------------------------------------*/
4725 /* isLiteralBit - test if lit == 2^n */
4726 /*-----------------------------------------------------------------*/
4728 isLiteralBit (unsigned long lit)
4730 unsigned long pw[32] =
4731 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4732 0x100L, 0x200L, 0x400L, 0x800L,
4733 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4734 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4735 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4736 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4737 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4740 for (idx = 0; idx < 32; idx++)
4746 /*-----------------------------------------------------------------*/
4747 /* continueIfTrue - */
4748 /*-----------------------------------------------------------------*/
4750 continueIfTrue (iCode * ic)
4753 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4757 /*-----------------------------------------------------------------*/
4759 /*-----------------------------------------------------------------*/
4761 jumpIfTrue (iCode * ic)
4764 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4768 /*-----------------------------------------------------------------*/
4769 /* jmpTrueOrFalse - */
4770 /*-----------------------------------------------------------------*/
4772 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4774 // ugly but optimized by peephole
4777 symbol *nlbl = newiTempLabel (NULL);
4778 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4779 emitcode ("", "%05d$:", tlbl->key + 100);
4780 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4781 emitcode ("", "%05d$:", nlbl->key + 100);
4785 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4786 emitcode ("", "%05d$:", tlbl->key + 100);
4791 /*-----------------------------------------------------------------*/
4792 /* genAnd - code for and */
4793 /*-----------------------------------------------------------------*/
4795 genAnd (iCode * ic, iCode * ifx)
4797 operand *left, *right, *result;
4798 int size, offset = 0;
4799 unsigned long lit = 0L;
4803 D(emitcode ("; genAnd",""));
4805 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4806 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4807 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4810 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4812 AOP_TYPE (left), AOP_TYPE (right));
4813 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4815 AOP_SIZE (left), AOP_SIZE (right));
4818 /* if left is a literal & right is not then exchange them */
4819 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4820 AOP_NEEDSACC (left))
4822 operand *tmp = right;
4827 /* if result = right then exchange them */
4828 if (sameRegs (AOP (result), AOP (right)))
4830 operand *tmp = right;
4835 /* if right is bit then exchange them */
4836 if (AOP_TYPE (right) == AOP_CRY &&
4837 AOP_TYPE (left) != AOP_CRY)
4839 operand *tmp = right;
4843 if (AOP_TYPE (right) == AOP_LIT)
4844 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4846 size = AOP_SIZE (result);
4849 // result = bit & yy;
4850 if (AOP_TYPE (left) == AOP_CRY)
4852 // c = bit & literal;
4853 if (AOP_TYPE (right) == AOP_LIT)
4857 if (size && sameRegs (AOP (result), AOP (left)))
4860 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4865 if (size && (AOP_TYPE (result) == AOP_CRY))
4867 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4870 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4875 emitcode ("clr", "c");
4880 if (AOP_TYPE (right) == AOP_CRY)
4883 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4884 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4889 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4891 emitcode ("rrc", "a");
4892 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4900 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4901 genIfxJump (ifx, "c");
4905 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4906 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4907 if ((AOP_TYPE (right) == AOP_LIT) &&
4908 (AOP_TYPE (result) == AOP_CRY) &&
4909 (AOP_TYPE (left) != AOP_CRY))
4911 int posbit = isLiteralBit (lit);
4916 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4919 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4925 sprintf (buffer, "acc.%d", posbit & 0x07);
4926 genIfxJump (ifx, buffer);
4933 symbol *tlbl = newiTempLabel (NULL);
4934 int sizel = AOP_SIZE (left);
4936 emitcode ("setb", "c");
4939 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4941 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4943 if ((posbit = isLiteralBit (bytelit)) != 0)
4944 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4947 if (bytelit != 0x0FFL)
4948 emitcode ("anl", "a,%s",
4949 aopGet (AOP (right), offset, FALSE, TRUE));
4950 emitcode ("jnz", "%05d$", tlbl->key + 100);
4955 // bit = left & literal
4958 emitcode ("clr", "c");
4959 emitcode ("", "%05d$:", tlbl->key + 100);
4961 // if(left & literal)
4965 jmpTrueOrFalse (ifx, tlbl);
4967 emitcode ("", "%05d$:", tlbl->key + 100);
4975 /* if left is same as result */
4976 if (sameRegs (AOP (result), AOP (left)))
4978 for (; size--; offset++)
4980 if (AOP_TYPE (right) == AOP_LIT)
4982 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4984 else if (bytelit == 0)
4986 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4988 else if (IS_AOP_PREG (result))
4990 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4991 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4992 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4995 emitcode ("anl", "%s,%s",
4996 aopGet (AOP (left), offset, FALSE, TRUE),
4997 aopGet (AOP (right), offset, FALSE, FALSE));
5001 if (AOP_TYPE (left) == AOP_ACC)
5002 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5005 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5006 if (IS_AOP_PREG (result))
5008 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5009 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5013 emitcode ("anl", "%s,a",
5014 aopGet (AOP (left), offset, FALSE, TRUE));
5021 // left & result in different registers
5022 if (AOP_TYPE (result) == AOP_CRY)
5025 // if(size), result in bit
5026 // if(!size && ifx), conditional oper: if(left & right)
5027 symbol *tlbl = newiTempLabel (NULL);
5028 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5030 emitcode ("setb", "c");
5033 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5034 emitcode ("anl", "a,%s",
5035 aopGet (AOP (right), offset, FALSE, FALSE));
5037 if (AOP_TYPE(left)==AOP_ACC) {
5038 emitcode("mov", "b,a");
5039 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5040 emitcode("anl", "a,b");
5042 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5043 emitcode ("anl", "a,%s",
5044 aopGet (AOP (left), offset, FALSE, FALSE));
5047 emitcode ("jnz", "%05d$", tlbl->key + 100);
5053 emitcode ("", "%05d$:", tlbl->key + 100);
5057 jmpTrueOrFalse (ifx, tlbl);
5059 emitcode ("", "%05d$:", tlbl->key + 100);
5063 for (; (size--); offset++)
5066 // result = left & right
5067 if (AOP_TYPE (right) == AOP_LIT)
5069 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5071 aopPut (AOP (result),
5072 aopGet (AOP (left), offset, FALSE, FALSE),
5074 isOperandVolatile (result, FALSE));
5077 else if (bytelit == 0)
5079 /* dummy read of volatile operand */
5080 if (isOperandVolatile (left, FALSE))
5081 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5082 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5086 // faster than result <- left, anl result,right
5087 // and better if result is SFR
5088 if (AOP_TYPE (left) == AOP_ACC)
5089 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5092 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5093 emitcode ("anl", "a,%s",
5094 aopGet (AOP (left), offset, FALSE, FALSE));
5096 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5102 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5103 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5104 freeAsmop (result, NULL, ic, TRUE);
5107 /*-----------------------------------------------------------------*/
5108 /* genOr - code for or */
5109 /*-----------------------------------------------------------------*/
5111 genOr (iCode * ic, iCode * ifx)
5113 operand *left, *right, *result;
5114 int size, offset = 0;
5115 unsigned long lit = 0L;
5117 D(emitcode ("; genOr",""));
5119 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5120 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5121 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5124 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5126 AOP_TYPE (left), AOP_TYPE (right));
5127 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5129 AOP_SIZE (left), AOP_SIZE (right));
5132 /* if left is a literal & right is not then exchange them */
5133 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5134 AOP_NEEDSACC (left))
5136 operand *tmp = right;
5141 /* if result = right then exchange them */
5142 if (sameRegs (AOP (result), AOP (right)))
5144 operand *tmp = right;
5149 /* if right is bit then exchange them */
5150 if (AOP_TYPE (right) == AOP_CRY &&
5151 AOP_TYPE (left) != AOP_CRY)
5153 operand *tmp = right;
5157 if (AOP_TYPE (right) == AOP_LIT)
5158 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5160 size = AOP_SIZE (result);
5164 if (AOP_TYPE (left) == AOP_CRY)
5166 if (AOP_TYPE (right) == AOP_LIT)
5168 // c = bit | literal;
5171 // lit != 0 => result = 1
5172 if (AOP_TYPE (result) == AOP_CRY)
5175 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5177 continueIfTrue (ifx);
5180 emitcode ("setb", "c");
5184 // lit == 0 => result = left
5185 if (size && sameRegs (AOP (result), AOP (left)))
5187 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5192 if (AOP_TYPE (right) == AOP_CRY)
5195 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5196 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5201 symbol *tlbl = newiTempLabel (NULL);
5202 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5203 emitcode ("setb", "c");
5204 emitcode ("jb", "%s,%05d$",
5205 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5207 emitcode ("jnz", "%05d$", tlbl->key + 100);
5208 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5210 jmpTrueOrFalse (ifx, tlbl);
5216 emitcode ("", "%05d$:", tlbl->key + 100);
5225 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5226 genIfxJump (ifx, "c");
5230 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5231 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5232 if ((AOP_TYPE (right) == AOP_LIT) &&
5233 (AOP_TYPE (result) == AOP_CRY) &&
5234 (AOP_TYPE (left) != AOP_CRY))
5240 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5242 continueIfTrue (ifx);
5247 // lit = 0, result = boolean(left)
5249 emitcode ("setb", "c");
5253 symbol *tlbl = newiTempLabel (NULL);
5254 emitcode ("jnz", "%05d$", tlbl->key + 100);
5256 emitcode ("", "%05d$:", tlbl->key + 100);
5260 genIfxJump (ifx, "a");
5268 /* if left is same as result */
5269 if (sameRegs (AOP (result), AOP (left)))
5271 for (; size--; offset++)
5273 if (AOP_TYPE (right) == AOP_LIT)
5275 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5277 /* dummy read of volatile operand */
5278 if (isOperandVolatile (left, FALSE))
5279 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5283 else if (IS_AOP_PREG (left))
5285 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5286 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5287 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5290 emitcode ("orl", "%s,%s",
5291 aopGet (AOP (left), offset, FALSE, TRUE),
5292 aopGet (AOP (right), offset, FALSE, FALSE));
5296 if (AOP_TYPE (left) == AOP_ACC)
5297 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5300 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5301 if (IS_AOP_PREG (left))
5303 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5304 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5307 emitcode ("orl", "%s,a",
5308 aopGet (AOP (left), offset, FALSE, TRUE));
5315 // left & result in different registers
5316 if (AOP_TYPE (result) == AOP_CRY)
5319 // if(size), result in bit
5320 // if(!size && ifx), conditional oper: if(left | right)
5321 symbol *tlbl = newiTempLabel (NULL);
5322 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5324 emitcode ("setb", "c");
5327 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5328 emitcode ("orl", "a,%s",
5329 aopGet (AOP (right), offset, FALSE, FALSE));
5331 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5332 emitcode ("orl", "a,%s",
5333 aopGet (AOP (left), offset, FALSE, FALSE));
5335 emitcode ("jnz", "%05d$", tlbl->key + 100);
5341 emitcode ("", "%05d$:", tlbl->key + 100);
5345 jmpTrueOrFalse (ifx, tlbl);
5347 emitcode ("", "%05d$:", tlbl->key + 100);
5350 for (; (size--); offset++)
5353 // result = left & right
5354 if (AOP_TYPE (right) == AOP_LIT)
5356 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5358 aopPut (AOP (result),
5359 aopGet (AOP (left), offset, FALSE, FALSE),
5361 isOperandVolatile (result, FALSE));
5365 // faster than result <- left, anl result,right
5366 // and better if result is SFR
5367 if (AOP_TYPE (left) == AOP_ACC)
5368 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5371 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5372 emitcode ("orl", "a,%s",
5373 aopGet (AOP (left), offset, FALSE, FALSE));
5375 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5380 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5381 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5382 freeAsmop (result, NULL, ic, TRUE);
5385 /*-----------------------------------------------------------------*/
5386 /* genXor - code for xclusive or */
5387 /*-----------------------------------------------------------------*/
5389 genXor (iCode * ic, iCode * ifx)
5391 operand *left, *right, *result;
5392 int size, offset = 0;
5393 unsigned long lit = 0L;
5395 D(emitcode ("; genXor",""));
5397 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5398 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5399 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5402 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5404 AOP_TYPE (left), AOP_TYPE (right));
5405 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5407 AOP_SIZE (left), AOP_SIZE (right));
5410 /* if left is a literal & right is not ||
5411 if left needs acc & right does not */
5412 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5413 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5415 operand *tmp = right;
5420 /* if result = right then exchange them */
5421 if (sameRegs (AOP (result), AOP (right)))
5423 operand *tmp = right;
5428 /* if right is bit then exchange them */
5429 if (AOP_TYPE (right) == AOP_CRY &&
5430 AOP_TYPE (left) != AOP_CRY)
5432 operand *tmp = right;
5436 if (AOP_TYPE (right) == AOP_LIT)
5437 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5439 size = AOP_SIZE (result);
5443 if (AOP_TYPE (left) == AOP_CRY)
5445 if (AOP_TYPE (right) == AOP_LIT)
5447 // c = bit & literal;
5450 // lit>>1 != 0 => result = 1
5451 if (AOP_TYPE (result) == AOP_CRY)
5454 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5456 continueIfTrue (ifx);
5459 emitcode ("setb", "c");
5466 // lit == 0, result = left
5467 if (size && sameRegs (AOP (result), AOP (left)))
5469 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5473 // lit == 1, result = not(left)
5474 if (size && sameRegs (AOP (result), AOP (left)))
5476 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5481 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5482 emitcode ("cpl", "c");
5491 symbol *tlbl = newiTempLabel (NULL);
5492 if (AOP_TYPE (right) == AOP_CRY)
5495 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5499 int sizer = AOP_SIZE (right);
5501 // if val>>1 != 0, result = 1
5502 emitcode ("setb", "c");
5505 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5507 // test the msb of the lsb
5508 emitcode ("anl", "a,#0xfe");
5509 emitcode ("jnz", "%05d$", tlbl->key + 100);
5513 emitcode ("rrc", "a");
5515 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5516 emitcode ("cpl", "c");
5517 emitcode ("", "%05d$:", (tlbl->key + 100));
5524 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5525 genIfxJump (ifx, "c");
5529 if (sameRegs (AOP (result), AOP (left)))
5531 /* if left is same as result */
5532 for (; size--; offset++)
5534 if (AOP_TYPE (right) == AOP_LIT)
5536 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5538 else if (IS_AOP_PREG (left))
5540 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5541 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5542 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5545 emitcode ("xrl", "%s,%s",
5546 aopGet (AOP (left), offset, FALSE, TRUE),
5547 aopGet (AOP (right), offset, FALSE, FALSE));
5551 if (AOP_TYPE (left) == AOP_ACC)
5552 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5555 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5556 if (IS_AOP_PREG (left))
5558 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5559 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5562 emitcode ("xrl", "%s,a",
5563 aopGet (AOP (left), offset, FALSE, TRUE));
5570 // left & result in different registers
5571 if (AOP_TYPE (result) == AOP_CRY)
5574 // if(size), result in bit
5575 // if(!size && ifx), conditional oper: if(left ^ right)
5576 symbol *tlbl = newiTempLabel (NULL);
5577 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5579 emitcode ("setb", "c");
5582 if ((AOP_TYPE (right) == AOP_LIT) &&
5583 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5585 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5589 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5590 emitcode ("xrl", "a,%s",
5591 aopGet (AOP (right), offset, FALSE, FALSE));
5593 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5594 emitcode ("xrl", "a,%s",
5595 aopGet (AOP (left), offset, FALSE, FALSE));
5598 emitcode ("jnz", "%05d$", tlbl->key + 100);
5604 emitcode ("", "%05d$:", tlbl->key + 100);
5608 jmpTrueOrFalse (ifx, tlbl);
5611 for (; (size--); offset++)
5614 // result = left & right
5615 if (AOP_TYPE (right) == AOP_LIT)
5617 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5619 aopPut (AOP (result),
5620 aopGet (AOP (left), offset, FALSE, FALSE),
5622 isOperandVolatile (result, FALSE));
5626 // faster than result <- left, anl result,right
5627 // and better if result is SFR
5628 if (AOP_TYPE (left) == AOP_ACC)
5629 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5632 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5633 emitcode ("xrl", "a,%s",
5634 aopGet (AOP (left), offset, FALSE, TRUE));
5636 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5641 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5642 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5643 freeAsmop (result, NULL, ic, TRUE);
5646 /*-----------------------------------------------------------------*/
5647 /* genInline - write the inline code out */
5648 /*-----------------------------------------------------------------*/
5650 genInline (iCode * ic)
5652 char *buffer, *bp, *bp1;
5654 D(emitcode ("; genInline",""));
5656 _G.inLine += (!options.asmpeep);
5658 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5659 strcpy (buffer, IC_INLINE (ic));
5661 /* emit each line as a code */
5686 /* emitcode("",buffer); */
5687 _G.inLine -= (!options.asmpeep);
5690 /*-----------------------------------------------------------------*/
5691 /* genRRC - rotate right with carry */
5692 /*-----------------------------------------------------------------*/
5696 operand *left, *result;
5697 int size, offset = 0;
5700 D(emitcode ("; genRRC",""));
5702 /* rotate right with carry */
5703 left = IC_LEFT (ic);
5704 result = IC_RESULT (ic);
5705 aopOp (left, ic, FALSE);
5706 aopOp (result, ic, FALSE);
5708 /* move it to the result */
5709 size = AOP_SIZE (result);
5711 if (size == 1) { /* special case for 1 byte */
5712 l = aopGet (AOP (left), offset, FALSE, FALSE);
5714 emitcode ("rr", "a");
5720 l = aopGet (AOP (left), offset, FALSE, FALSE);
5722 emitcode ("rrc", "a");
5723 if (AOP_SIZE (result) > 1)
5724 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5726 /* now we need to put the carry into the
5727 highest order byte of the result */
5728 if (AOP_SIZE (result) > 1)
5730 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5733 emitcode ("mov", "acc.7,c");
5735 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5736 freeAsmop (left, NULL, ic, TRUE);
5737 freeAsmop (result, NULL, ic, TRUE);
5740 /*-----------------------------------------------------------------*/
5741 /* genRLC - generate code for rotate left with carry */
5742 /*-----------------------------------------------------------------*/
5746 operand *left, *result;
5747 int size, offset = 0;
5750 D(emitcode ("; genRLC",""));
5752 /* rotate right with carry */
5753 left = IC_LEFT (ic);
5754 result = IC_RESULT (ic);
5755 aopOp (left, ic, FALSE);
5756 aopOp (result, ic, FALSE);
5758 /* move it to the result */
5759 size = AOP_SIZE (result);
5763 l = aopGet (AOP (left), offset, FALSE, FALSE);
5765 if (size == 0) { /* special case for 1 byte */
5769 emitcode ("add", "a,acc");
5770 if (AOP_SIZE (result) > 1)
5771 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5774 l = aopGet (AOP (left), offset, FALSE, FALSE);
5776 emitcode ("rlc", "a");
5777 if (AOP_SIZE (result) > 1)
5778 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5781 /* now we need to put the carry into the
5782 highest order byte of the result */
5783 if (AOP_SIZE (result) > 1)
5785 l = aopGet (AOP (result), 0, FALSE, FALSE);
5788 emitcode ("mov", "acc.0,c");
5790 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5791 freeAsmop (left, NULL, ic, TRUE);
5792 freeAsmop (result, NULL, ic, TRUE);
5795 /*-----------------------------------------------------------------*/
5796 /* genGetHbit - generates code get highest order bit */
5797 /*-----------------------------------------------------------------*/
5799 genGetHbit (iCode * ic)
5801 operand *left, *result;
5803 D(emitcode ("; genGetHbit",""));
5805 left = IC_LEFT (ic);
5806 result = IC_RESULT (ic);
5807 aopOp (left, ic, FALSE);
5808 aopOp (result, ic, FALSE);
5810 /* get the highest order byte into a */
5811 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5812 if (AOP_TYPE (result) == AOP_CRY)
5814 emitcode ("rlc", "a");
5819 emitcode ("rl", "a");
5820 emitcode ("anl", "a,#0x01");
5825 freeAsmop (left, NULL, ic, TRUE);
5826 freeAsmop (result, NULL, ic, TRUE);
5829 /*-----------------------------------------------------------------*/
5830 /* genSwap - generates code to swap nibbles or bytes */
5831 /*-----------------------------------------------------------------*/
5833 genSwap (iCode * ic)
5835 operand *left, *result;
5837 D(emitcode ("; genSwap",""));
5839 left = IC_LEFT (ic);
5840 result = IC_RESULT (ic);
5841 aopOp (left, ic, FALSE);
5842 aopOp (result, ic, FALSE);
5844 switch (AOP_SIZE (left))
5846 case 1: /* swap nibbles in byte */
5847 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5848 emitcode ("swap", "a");
5849 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5851 case 2: /* swap bytes in word */
5852 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
5854 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5855 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5856 0, isOperandVolatile (result, FALSE));
5857 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
5859 else if (operandsEqu (left, result))
5862 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5863 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
5865 emitcode ("mov", "b,a");
5868 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5869 0, isOperandVolatile (result, FALSE));
5870 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
5874 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5875 0, isOperandVolatile (result, FALSE));
5876 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
5877 1, isOperandVolatile (result, FALSE));
5881 wassertl(FALSE, "unsupported SWAP operand size");
5884 freeAsmop (left, NULL, ic, TRUE);
5885 freeAsmop (result, NULL, ic, TRUE);
5889 /*-----------------------------------------------------------------*/
5890 /* AccRol - rotate left accumulator by known count */
5891 /*-----------------------------------------------------------------*/
5893 AccRol (int shCount)
5895 shCount &= 0x0007; // shCount : 0..7
5902 emitcode ("rl", "a");
5905 emitcode ("rl", "a");
5906 emitcode ("rl", "a");
5909 emitcode ("swap", "a");
5910 emitcode ("rr", "a");
5913 emitcode ("swap", "a");
5916 emitcode ("swap", "a");
5917 emitcode ("rl", "a");
5920 emitcode ("rr", "a");
5921 emitcode ("rr", "a");
5924 emitcode ("rr", "a");
5929 /*-----------------------------------------------------------------*/
5930 /* AccLsh - left shift accumulator by known count */
5931 /*-----------------------------------------------------------------*/
5933 AccLsh (int shCount)
5938 emitcode ("add", "a,acc");
5939 else if (shCount == 2)
5941 emitcode ("add", "a,acc");
5942 emitcode ("add", "a,acc");
5946 /* rotate left accumulator */
5948 /* and kill the lower order bits */
5949 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5954 /*-----------------------------------------------------------------*/
5955 /* AccRsh - right shift accumulator by known count */
5956 /*-----------------------------------------------------------------*/
5958 AccRsh (int shCount)
5965 emitcode ("rrc", "a");
5969 /* rotate right accumulator */
5970 AccRol (8 - shCount);
5971 /* and kill the higher order bits */
5972 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5977 /*-----------------------------------------------------------------*/
5978 /* AccSRsh - signed right shift accumulator by known count */
5979 /*-----------------------------------------------------------------*/
5981 AccSRsh (int shCount)
5988 emitcode ("mov", "c,acc.7");
5989 emitcode ("rrc", "a");
5991 else if (shCount == 2)
5993 emitcode ("mov", "c,acc.7");
5994 emitcode ("rrc", "a");
5995 emitcode ("mov", "c,acc.7");
5996 emitcode ("rrc", "a");
6000 tlbl = newiTempLabel (NULL);
6001 /* rotate right accumulator */
6002 AccRol (8 - shCount);
6003 /* and kill the higher order bits */
6004 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6005 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6006 emitcode ("orl", "a,#0x%02x",
6007 (unsigned char) ~SRMask[shCount]);
6008 emitcode ("", "%05d$:", tlbl->key + 100);
6013 /*-----------------------------------------------------------------*/
6014 /* shiftR1Left2Result - shift right one byte from left to result */
6015 /*-----------------------------------------------------------------*/
6017 shiftR1Left2Result (operand * left, int offl,
6018 operand * result, int offr,
6019 int shCount, int sign)
6021 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6022 /* shift right accumulator */
6027 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6030 /*-----------------------------------------------------------------*/
6031 /* shiftL1Left2Result - shift left one byte from left to result */
6032 /*-----------------------------------------------------------------*/
6034 shiftL1Left2Result (operand * left, int offl,
6035 operand * result, int offr, int shCount)
6038 l = aopGet (AOP (left), offl, FALSE, FALSE);
6040 /* shift left accumulator */
6042 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6045 /*-----------------------------------------------------------------*/
6046 /* movLeft2Result - move byte from left to result */
6047 /*-----------------------------------------------------------------*/
6049 movLeft2Result (operand * left, int offl,
6050 operand * result, int offr, int sign)
6053 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6055 l = aopGet (AOP (left), offl, FALSE, FALSE);
6057 if (*l == '@' && (IS_AOP_PREG (result)))
6059 emitcode ("mov", "a,%s", l);
6060 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6065 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6068 /* MSB sign in acc.7 ! */
6069 if (getDataSize (left) == offl + 1)
6071 emitcode ("mov", "a,%s", l);
6072 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6079 /*-----------------------------------------------------------------*/
6080 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6081 /*-----------------------------------------------------------------*/
6085 emitcode ("rrc", "a");
6086 emitcode ("xch", "a,%s", x);
6087 emitcode ("rrc", "a");
6088 emitcode ("xch", "a,%s", x);
6091 /*-----------------------------------------------------------------*/
6092 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6093 /*-----------------------------------------------------------------*/
6097 emitcode ("xch", "a,%s", x);
6098 emitcode ("rlc", "a");
6099 emitcode ("xch", "a,%s", x);
6100 emitcode ("rlc", "a");
6103 /*-----------------------------------------------------------------*/
6104 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6105 /*-----------------------------------------------------------------*/
6109 emitcode ("xch", "a,%s", x);
6110 emitcode ("add", "a,acc");
6111 emitcode ("xch", "a,%s", x);
6112 emitcode ("rlc", "a");
6115 /*-----------------------------------------------------------------*/
6116 /* AccAXLsh - left shift a:x by known count (0..7) */
6117 /*-----------------------------------------------------------------*/
6119 AccAXLsh (char *x, int shCount)
6134 case 5: // AAAAABBB:CCCCCDDD
6136 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6138 emitcode ("anl", "a,#0x%02x",
6139 SLMask[shCount]); // BBB00000:CCCCCDDD
6141 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6143 AccRol (shCount); // DDDCCCCC:BBB00000
6145 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6147 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6149 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6151 emitcode ("anl", "a,#0x%02x",
6152 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6154 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6156 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6159 case 6: // AAAAAABB:CCCCCCDD
6160 emitcode ("anl", "a,#0x%02x",
6161 SRMask[shCount]); // 000000BB:CCCCCCDD
6162 emitcode ("mov", "c,acc.0"); // c = B
6163 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6165 AccAXRrl1 (x); // BCCCCCCD:D000000B
6166 AccAXRrl1 (x); // BBCCCCCC:DD000000
6168 emitcode("rrc","a");
6169 emitcode("xch","a,%s", x);
6170 emitcode("rrc","a");
6171 emitcode("mov","c,acc.0"); //<< get correct bit
6172 emitcode("xch","a,%s", x);
6174 emitcode("rrc","a");
6175 emitcode("xch","a,%s", x);
6176 emitcode("rrc","a");
6177 emitcode("xch","a,%s", x);
6180 case 7: // a:x <<= 7
6182 emitcode ("anl", "a,#0x%02x",
6183 SRMask[shCount]); // 0000000B:CCCCCCCD
6185 emitcode ("mov", "c,acc.0"); // c = B
6187 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6189 AccAXRrl1 (x); // BCCCCCCC:D0000000
6197 /*-----------------------------------------------------------------*/
6198 /* AccAXRsh - right shift a:x known count (0..7) */
6199 /*-----------------------------------------------------------------*/
6201 AccAXRsh (char *x, int shCount)
6209 AccAXRrl1 (x); // 0->a:x
6214 AccAXRrl1 (x); // 0->a:x
6217 AccAXRrl1 (x); // 0->a:x
6222 case 5: // AAAAABBB:CCCCCDDD = a:x
6224 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6226 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6228 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6230 emitcode ("anl", "a,#0x%02x",
6231 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6233 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6235 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6237 emitcode ("anl", "a,#0x%02x",
6238 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6240 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6242 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6244 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6247 case 6: // AABBBBBB:CCDDDDDD
6249 emitcode ("mov", "c,acc.7");
6250 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6252 emitcode ("mov", "c,acc.7");
6253 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6255 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6257 emitcode ("anl", "a,#0x%02x",
6258 SRMask[shCount]); // 000000AA:BBBBBBCC
6261 case 7: // ABBBBBBB:CDDDDDDD
6263 emitcode ("mov", "c,acc.7"); // c = A
6265 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6267 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6269 emitcode ("anl", "a,#0x%02x",
6270 SRMask[shCount]); // 0000000A:BBBBBBBC
6278 /*-----------------------------------------------------------------*/
6279 /* AccAXRshS - right shift signed a:x known count (0..7) */
6280 /*-----------------------------------------------------------------*/
6282 AccAXRshS (char *x, int shCount)
6290 emitcode ("mov", "c,acc.7");
6291 AccAXRrl1 (x); // s->a:x
6295 emitcode ("mov", "c,acc.7");
6296 AccAXRrl1 (x); // s->a:x
6298 emitcode ("mov", "c,acc.7");
6299 AccAXRrl1 (x); // s->a:x
6304 case 5: // AAAAABBB:CCCCCDDD = a:x
6306 tlbl = newiTempLabel (NULL);
6307 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6309 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6311 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6313 emitcode ("anl", "a,#0x%02x",
6314 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6316 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6318 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6320 emitcode ("anl", "a,#0x%02x",
6321 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6323 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6325 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6327 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6329 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6330 emitcode ("orl", "a,#0x%02x",
6331 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6333 emitcode ("", "%05d$:", tlbl->key + 100);
6334 break; // SSSSAAAA:BBBCCCCC
6336 case 6: // AABBBBBB:CCDDDDDD
6338 tlbl = newiTempLabel (NULL);
6339 emitcode ("mov", "c,acc.7");
6340 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6342 emitcode ("mov", "c,acc.7");
6343 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6345 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6347 emitcode ("anl", "a,#0x%02x",
6348 SRMask[shCount]); // 000000AA:BBBBBBCC
6350 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6351 emitcode ("orl", "a,#0x%02x",
6352 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6354 emitcode ("", "%05d$:", tlbl->key + 100);
6356 case 7: // ABBBBBBB:CDDDDDDD
6358 tlbl = newiTempLabel (NULL);
6359 emitcode ("mov", "c,acc.7"); // c = A
6361 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6363 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6365 emitcode ("anl", "a,#0x%02x",
6366 SRMask[shCount]); // 0000000A:BBBBBBBC
6368 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6369 emitcode ("orl", "a,#0x%02x",
6370 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6372 emitcode ("", "%05d$:", tlbl->key + 100);
6379 /*-----------------------------------------------------------------*/
6380 /* shiftL2Left2Result - shift left two bytes from left to result */
6381 /*-----------------------------------------------------------------*/
6383 shiftL2Left2Result (operand * left, int offl,
6384 operand * result, int offr, int shCount)
6386 if (sameRegs (AOP (result), AOP (left)) &&
6387 ((offl + MSB16) == offr))
6389 /* don't crash result[offr] */
6390 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6391 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6395 movLeft2Result (left, offl, result, offr, 0);
6396 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6398 /* ax << shCount (x = lsb(result)) */
6399 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6400 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6404 /*-----------------------------------------------------------------*/
6405 /* shiftR2Left2Result - shift right two bytes from left to result */
6406 /*-----------------------------------------------------------------*/
6408 shiftR2Left2Result (operand * left, int offl,
6409 operand * result, int offr,
6410 int shCount, int sign)
6412 if (sameRegs (AOP (result), AOP (left)) &&
6413 ((offl + MSB16) == offr))
6415 /* don't crash result[offr] */
6416 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6417 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6421 movLeft2Result (left, offl, result, offr, 0);
6422 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6424 /* a:x >> shCount (x = lsb(result)) */
6426 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6428 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6429 if (getDataSize (result) > 1)
6430 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6433 /*-----------------------------------------------------------------*/
6434 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6435 /*-----------------------------------------------------------------*/
6437 shiftLLeftOrResult (operand * left, int offl,
6438 operand * result, int offr, int shCount)
6440 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6441 /* shift left accumulator */
6443 /* or with result */
6444 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6445 /* back to result */
6446 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6449 /*-----------------------------------------------------------------*/
6450 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6451 /*-----------------------------------------------------------------*/
6453 shiftRLeftOrResult (operand * left, int offl,
6454 operand * result, int offr, int shCount)
6456 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6457 /* shift right accumulator */
6459 /* or with result */
6460 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6461 /* back to result */
6462 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6465 /*-----------------------------------------------------------------*/
6466 /* genlshOne - left shift a one byte quantity by known count */
6467 /*-----------------------------------------------------------------*/
6469 genlshOne (operand * result, operand * left, int shCount)
6471 D(emitcode ("; genlshOne",""));
6473 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6476 /*-----------------------------------------------------------------*/
6477 /* genlshTwo - left shift two bytes by known amount != 0 */
6478 /*-----------------------------------------------------------------*/
6480 genlshTwo (operand * result, operand * left, int shCount)
6484 D(emitcode ("; genlshTwo",""));
6486 size = getDataSize (result);
6488 /* if shCount >= 8 */
6496 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6498 movLeft2Result (left, LSB, result, MSB16, 0);
6500 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6503 /* 1 <= shCount <= 7 */
6507 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6509 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6513 /*-----------------------------------------------------------------*/
6514 /* shiftLLong - shift left one long from left to result */
6515 /* offl = LSB or MSB16 */
6516 /*-----------------------------------------------------------------*/
6518 shiftLLong (operand * left, operand * result, int offr)
6521 int size = AOP_SIZE (result);
6523 if (size >= LSB + offr)
6525 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6527 emitcode ("add", "a,acc");
6528 if (sameRegs (AOP (left), AOP (result)) &&
6529 size >= MSB16 + offr && offr != LSB)
6530 emitcode ("xch", "a,%s",
6531 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6533 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6536 if (size >= MSB16 + offr)
6538 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6540 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6543 emitcode ("rlc", "a");
6544 if (sameRegs (AOP (left), AOP (result)) &&
6545 size >= MSB24 + offr && offr != LSB)
6546 emitcode ("xch", "a,%s",
6547 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6549 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6552 if (size >= MSB24 + offr)
6554 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6556 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6559 emitcode ("rlc", "a");
6560 if (sameRegs (AOP (left), AOP (result)) &&
6561 size >= MSB32 + offr && offr != LSB)
6562 emitcode ("xch", "a,%s",
6563 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6565 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6568 if (size > MSB32 + offr)
6570 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6572 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6575 emitcode ("rlc", "a");
6576 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6579 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6582 /*-----------------------------------------------------------------*/
6583 /* genlshFour - shift four byte by a known amount != 0 */
6584 /*-----------------------------------------------------------------*/
6586 genlshFour (operand * result, operand * left, int shCount)
6590 D(emitcode ("; genlshFour",""));
6592 size = AOP_SIZE (result);
6594 /* if shifting more that 3 bytes */
6599 /* lowest order of left goes to the highest
6600 order of the destination */
6601 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6603 movLeft2Result (left, LSB, result, MSB32, 0);
6604 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6605 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6606 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6610 /* more than two bytes */
6611 else if (shCount >= 16)
6613 /* lower order two bytes goes to higher order two bytes */
6615 /* if some more remaining */
6617 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6620 movLeft2Result (left, MSB16, result, MSB32, 0);
6621 movLeft2Result (left, LSB, result, MSB24, 0);
6623 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6624 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6628 /* if more than 1 byte */
6629 else if (shCount >= 8)
6631 /* lower order three bytes goes to higher order three bytes */
6636 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6638 movLeft2Result (left, LSB, result, MSB16, 0);
6644 movLeft2Result (left, MSB24, result, MSB32, 0);
6645 movLeft2Result (left, MSB16, result, MSB24, 0);
6646 movLeft2Result (left, LSB, result, MSB16, 0);
6647 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6649 else if (shCount == 1)
6650 shiftLLong (left, result, MSB16);
6653 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6654 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6655 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6656 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6661 /* 1 <= shCount <= 7 */
6662 else if (shCount <= 2)
6664 shiftLLong (left, result, LSB);
6666 shiftLLong (result, result, LSB);
6668 /* 3 <= shCount <= 7, optimize */
6671 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6672 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6673 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6677 /*-----------------------------------------------------------------*/
6678 /* genLeftShiftLiteral - left shifting by known count */
6679 /*-----------------------------------------------------------------*/
6681 genLeftShiftLiteral (operand * left,
6686 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6689 D(emitcode ("; genLeftShiftLiteral",""));
6691 freeAsmop (right, NULL, ic, TRUE);
6693 aopOp (left, ic, FALSE);
6694 aopOp (result, ic, FALSE);
6696 size = getSize (operandType (result));
6699 emitcode ("; shift left ", "result %d, left %d", size,
6703 /* I suppose that the left size >= result size */
6708 movLeft2Result (left, size, result, size, 0);
6712 else if (shCount >= (size * 8))
6714 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6720 genlshOne (result, left, shCount);
6724 genlshTwo (result, left, shCount);
6728 genlshFour (result, left, shCount);
6731 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6732 "*** ack! mystery literal shift!\n");
6736 freeAsmop (left, NULL, ic, TRUE);
6737 freeAsmop (result, NULL, ic, TRUE);
6740 /*-----------------------------------------------------------------*/
6741 /* genLeftShift - generates code for left shifting */
6742 /*-----------------------------------------------------------------*/
6744 genLeftShift (iCode * ic)
6746 operand *left, *right, *result;
6749 symbol *tlbl, *tlbl1;
6751 D(emitcode ("; genLeftShift",""));
6753 right = IC_RIGHT (ic);
6754 left = IC_LEFT (ic);
6755 result = IC_RESULT (ic);
6757 aopOp (right, ic, FALSE);
6759 /* if the shift count is known then do it
6760 as efficiently as possible */
6761 if (AOP_TYPE (right) == AOP_LIT)
6763 genLeftShiftLiteral (left, right, result, ic);
6767 /* shift count is unknown then we have to form
6768 a loop get the loop count in B : Note: we take
6769 only the lower order byte since shifting
6770 more that 32 bits make no sense anyway, ( the
6771 largest size of an object can be only 32 bits ) */
6773 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6774 emitcode ("inc", "b");
6775 freeAsmop (right, NULL, ic, TRUE);
6776 aopOp (left, ic, FALSE);
6777 aopOp (result, ic, FALSE);
6779 /* now move the left to the result if they are not the
6781 if (!sameRegs (AOP (left), AOP (result)) &&
6782 AOP_SIZE (result) > 1)
6785 size = AOP_SIZE (result);
6789 l = aopGet (AOP (left), offset, FALSE, TRUE);
6790 if (*l == '@' && (IS_AOP_PREG (result)))
6793 emitcode ("mov", "a,%s", l);
6794 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6797 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6802 tlbl = newiTempLabel (NULL);
6803 size = AOP_SIZE (result);
6805 tlbl1 = newiTempLabel (NULL);
6807 /* if it is only one byte then */
6810 symbol *tlbl1 = newiTempLabel (NULL);
6812 l = aopGet (AOP (left), 0, FALSE, FALSE);
6814 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6815 emitcode ("", "%05d$:", tlbl->key + 100);
6816 emitcode ("add", "a,acc");
6817 emitcode ("", "%05d$:", tlbl1->key + 100);
6818 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6819 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6823 reAdjustPreg (AOP (result));
6825 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6826 emitcode ("", "%05d$:", tlbl->key + 100);
6827 l = aopGet (AOP (result), offset, FALSE, FALSE);
6829 emitcode ("add", "a,acc");
6830 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6833 l = aopGet (AOP (result), offset, FALSE, FALSE);
6835 emitcode ("rlc", "a");
6836 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6838 reAdjustPreg (AOP (result));
6840 emitcode ("", "%05d$:", tlbl1->key + 100);
6841 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6843 freeAsmop (left, NULL, ic, TRUE);
6844 freeAsmop (result, NULL, ic, TRUE);
6847 /*-----------------------------------------------------------------*/
6848 /* genrshOne - right shift a one byte quantity by known count */
6849 /*-----------------------------------------------------------------*/
6851 genrshOne (operand * result, operand * left,
6852 int shCount, int sign)
6854 D(emitcode ("; genrshOne",""));
6856 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6859 /*-----------------------------------------------------------------*/
6860 /* genrshTwo - right shift two bytes by known amount != 0 */
6861 /*-----------------------------------------------------------------*/
6863 genrshTwo (operand * result, operand * left,
6864 int shCount, int sign)
6866 D(emitcode ("; genrshTwo",""));
6868 /* if shCount >= 8 */
6873 shiftR1Left2Result (left, MSB16, result, LSB,
6876 movLeft2Result (left, MSB16, result, LSB, sign);
6877 addSign (result, MSB16, sign);
6880 /* 1 <= shCount <= 7 */
6882 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6885 /*-----------------------------------------------------------------*/
6886 /* shiftRLong - shift right one long from left to result */
6887 /* offl = LSB or MSB16 */
6888 /*-----------------------------------------------------------------*/
6890 shiftRLong (operand * left, int offl,
6891 operand * result, int sign)
6893 int isSameRegs=sameRegs(AOP(left),AOP(result));
6895 if (isSameRegs && offl>1) {
6896 // we are in big trouble, but this shouldn't happen
6897 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6900 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6905 emitcode ("rlc", "a");
6906 emitcode ("subb", "a,acc");
6908 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6910 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6911 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6914 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6919 emitcode ("clr", "c");
6921 emitcode ("mov", "c,acc.7");
6924 emitcode ("rrc", "a");
6926 if (isSameRegs && offl==MSB16) {
6927 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6929 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6930 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6933 emitcode ("rrc", "a");
6934 if (isSameRegs && offl==1) {
6935 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6937 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6938 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6940 emitcode ("rrc", "a");
6941 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6945 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6946 emitcode ("rrc", "a");
6947 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6951 /*-----------------------------------------------------------------*/
6952 /* genrshFour - shift four byte by a known amount != 0 */
6953 /*-----------------------------------------------------------------*/
6955 genrshFour (operand * result, operand * left,
6956 int shCount, int sign)
6958 D(emitcode ("; genrshFour",""));
6960 /* if shifting more that 3 bytes */
6965 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6967 movLeft2Result (left, MSB32, result, LSB, sign);
6968 addSign (result, MSB16, sign);
6970 else if (shCount >= 16)
6974 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6977 movLeft2Result (left, MSB24, result, LSB, 0);
6978 movLeft2Result (left, MSB32, result, MSB16, sign);
6980 addSign (result, MSB24, sign);
6982 else if (shCount >= 8)
6986 shiftRLong (left, MSB16, result, sign);
6987 else if (shCount == 0)
6989 movLeft2Result (left, MSB16, result, LSB, 0);
6990 movLeft2Result (left, MSB24, result, MSB16, 0);
6991 movLeft2Result (left, MSB32, result, MSB24, sign);
6992 addSign (result, MSB32, sign);
6996 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6997 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6998 /* the last shift is signed */
6999 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7000 addSign (result, MSB32, sign);
7004 { /* 1 <= shCount <= 7 */
7007 shiftRLong (left, LSB, result, sign);
7009 shiftRLong (result, LSB, result, sign);
7013 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7014 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7015 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7020 /*-----------------------------------------------------------------*/
7021 /* genRightShiftLiteral - right shifting by known count */
7022 /*-----------------------------------------------------------------*/
7024 genRightShiftLiteral (operand * left,
7030 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7033 D(emitcode ("; genRightShiftLiteral",""));
7035 freeAsmop (right, NULL, ic, TRUE);
7037 aopOp (left, ic, FALSE);
7038 aopOp (result, ic, FALSE);
7041 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7045 size = getDataSize (left);
7046 /* test the LEFT size !!! */
7048 /* I suppose that the left size >= result size */
7051 size = getDataSize (result);
7053 movLeft2Result (left, size, result, size, 0);
7056 else if (shCount >= (size * 8))
7059 /* get sign in acc.7 */
7060 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7062 addSign (result, LSB, sign);
7069 genrshOne (result, left, shCount, sign);
7073 genrshTwo (result, left, shCount, sign);
7077 genrshFour (result, left, shCount, sign);
7083 freeAsmop (left, NULL, ic, TRUE);
7084 freeAsmop (result, NULL, ic, TRUE);
7087 /*-----------------------------------------------------------------*/
7088 /* genSignedRightShift - right shift of signed number */
7089 /*-----------------------------------------------------------------*/
7091 genSignedRightShift (iCode * ic)
7093 operand *right, *left, *result;
7096 symbol *tlbl, *tlbl1;
7098 D(emitcode ("; genSignedRightShift",""));
7100 /* we do it the hard way put the shift count in b
7101 and loop thru preserving the sign */
7103 right = IC_RIGHT (ic);
7104 left = IC_LEFT (ic);
7105 result = IC_RESULT (ic);
7107 aopOp (right, ic, FALSE);
7110 if (AOP_TYPE (right) == AOP_LIT)
7112 genRightShiftLiteral (left, right, result, ic, 1);
7115 /* shift count is unknown then we have to form
7116 a loop get the loop count in B : Note: we take
7117 only the lower order byte since shifting
7118 more that 32 bits make no sense anyway, ( the
7119 largest size of an object can be only 32 bits ) */
7121 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7122 emitcode ("inc", "b");
7123 freeAsmop (right, NULL, ic, TRUE);
7124 aopOp (left, ic, FALSE);
7125 aopOp (result, ic, FALSE);
7127 /* now move the left to the result if they are not the
7129 if (!sameRegs (AOP (left), AOP (result)) &&
7130 AOP_SIZE (result) > 1)
7133 size = AOP_SIZE (result);
7137 l = aopGet (AOP (left), offset, FALSE, TRUE);
7138 if (*l == '@' && IS_AOP_PREG (result))
7141 emitcode ("mov", "a,%s", l);
7142 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7145 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7150 /* mov the highest order bit to OVR */
7151 tlbl = newiTempLabel (NULL);
7152 tlbl1 = newiTempLabel (NULL);
7154 size = AOP_SIZE (result);
7156 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7157 emitcode ("rlc", "a");
7158 emitcode ("mov", "ov,c");
7159 /* if it is only one byte then */
7162 l = aopGet (AOP (left), 0, FALSE, FALSE);
7164 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7165 emitcode ("", "%05d$:", tlbl->key + 100);
7166 emitcode ("mov", "c,ov");
7167 emitcode ("rrc", "a");
7168 emitcode ("", "%05d$:", tlbl1->key + 100);
7169 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7170 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7174 reAdjustPreg (AOP (result));
7175 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7176 emitcode ("", "%05d$:", tlbl->key + 100);
7177 emitcode ("mov", "c,ov");
7180 l = aopGet (AOP (result), offset, FALSE, FALSE);
7182 emitcode ("rrc", "a");
7183 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7185 reAdjustPreg (AOP (result));
7186 emitcode ("", "%05d$:", tlbl1->key + 100);
7187 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7190 freeAsmop (left, NULL, ic, TRUE);
7191 freeAsmop (result, NULL, ic, TRUE);
7194 /*-----------------------------------------------------------------*/
7195 /* genRightShift - generate code for right shifting */
7196 /*-----------------------------------------------------------------*/
7198 genRightShift (iCode * ic)
7200 operand *right, *left, *result;
7204 symbol *tlbl, *tlbl1;
7206 D(emitcode ("; genRightShift",""));
7208 /* if signed then we do it the hard way preserve the
7209 sign bit moving it inwards */
7210 letype = getSpec (operandType (IC_LEFT (ic)));
7212 if (!SPEC_USIGN (letype))
7214 genSignedRightShift (ic);
7218 /* signed & unsigned types are treated the same : i.e. the
7219 signed is NOT propagated inwards : quoting from the
7220 ANSI - standard : "for E1 >> E2, is equivalent to division
7221 by 2**E2 if unsigned or if it has a non-negative value,
7222 otherwise the result is implementation defined ", MY definition
7223 is that the sign does not get propagated */
7225 right = IC_RIGHT (ic);
7226 left = IC_LEFT (ic);
7227 result = IC_RESULT (ic);
7229 aopOp (right, ic, FALSE);
7231 /* if the shift count is known then do it
7232 as efficiently as possible */
7233 if (AOP_TYPE (right) == AOP_LIT)
7235 genRightShiftLiteral (left, right, result, ic, 0);
7239 /* shift count is unknown then we have to form
7240 a loop get the loop count in B : Note: we take
7241 only the lower order byte since shifting
7242 more that 32 bits make no sense anyway, ( the
7243 largest size of an object can be only 32 bits ) */
7245 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7246 emitcode ("inc", "b");
7247 freeAsmop (right, NULL, ic, TRUE);
7248 aopOp (left, ic, FALSE);
7249 aopOp (result, ic, FALSE);
7251 /* now move the left to the result if they are not the
7253 if (!sameRegs (AOP (left), AOP (result)) &&
7254 AOP_SIZE (result) > 1)
7257 size = AOP_SIZE (result);
7261 l = aopGet (AOP (left), offset, FALSE, TRUE);
7262 if (*l == '@' && IS_AOP_PREG (result))
7265 emitcode ("mov", "a,%s", l);
7266 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7269 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7274 tlbl = newiTempLabel (NULL);
7275 tlbl1 = newiTempLabel (NULL);
7276 size = AOP_SIZE (result);
7279 /* if it is only one byte then */
7282 l = aopGet (AOP (left), 0, FALSE, FALSE);
7284 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7285 emitcode ("", "%05d$:", tlbl->key + 100);
7287 emitcode ("rrc", "a");
7288 emitcode ("", "%05d$:", tlbl1->key + 100);
7289 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7290 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7294 reAdjustPreg (AOP (result));
7295 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7296 emitcode ("", "%05d$:", tlbl->key + 100);
7300 l = aopGet (AOP (result), offset, FALSE, FALSE);
7302 emitcode ("rrc", "a");
7303 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7305 reAdjustPreg (AOP (result));
7307 emitcode ("", "%05d$:", tlbl1->key + 100);
7308 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7311 freeAsmop (left, NULL, ic, TRUE);
7312 freeAsmop (result, NULL, ic, TRUE);
7315 /*-----------------------------------------------------------------*/
7316 /* emitPtrByteGet - emits code to get a byte into A through a */
7317 /* pointer register (R0, R1, or DPTR). The */
7318 /* original value of A can be preserved in B. */
7319 /*-----------------------------------------------------------------*/
7321 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7328 emitcode ("mov", "b,a");
7329 emitcode ("mov", "a,@%s", rname);
7334 emitcode ("mov", "b,a");
7335 emitcode ("movx", "a,@%s", rname);
7340 emitcode ("mov", "b,a");
7341 emitcode ("movx", "a,@dptr");
7346 emitcode ("mov", "b,a");
7347 emitcode ("clr", "a");
7348 emitcode ("movc", "a,@a+dptr");
7354 emitcode ("push", "b");
7355 emitcode ("push", "acc");
7357 emitcode ("lcall", "__gptrget");
7359 emitcode ("pop", "b");
7364 /*-----------------------------------------------------------------*/
7365 /* emitPtrByteSet - emits code to set a byte from src through a */
7366 /* pointer register (R0, R1, or DPTR). */
7367 /*-----------------------------------------------------------------*/
7369 emitPtrByteSet (char *rname, int p_type, char *src)
7378 emitcode ("mov", "@%s,a", rname);
7381 emitcode ("mov", "@%s,%s", rname, src);
7386 emitcode ("movx", "@%s,a", rname);
7391 emitcode ("movx", "@dptr,a");
7396 emitcode ("lcall", "__gptrput");
7401 /*-----------------------------------------------------------------*/
7402 /* genUnpackBits - generates code for unpacking bits */
7403 /*-----------------------------------------------------------------*/
7405 genUnpackBits (operand * result, char *rname, int ptype)
7407 int offset = 0; /* result byte offset */
7408 int rsize; /* result size */
7409 int rlen = 0; /* remaining bitfield length */
7410 sym_link *etype; /* bitfield type information */
7411 int blen; /* bitfield length */
7412 int bstr; /* bitfield starting bit within byte */
7414 D(emitcode ("; genUnpackBits",""));
7416 etype = getSpec (operandType (result));
7417 rsize = getSize (operandType (result));
7418 blen = SPEC_BLEN (etype);
7419 bstr = SPEC_BSTR (etype);
7421 /* If the bitfield length is less than a byte */
7424 emitPtrByteGet (rname, ptype, FALSE);
7426 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7427 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7431 /* Bit field did not fit in a byte. Copy all
7432 but the partial byte at the end. */
7433 for (rlen=blen;rlen>=8;rlen-=8)
7435 emitPtrByteGet (rname, ptype, FALSE);
7436 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7438 emitcode ("inc", "%s", rname);
7441 /* Handle the partial byte at the end */
7444 emitPtrByteGet (rname, ptype, FALSE);
7445 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7446 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7454 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7459 /*-----------------------------------------------------------------*/
7460 /* genDataPointerGet - generates code when ptr offset is known */
7461 /*-----------------------------------------------------------------*/
7463 genDataPointerGet (operand * left,
7469 int size, offset = 0;
7471 D(emitcode ("; genDataPointerGet",""));
7473 aopOp (result, ic, TRUE);
7475 /* get the string representation of the name */
7476 l = aopGet (AOP (left), 0, FALSE, TRUE);
7477 size = AOP_SIZE (result);
7481 sprintf (buffer, "(%s + %d)", l + 1, offset);
7483 sprintf (buffer, "%s", l + 1);
7484 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7487 freeAsmop (left, NULL, ic, TRUE);
7488 freeAsmop (result, NULL, ic, TRUE);
7491 /*-----------------------------------------------------------------*/
7492 /* genNearPointerGet - emitcode for near pointer fetch */
7493 /*-----------------------------------------------------------------*/
7495 genNearPointerGet (operand * left,
7503 sym_link *rtype, *retype;
7504 sym_link *ltype = operandType (left);
7507 D(emitcode ("; genNearPointerGet",""));
7509 rtype = operandType (result);
7510 retype = getSpec (rtype);
7512 aopOp (left, ic, FALSE);
7514 /* if left is rematerialisable and
7515 result is not bit variable type and
7516 the left is pointer to data space i.e
7517 lower 128 bytes of space */
7518 if (AOP_TYPE (left) == AOP_IMMD &&
7519 !IS_BITVAR (retype) &&
7520 DCL_TYPE (ltype) == POINTER)
7522 genDataPointerGet (left, result, ic);
7526 /* if the value is already in a pointer register
7527 then don't need anything more */
7528 if (!AOP_INPREG (AOP (left)))
7530 if (IS_AOP_PREG (left))
7532 // Aha, it is a pointer, just in disguise.
7533 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7536 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7537 __FILE__, __LINE__);
7542 emitcode ("mov", "a%s,%s", rname + 1, rname);
7543 rname++; // skip the '@'.
7548 /* otherwise get a free pointer register */
7550 preg = getFreePtr (ic, &aop, FALSE);
7551 emitcode ("mov", "%s,%s",
7553 aopGet (AOP (left), 0, FALSE, TRUE));
7558 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7560 //aopOp (result, ic, FALSE);
7561 aopOp (result, ic, result?TRUE:FALSE);
7563 /* if bitfield then unpack the bits */
7564 if (IS_BITVAR (retype))
7565 genUnpackBits (result, rname, POINTER);
7568 /* we have can just get the values */
7569 int size = AOP_SIZE (result);
7574 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7577 emitcode ("mov", "a,@%s", rname);
7578 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7582 sprintf (buffer, "@%s", rname);
7583 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7587 emitcode ("inc", "%s", rname);
7591 /* now some housekeeping stuff */
7592 if (aop) /* we had to allocate for this iCode */
7594 if (pi) { /* post increment present */
7595 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7597 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7601 /* we did not allocate which means left
7602 already in a pointer register, then
7603 if size > 0 && this could be used again
7604 we have to point it back to where it
7606 if ((AOP_SIZE (result) > 1 &&
7607 !OP_SYMBOL (left)->remat &&
7608 (OP_SYMBOL (left)->liveTo > ic->seq ||
7612 int size = AOP_SIZE (result) - 1;
7614 emitcode ("dec", "%s", rname);
7619 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7620 freeAsmop (left, NULL, ic, TRUE);
7621 if (pi) pi->generated = 1;
7624 /*-----------------------------------------------------------------*/
7625 /* genPagedPointerGet - emitcode for paged pointer fetch */
7626 /*-----------------------------------------------------------------*/
7628 genPagedPointerGet (operand * left,
7636 sym_link *rtype, *retype;
7638 D(emitcode ("; genPagedPointerGet",""));
7640 rtype = operandType (result);
7641 retype = getSpec (rtype);
7643 aopOp (left, ic, FALSE);
7645 /* if the value is already in a pointer register
7646 then don't need anything more */
7647 if (!AOP_INPREG (AOP (left)))
7649 /* otherwise get a free pointer register */
7651 preg = getFreePtr (ic, &aop, FALSE);
7652 emitcode ("mov", "%s,%s",
7654 aopGet (AOP (left), 0, FALSE, TRUE));
7658 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7660 aopOp (result, ic, FALSE);
7662 /* if bitfield then unpack the bits */
7663 if (IS_BITVAR (retype))
7664 genUnpackBits (result, rname, PPOINTER);
7667 /* we have can just get the values */
7668 int size = AOP_SIZE (result);
7674 emitcode ("movx", "a,@%s", rname);
7675 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7680 emitcode ("inc", "%s", rname);
7684 /* now some housekeeping stuff */
7685 if (aop) /* we had to allocate for this iCode */
7687 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7688 freeAsmop (NULL, aop, ic, TRUE);
7692 /* we did not allocate which means left
7693 already in a pointer register, then
7694 if size > 0 && this could be used again
7695 we have to point it back to where it
7697 if ((AOP_SIZE (result) > 1 &&
7698 !OP_SYMBOL (left)->remat &&
7699 (OP_SYMBOL (left)->liveTo > ic->seq ||
7703 int size = AOP_SIZE (result) - 1;
7705 emitcode ("dec", "%s", rname);
7710 freeAsmop (left, NULL, ic, TRUE);
7711 freeAsmop (result, NULL, ic, TRUE);
7712 if (pi) pi->generated = 1;
7716 /*--------------------------------------------------------------------*/
7717 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7718 /*--------------------------------------------------------------------*/
7720 loadDptrFromOperand (operand *op, bool loadBToo)
7722 if (AOP_TYPE (op) != AOP_STR)
7724 /* if this is remateriazable */
7725 if (AOP_TYPE (op) == AOP_IMMD)
7727 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7730 if (AOP(op)->aopu.aop_immd.from_cast_remat)
7731 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7734 wassertl(FALSE, "need pointerCode");
7735 emitcode ("", "; mov b,???");
7736 /* genPointerGet and genPointerSet originally did different
7737 ** things for this case. Both seem wrong.
7738 ** from genPointerGet:
7739 ** emitcode ("mov", "b,#%d", pointerCode (retype));
7740 ** from genPointerSet:
7741 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7746 else if (AOP_TYPE (op) == AOP_DPTR)
7750 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7751 emitcode ("push", "acc");
7752 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7753 emitcode ("push", "acc");
7754 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7755 emitcode ("pop", "dph");
7756 emitcode ("pop", "dpl");
7760 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7761 emitcode ("push", "acc");
7762 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7763 emitcode ("pop", "dpl");
7767 { /* we need to get it byte by byte */
7768 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7769 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7771 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7776 /*-----------------------------------------------------------------*/
7777 /* genFarPointerGet - gget value from far space */
7778 /*-----------------------------------------------------------------*/
7780 genFarPointerGet (operand * left,
7781 operand * result, iCode * ic, iCode * pi)
7784 sym_link *retype = getSpec (operandType (result));
7786 D(emitcode ("; genFarPointerGet",""));
7788 aopOp (left, ic, FALSE);
7789 loadDptrFromOperand (left, FALSE);
7791 /* so dptr now contains the address */
7792 aopOp (result, ic, FALSE);
7794 /* if bit then unpack */
7795 if (IS_BITVAR (retype))
7796 genUnpackBits (result, "dptr", FPOINTER);
7799 size = AOP_SIZE (result);
7804 emitcode ("movx", "a,@dptr");
7805 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7807 emitcode ("inc", "dptr");
7811 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7812 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7813 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7816 freeAsmop (left, NULL, ic, TRUE);
7817 freeAsmop (result, NULL, ic, TRUE);
7820 /*-----------------------------------------------------------------*/
7821 /* genCodePointerGet - gget value from code space */
7822 /*-----------------------------------------------------------------*/
7824 genCodePointerGet (operand * left,
7825 operand * result, iCode * ic, iCode *pi)
7828 sym_link *retype = getSpec (operandType (result));
7830 D(emitcode ("; genCodePointerGet",""));
7832 aopOp (left, ic, FALSE);
7833 loadDptrFromOperand (left, FALSE);
7835 /* so dptr now contains the address */
7836 aopOp (result, ic, FALSE);
7838 /* if bit then unpack */
7839 if (IS_BITVAR (retype))
7840 genUnpackBits (result, "dptr", CPOINTER);
7843 size = AOP_SIZE (result);
7850 emitcode ("clr", "a");
7851 emitcode ("movc", "a,@a+dptr");
7852 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7853 emitcode ("inc", "dptr");
7857 emitcode ("mov", "a,#0x%02x", offset);
7858 emitcode ("movc", "a,@a+dptr");
7859 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7864 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7865 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7866 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7869 freeAsmop (left, NULL, ic, TRUE);
7870 freeAsmop (result, NULL, ic, TRUE);
7873 /*-----------------------------------------------------------------*/
7874 /* genGenPointerGet - gget value from generic pointer space */
7875 /*-----------------------------------------------------------------*/
7877 genGenPointerGet (operand * left,
7878 operand * result, iCode * ic, iCode *pi)
7881 sym_link *retype = getSpec (operandType (result));
7883 D(emitcode ("; genGenPointerGet",""));
7885 aopOp (left, ic, FALSE);
7886 loadDptrFromOperand (left, TRUE);
7888 /* so dptr know contains the address */
7889 aopOp (result, ic, FALSE);
7891 /* if bit then unpack */
7892 if (IS_BITVAR (retype))
7893 genUnpackBits (result, "dptr", GPOINTER);
7896 size = AOP_SIZE (result);
7901 emitcode ("lcall", "__gptrget");
7902 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7904 emitcode ("inc", "dptr");
7908 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7909 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7910 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7913 freeAsmop (left, NULL, ic, TRUE);
7914 freeAsmop (result, NULL, ic, TRUE);
7917 /*-----------------------------------------------------------------*/
7918 /* genPointerGet - generate code for pointer get */
7919 /*-----------------------------------------------------------------*/
7921 genPointerGet (iCode * ic, iCode *pi)
7923 operand *left, *result;
7924 sym_link *type, *etype;
7927 D(emitcode ("; genPointerGet",""));
7929 left = IC_LEFT (ic);
7930 result = IC_RESULT (ic);
7932 /* depending on the type of pointer we need to
7933 move it to the correct pointer register */
7934 type = operandType (left);
7935 etype = getSpec (type);
7936 /* if left is of type of pointer then it is simple */
7937 if (IS_PTR (type) && !IS_FUNC (type->next))
7938 p_type = DCL_TYPE (type);
7941 /* we have to go by the storage class */
7942 p_type = PTR_TYPE (SPEC_OCLS (etype));
7945 /* special case when cast remat */
7946 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7947 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7948 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7949 type = operandType (left);
7950 p_type = DCL_TYPE (type);
7952 /* now that we have the pointer type we assign
7953 the pointer values */
7959 genNearPointerGet (left, result, ic, pi);
7963 genPagedPointerGet (left, result, ic, pi);
7967 genFarPointerGet (left, result, ic, pi);
7971 genCodePointerGet (left, result, ic, pi);
7975 genGenPointerGet (left, result, ic, pi);
7983 /*-----------------------------------------------------------------*/
7984 /* genPackBits - generates code for packed bit storage */
7985 /*-----------------------------------------------------------------*/
7987 genPackBits (sym_link * etype,
7989 char *rname, int p_type)
7991 int offset = 0; /* source byte offset */
7992 int rlen = 0; /* remaining bitfield length */
7993 int blen; /* bitfield length */
7994 int bstr; /* bitfield starting bit within byte */
7995 int litval; /* source literal value (if AOP_LIT) */
7996 unsigned char mask; /* bitmask within current byte */
7998 D(emitcode ("; genPackBits",""));
8000 blen = SPEC_BLEN (etype);
8001 bstr = SPEC_BSTR (etype);
8003 /* If the bitfield length is less than a byte */
8006 mask = ((unsigned char) (0xFF << (blen + bstr)) |
8007 (unsigned char) (0xFF >> (8 - bstr)));
8009 if (AOP_TYPE (right) == AOP_LIT)
8011 /* Case with a bitfield length <8 and literal source
8013 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8015 litval &= (~mask) & 0xff;
8016 emitPtrByteGet (rname, p_type, FALSE);
8017 if ((mask|litval)!=0xff)
8018 emitcode ("anl","a,#0x%02x", mask);
8020 emitcode ("orl","a,#0x%02x", litval);
8024 if ((blen==1) && (p_type!=GPOINTER))
8026 /* Case with a bitfield length == 1 and no generic pointer
8028 if (AOP_TYPE (right) == AOP_CRY)
8029 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
8032 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8033 emitcode ("rrc","a");
8035 emitPtrByteGet (rname, p_type, FALSE);
8036 emitcode ("mov","acc.%d,c",bstr);
8040 /* Case with a bitfield length < 8 and arbitrary source
8042 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8043 /* shift and mask source value */
8045 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8047 /* transfer A to B and get next byte */
8048 emitPtrByteGet (rname, p_type, TRUE);
8050 emitcode ("anl", "a,#0x%02x", mask);
8051 emitcode ("orl", "a,b");
8052 if (p_type == GPOINTER)
8053 emitcode ("pop", "b");
8057 emitPtrByteSet (rname, p_type, "a");
8061 /* Bit length is greater than 7 bits. In this case, copy */
8062 /* all except the partial byte at the end */
8063 for (rlen=blen;rlen>=8;rlen-=8)
8065 emitPtrByteSet (rname, p_type,
8066 aopGet (AOP (right), offset++, FALSE, TRUE) );
8068 emitcode ("inc", "%s", rname);
8071 /* If there was a partial byte at the end */
8074 mask = (((unsigned char) -1 << rlen) & 0xff);
8076 if (AOP_TYPE (right) == AOP_LIT)
8078 /* Case with partial byte and literal source
8080 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8081 litval >>= (blen-rlen);
8082 litval &= (~mask) & 0xff;
8083 emitPtrByteGet (rname, p_type, FALSE);
8084 if ((mask|litval)!=0xff)
8085 emitcode ("anl","a,#0x%02x", mask);
8087 emitcode ("orl","a,#0x%02x", litval);
8091 /* Case with partial byte and arbitrary source
8093 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8094 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8096 /* transfer A to B and get next byte */
8097 emitPtrByteGet (rname, p_type, TRUE);
8099 emitcode ("anl", "a,#0x%02x", mask);
8100 emitcode ("orl", "a,b");
8101 if (p_type == GPOINTER)
8102 emitcode ("pop", "b");
8104 emitPtrByteSet (rname, p_type, "a");
8110 /*-----------------------------------------------------------------*/
8111 /* genDataPointerSet - remat pointer to data space */
8112 /*-----------------------------------------------------------------*/
8114 genDataPointerSet (operand * right,
8118 int size, offset = 0;
8119 char *l, buffer[256];
8121 D(emitcode ("; genDataPointerSet",""));
8123 aopOp (right, ic, FALSE);
8125 l = aopGet (AOP (result), 0, FALSE, TRUE);
8126 size = AOP_SIZE (right);
8130 sprintf (buffer, "(%s + %d)", l + 1, offset);
8132 sprintf (buffer, "%s", l + 1);
8133 emitcode ("mov", "%s,%s", buffer,
8134 aopGet (AOP (right), offset++, FALSE, FALSE));
8137 freeAsmop (right, NULL, ic, TRUE);
8138 freeAsmop (result, NULL, ic, TRUE);
8141 /*-----------------------------------------------------------------*/
8142 /* genNearPointerSet - emitcode for near pointer put */
8143 /*-----------------------------------------------------------------*/
8145 genNearPointerSet (operand * right,
8153 sym_link *retype, *letype;
8154 sym_link *ptype = operandType (result);
8156 D(emitcode ("; genNearPointerSet",""));
8158 retype = getSpec (operandType (right));
8159 letype = getSpec (ptype);
8160 aopOp (result, ic, FALSE);
8162 /* if the result is rematerializable &
8163 in data space & not a bit variable */
8164 if (AOP_TYPE (result) == AOP_IMMD &&
8165 DCL_TYPE (ptype) == POINTER &&
8166 !IS_BITVAR (retype) &&
8167 !IS_BITVAR (letype))
8169 genDataPointerSet (right, result, ic);
8173 /* if the value is already in a pointer register
8174 then don't need anything more */
8175 if (!AOP_INPREG (AOP (result)))
8178 //AOP_TYPE (result) == AOP_STK
8182 // Aha, it is a pointer, just in disguise.
8183 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8186 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8187 __FILE__, __LINE__);
8192 emitcode ("mov", "a%s,%s", rname + 1, rname);
8193 rname++; // skip the '@'.
8198 /* otherwise get a free pointer register */
8200 preg = getFreePtr (ic, &aop, FALSE);
8201 emitcode ("mov", "%s,%s",
8203 aopGet (AOP (result), 0, FALSE, TRUE));
8209 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8212 aopOp (right, ic, FALSE);
8214 /* if bitfield then unpack the bits */
8215 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8216 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8219 /* we have can just get the values */
8220 int size = AOP_SIZE (right);
8225 l = aopGet (AOP (right), offset, FALSE, TRUE);
8229 emitcode ("mov", "@%s,a", rname);
8232 emitcode ("mov", "@%s,%s", rname, l);
8234 emitcode ("inc", "%s", rname);
8239 /* now some housekeeping stuff */
8240 if (aop) /* we had to allocate for this iCode */
8243 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8244 freeAsmop (NULL, aop, ic, TRUE);
8248 /* we did not allocate which means left
8249 already in a pointer register, then
8250 if size > 0 && this could be used again
8251 we have to point it back to where it
8253 if ((AOP_SIZE (right) > 1 &&
8254 !OP_SYMBOL (result)->remat &&
8255 (OP_SYMBOL (result)->liveTo > ic->seq ||
8259 int size = AOP_SIZE (right) - 1;
8261 emitcode ("dec", "%s", rname);
8266 if (pi) pi->generated = 1;
8267 freeAsmop (result, NULL, ic, TRUE);
8268 freeAsmop (right, NULL, ic, TRUE);
8271 /*-----------------------------------------------------------------*/
8272 /* genPagedPointerSet - emitcode for Paged pointer put */
8273 /*-----------------------------------------------------------------*/
8275 genPagedPointerSet (operand * right,
8283 sym_link *retype, *letype;
8285 D(emitcode ("; genPagedPointerSet",""));
8287 retype = getSpec (operandType (right));
8288 letype = getSpec (operandType (result));
8290 aopOp (result, ic, FALSE);
8292 /* if the value is already in a pointer register
8293 then don't need anything more */
8294 if (!AOP_INPREG (AOP (result)))
8296 /* otherwise get a free pointer register */
8298 preg = getFreePtr (ic, &aop, FALSE);
8299 emitcode ("mov", "%s,%s",
8301 aopGet (AOP (result), 0, FALSE, TRUE));
8305 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8307 aopOp (right, ic, FALSE);
8309 /* if bitfield then unpack the bits */
8310 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8311 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8314 /* we have can just get the values */
8315 int size = AOP_SIZE (right);
8320 l = aopGet (AOP (right), offset, FALSE, TRUE);
8323 emitcode ("movx", "@%s,a", rname);
8326 emitcode ("inc", "%s", rname);
8332 /* now some housekeeping stuff */
8333 if (aop) /* we had to allocate for this iCode */
8336 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8337 freeAsmop (NULL, aop, ic, TRUE);
8341 /* we did not allocate which means left
8342 already in a pointer register, then
8343 if size > 0 && this could be used again
8344 we have to point it back to where it
8346 if (AOP_SIZE (right) > 1 &&
8347 !OP_SYMBOL (result)->remat &&
8348 (OP_SYMBOL (result)->liveTo > ic->seq ||
8351 int size = AOP_SIZE (right) - 1;
8353 emitcode ("dec", "%s", rname);
8358 if (pi) pi->generated = 1;
8359 freeAsmop (result, NULL, ic, TRUE);
8360 freeAsmop (right, NULL, ic, TRUE);
8365 /*-----------------------------------------------------------------*/
8366 /* genFarPointerSet - set value from far space */
8367 /*-----------------------------------------------------------------*/
8369 genFarPointerSet (operand * right,
8370 operand * result, iCode * ic, iCode * pi)
8373 sym_link *retype = getSpec (operandType (right));
8374 sym_link *letype = getSpec (operandType (result));
8376 D(emitcode ("; genFarPointerSet",""));
8378 aopOp (result, ic, FALSE);
8379 loadDptrFromOperand (result, FALSE);
8381 /* so dptr know contains the address */
8382 aopOp (right, ic, FALSE);
8384 /* if bit then unpack */
8385 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8386 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8389 size = AOP_SIZE (right);
8394 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8396 emitcode ("movx", "@dptr,a");
8398 emitcode ("inc", "dptr");
8401 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8402 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8403 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8406 freeAsmop (result, NULL, ic, TRUE);
8407 freeAsmop (right, NULL, ic, TRUE);
8410 /*-----------------------------------------------------------------*/
8411 /* genGenPointerSet - set value from generic pointer space */
8412 /*-----------------------------------------------------------------*/
8414 genGenPointerSet (operand * right,
8415 operand * result, iCode * ic, iCode * pi)
8418 sym_link *retype = getSpec (operandType (right));
8419 sym_link *letype = getSpec (operandType (result));
8421 D(emitcode ("; genGenPointerSet",""));
8423 aopOp (result, ic, FALSE);
8424 loadDptrFromOperand (result, TRUE);
8426 /* so dptr know contains the address */
8427 aopOp (right, ic, FALSE);
8429 /* if bit then unpack */
8430 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8431 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8434 size = AOP_SIZE (right);
8439 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8441 emitcode ("lcall", "__gptrput");
8443 emitcode ("inc", "dptr");
8447 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8448 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8449 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8452 freeAsmop (result, NULL, ic, TRUE);
8453 freeAsmop (right, NULL, ic, TRUE);
8456 /*-----------------------------------------------------------------*/
8457 /* genPointerSet - stores the value into a pointer location */
8458 /*-----------------------------------------------------------------*/
8460 genPointerSet (iCode * ic, iCode *pi)
8462 operand *right, *result;
8463 sym_link *type, *etype;
8466 D(emitcode ("; genPointerSet",""));
8468 right = IC_RIGHT (ic);
8469 result = IC_RESULT (ic);
8471 /* depending on the type of pointer we need to
8472 move it to the correct pointer register */
8473 type = operandType (result);
8474 etype = getSpec (type);
8475 /* if left is of type of pointer then it is simple */
8476 if (IS_PTR (type) && !IS_FUNC (type->next))
8478 p_type = DCL_TYPE (type);
8482 /* we have to go by the storage class */
8483 p_type = PTR_TYPE (SPEC_OCLS (etype));
8486 /* special case when cast remat */
8487 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8488 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8489 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8490 type = operandType (result);
8491 p_type = DCL_TYPE (type);
8493 /* now that we have the pointer type we assign
8494 the pointer values */
8500 genNearPointerSet (right, result, ic, pi);
8504 genPagedPointerSet (right, result, ic, pi);
8508 genFarPointerSet (right, result, ic, pi);
8512 genGenPointerSet (right, result, ic, pi);
8516 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8517 "genPointerSet: illegal pointer type");
8522 /*-----------------------------------------------------------------*/
8523 /* genIfx - generate code for Ifx statement */
8524 /*-----------------------------------------------------------------*/
8526 genIfx (iCode * ic, iCode * popIc)
8528 operand *cond = IC_COND (ic);
8531 D(emitcode ("; genIfx",""));
8533 aopOp (cond, ic, FALSE);
8535 /* get the value into acc */
8536 if (AOP_TYPE (cond) != AOP_CRY)
8540 /* the result is now in the accumulator */
8541 freeAsmop (cond, NULL, ic, TRUE);
8543 /* if there was something to be popped then do it */
8547 /* if the condition is a bit variable */
8548 if (isbit && IS_ITEMP (cond) &&
8550 genIfxJump (ic, SPIL_LOC (cond)->rname);
8551 else if (isbit && !IS_ITEMP (cond))
8552 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8554 genIfxJump (ic, "a");
8559 /*-----------------------------------------------------------------*/
8560 /* genAddrOf - generates code for address of */
8561 /*-----------------------------------------------------------------*/
8563 genAddrOf (iCode * ic)
8565 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8568 D(emitcode ("; genAddrOf",""));
8570 aopOp (IC_RESULT (ic), ic, FALSE);
8572 /* if the operand is on the stack then we
8573 need to get the stack offset of this
8577 /* if it has an offset then we need to compute
8581 emitcode ("mov", "a,_bp");
8582 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8583 ((char) (sym->stack - _G.nRegsSaved)) :
8584 ((char) sym->stack)) & 0xff);
8585 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8589 /* we can just move _bp */
8590 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8592 /* fill the result with zero */
8593 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8598 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8604 /* object not on stack then we need the name */
8605 size = AOP_SIZE (IC_RESULT (ic));
8610 char s[SDCC_NAME_MAX];
8612 sprintf (s, "#(%s >> %d)",
8616 sprintf (s, "#%s", sym->rname);
8617 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8621 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8625 /*-----------------------------------------------------------------*/
8626 /* genFarFarAssign - assignment when both are in far space */
8627 /*-----------------------------------------------------------------*/
8629 genFarFarAssign (operand * result, operand * right, iCode * ic)
8631 int size = AOP_SIZE (right);
8635 D(emitcode ("; genFarFarAssign",""));
8637 /* first push the right side on to the stack */
8640 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8642 emitcode ("push", "acc");
8645 freeAsmop (right, NULL, ic, FALSE);
8646 /* now assign DPTR to result */
8647 aopOp (result, ic, FALSE);
8648 size = AOP_SIZE (result);
8651 emitcode ("pop", "acc");
8652 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8654 freeAsmop (result, NULL, ic, FALSE);
8658 /*-----------------------------------------------------------------*/
8659 /* genAssign - generate code for assignment */
8660 /*-----------------------------------------------------------------*/
8662 genAssign (iCode * ic)
8664 operand *result, *right;
8666 unsigned long lit = 0L;
8668 D(emitcode("; genAssign",""));
8670 result = IC_RESULT (ic);
8671 right = IC_RIGHT (ic);
8673 /* if they are the same */
8674 if (operandsEqu (result, right) &&
8675 !isOperandVolatile (result, FALSE) &&
8676 !isOperandVolatile (right, FALSE))
8679 aopOp (right, ic, FALSE);
8681 /* special case both in far space */
8682 if (AOP_TYPE (right) == AOP_DPTR &&
8683 IS_TRUE_SYMOP (result) &&
8684 isOperandInFarSpace (result))
8687 genFarFarAssign (result, right, ic);
8691 aopOp (result, ic, TRUE);
8693 /* if they are the same registers */
8694 if (sameRegs (AOP (right), AOP (result)) &&
8695 !isOperandVolatile (result, FALSE) &&
8696 !isOperandVolatile (right, FALSE))
8699 /* if the result is a bit */
8700 if (AOP_TYPE (result) == AOP_CRY)
8703 /* if the right size is a literal then
8704 we know what the value is */
8705 if (AOP_TYPE (right) == AOP_LIT)
8707 if (((int) operandLitValue (right)))
8708 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8710 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8714 /* the right is also a bit variable */
8715 if (AOP_TYPE (right) == AOP_CRY)
8717 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8718 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8724 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8728 /* bit variables done */
8730 size = AOP_SIZE (result);
8732 if (AOP_TYPE (right) == AOP_LIT)
8733 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8735 (AOP_TYPE (result) != AOP_REG) &&
8736 (AOP_TYPE (right) == AOP_LIT) &&
8737 !IS_FLOAT (operandType (right)) &&
8740 emitcode ("clr", "a");
8743 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8744 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8746 aopPut (AOP (result),
8747 aopGet (AOP (right), size, FALSE, FALSE),
8749 isOperandVolatile (result, FALSE));
8756 aopPut (AOP (result),
8757 aopGet (AOP (right), offset, FALSE, FALSE),
8759 isOperandVolatile (result, FALSE));
8765 freeAsmop (right, NULL, ic, TRUE);
8766 freeAsmop (result, NULL, ic, TRUE);
8769 /*-----------------------------------------------------------------*/
8770 /* genJumpTab - genrates code for jump table */
8771 /*-----------------------------------------------------------------*/
8773 genJumpTab (iCode * ic)
8778 D(emitcode ("; genJumpTab",""));
8780 aopOp (IC_JTCOND (ic), ic, FALSE);
8781 /* get the condition into accumulator */
8782 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8784 /* multiply by three */
8785 emitcode ("add", "a,acc");
8786 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8787 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8789 jtab = newiTempLabel (NULL);
8790 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8791 emitcode ("jmp", "@a+dptr");
8792 emitcode ("", "%05d$:", jtab->key + 100);
8793 /* now generate the jump labels */
8794 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8795 jtab = setNextItem (IC_JTLABELS (ic)))
8796 emitcode ("ljmp", "%05d$", jtab->key + 100);
8800 /*-----------------------------------------------------------------*/
8801 /* genCast - gen code for casting */
8802 /*-----------------------------------------------------------------*/
8804 genCast (iCode * ic)
8806 operand *result = IC_RESULT (ic);
8807 sym_link *ctype = operandType (IC_LEFT (ic));
8808 sym_link *rtype = operandType (IC_RIGHT (ic));
8809 operand *right = IC_RIGHT (ic);
8812 D(emitcode("; genCast",""));
8814 /* if they are equivalent then do nothing */
8815 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8818 aopOp (right, ic, FALSE);
8819 aopOp (result, ic, FALSE);
8821 /* if the result is a bit (and not a bitfield) */
8822 // if (AOP_TYPE (result) == AOP_CRY)
8823 if (IS_BITVAR (OP_SYMBOL (result)->type)
8824 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8826 /* if the right size is a literal then
8827 we know what the value is */
8828 if (AOP_TYPE (right) == AOP_LIT)
8830 if (((int) operandLitValue (right)))
8831 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8833 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8838 /* the right is also a bit variable */
8839 if (AOP_TYPE (right) == AOP_CRY)
8841 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8842 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8848 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8853 /* if they are the same size : or less */
8854 if (AOP_SIZE (result) <= AOP_SIZE (right))
8857 /* if they are in the same place */
8858 if (sameRegs (AOP (right), AOP (result)))
8861 /* if they in different places then copy */
8862 size = AOP_SIZE (result);
8866 aopPut (AOP (result),
8867 aopGet (AOP (right), offset, FALSE, FALSE),
8869 isOperandVolatile (result, FALSE));
8876 /* if the result is of type pointer */
8881 sym_link *type = operandType (right);
8882 sym_link *etype = getSpec (type);
8884 /* pointer to generic pointer */
8885 if (IS_GENPTR (ctype))
8888 p_type = DCL_TYPE (type);
8891 if (SPEC_SCLS(etype)==S_REGISTER) {
8892 // let's assume it is a generic pointer
8895 /* we have to go by the storage class */
8896 p_type = PTR_TYPE (SPEC_OCLS (etype));
8900 /* the first two bytes are known */
8901 size = GPTRSIZE - 1;
8905 aopPut (AOP (result),
8906 aopGet (AOP (right), offset, FALSE, FALSE),
8908 isOperandVolatile (result, FALSE));
8911 /* the last byte depending on type */
8913 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8918 // pointerTypeToGPByte will have bitched.
8922 sprintf(gpValStr, "#0x%d", gpVal);
8923 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8928 /* just copy the pointers */
8929 size = AOP_SIZE (result);
8933 aopPut (AOP (result),
8934 aopGet (AOP (right), offset, FALSE, FALSE),
8936 isOperandVolatile (result, FALSE));
8942 /* so we now know that the size of destination is greater
8943 than the size of the source */
8944 /* we move to result for the size of source */
8945 size = AOP_SIZE (right);
8949 aopPut (AOP (result),
8950 aopGet (AOP (right), offset, FALSE, FALSE),
8952 isOperandVolatile (result, FALSE));
8956 /* now depending on the sign of the source && destination */
8957 size = AOP_SIZE (result) - AOP_SIZE (right);
8958 /* if unsigned or not an integral type */
8959 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8962 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8966 /* we need to extend the sign :{ */
8967 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8970 emitcode ("rlc", "a");
8971 emitcode ("subb", "a,acc");
8973 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8976 /* we are done hurray !!!! */
8979 freeAsmop (right, NULL, ic, TRUE);
8980 freeAsmop (result, NULL, ic, TRUE);
8984 /*-----------------------------------------------------------------*/
8985 /* genDjnz - generate decrement & jump if not zero instrucion */
8986 /*-----------------------------------------------------------------*/
8988 genDjnz (iCode * ic, iCode * ifx)
8994 D(emitcode ("; genDjnz",""));
8996 /* if the if condition has a false label
8997 then we cannot save */
9001 /* if the minus is not of the form
9003 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
9004 !IS_OP_LITERAL (IC_RIGHT (ic)))
9007 if (operandLitValue (IC_RIGHT (ic)) != 1)
9010 /* if the size of this greater than one then no
9012 if (getSize (operandType (IC_RESULT (ic))) > 1)
9015 /* otherwise we can save BIG */
9016 lbl = newiTempLabel (NULL);
9017 lbl1 = newiTempLabel (NULL);
9019 aopOp (IC_RESULT (ic), ic, FALSE);
9021 if (AOP_NEEDSACC(IC_RESULT(ic)))
9023 /* If the result is accessed indirectly via
9024 * the accumulator, we must explicitly write
9025 * it back after the decrement.
9027 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
9029 if (strcmp(rByte, "a"))
9031 /* Something is hopelessly wrong */
9032 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9033 __FILE__, __LINE__);
9034 /* We can just give up; the generated code will be inefficient,
9037 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9040 emitcode ("dec", "%s", rByte);
9041 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9042 emitcode ("jnz", "%05d$", lbl->key + 100);
9044 else if (IS_AOP_PREG (IC_RESULT (ic)))
9046 emitcode ("dec", "%s",
9047 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9048 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9049 emitcode ("jnz", "%05d$", lbl->key + 100);
9053 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9056 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9057 emitcode ("", "%05d$:", lbl->key + 100);
9058 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9059 emitcode ("", "%05d$:", lbl1->key + 100);
9061 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9066 /*-----------------------------------------------------------------*/
9067 /* genReceive - generate code for a receive iCode */
9068 /*-----------------------------------------------------------------*/
9070 genReceive (iCode * ic)
9072 int size = getSize (operandType (IC_RESULT (ic)));
9074 D(emitcode ("; genReceive",""));
9076 if (ic->argreg == 1) { /* first parameter */
9077 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9078 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9079 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9081 offset = fReturnSizeMCS51 - size;
9083 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9084 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9087 aopOp (IC_RESULT (ic), ic, FALSE);
9088 size = AOP_SIZE (IC_RESULT (ic));
9091 emitcode ("pop", "acc");
9092 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9097 aopOp (IC_RESULT (ic), ic, FALSE);
9099 assignResultValue (IC_RESULT (ic));
9101 } else { /* second receive onwards */
9103 aopOp (IC_RESULT (ic), ic, FALSE);
9104 rb1off = ic->argreg;
9106 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9109 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9112 /*-----------------------------------------------------------------*/
9113 /* genDummyRead - generate code for dummy read of volatiles */
9114 /*-----------------------------------------------------------------*/
9116 genDummyRead (iCode * ic)
9121 D(emitcode("; genDummyRead",""));
9124 if (op && IS_SYMOP (op))
9126 aopOp (op, ic, FALSE);
9128 /* if the result is a bit */
9129 if (AOP_TYPE (op) == AOP_CRY)
9130 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9133 /* bit variables done */
9135 size = AOP_SIZE (op);
9139 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9144 freeAsmop (op, NULL, ic, TRUE);
9148 if (op && IS_SYMOP (op))
9150 aopOp (op, ic, FALSE);
9152 /* if the result is a bit */
9153 if (AOP_TYPE (op) == AOP_CRY)
9154 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
9157 /* bit variables done */
9159 size = AOP_SIZE (op);
9163 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
9168 freeAsmop (op, NULL, ic, TRUE);
9172 /*-----------------------------------------------------------------*/
9173 /* genCritical - generate code for start of a critical sequence */
9174 /*-----------------------------------------------------------------*/
9176 genCritical (iCode *ic)
9178 symbol *tlbl = newiTempLabel (NULL);
9180 D(emitcode("; genCritical",""));
9183 aopOp (IC_RESULT (ic), ic, TRUE);
9185 emitcode ("setb", "c");
9186 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9187 emitcode ("clr", "c");
9188 emitcode ("", "%05d$:", (tlbl->key + 100));
9191 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9193 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9196 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9199 /*-----------------------------------------------------------------*/
9200 /* genEndCritical - generate code for end of a critical sequence */
9201 /*-----------------------------------------------------------------*/
9203 genEndCritical (iCode *ic)
9205 D(emitcode("; genEndCritical",""));
9209 aopOp (IC_RIGHT (ic), ic, FALSE);
9210 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9212 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9213 emitcode ("mov", "ea,c");
9217 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9218 emitcode ("rrc", "a");
9219 emitcode ("mov", "ea,c");
9221 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9225 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9226 emitcode ("mov", "ea,c");
9231 /*-----------------------------------------------------------------*/
9232 /* gen51Code - generate code for 8051 based controllers */
9233 /*-----------------------------------------------------------------*/
9235 gen51Code (iCode * lic)
9240 lineHead = lineCurr = NULL;
9242 /* print the allocation information */
9243 if (allocInfo && currFunc)
9244 printAllocInfo (currFunc, codeOutFile);
9245 /* if debug information required */
9246 if (options.debug && currFunc)
9248 debugFile->writeFunction(currFunc);
9250 if (IS_STATIC (currFunc->etype))
9251 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9253 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9256 /* stack pointer name */
9257 if (options.useXstack)
9263 for (ic = lic; ic; ic = ic->next)
9265 _G.current_iCode = ic;
9267 if (ic->lineno && cln != ic->lineno)
9272 emitcode ("", "C$%s$%d$%d$%d ==.",
9273 FileBaseName (ic->filename), ic->lineno,
9274 ic->level, ic->block);
9277 if (!options.noCcodeInAsm) {
9278 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9279 printCLine(ic->filename, ic->lineno));
9283 if (options.iCodeInAsm) {
9287 for (i=0; i<8; i++) {
9288 sprintf (®sInUse[i],
9289 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9292 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9294 /* if the result is marked as
9295 spilt and rematerializable or code for
9296 this has already been generated then
9298 if (resultRemat (ic) || ic->generated)
9301 /* depending on the operation */
9321 /* IPOP happens only when trying to restore a
9322 spilt live range, if there is an ifx statement
9323 following this pop then the if statement might
9324 be using some of the registers being popped which
9325 would destory the contents of the register so
9326 we need to check for this condition and handle it */
9328 ic->next->op == IFX &&
9329 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9330 genIfx (ic->next, ic);
9348 genEndFunction (ic);
9368 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9385 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9389 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9396 /* note these two are xlated by algebraic equivalence
9397 during parsing SDCC.y */
9398 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9399 "got '>=' or '<=' shouldn't have come here");
9403 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9415 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9419 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9423 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9450 case GET_VALUE_AT_ADDRESS:
9451 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9455 if (POINTER_SET (ic))
9456 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9482 addSet (&_G.sendSet, ic);
9485 case DUMMY_READ_VOLATILE:
9494 genEndCritical (ic);
9506 _G.current_iCode = NULL;
9508 /* now we are ready to call the
9509 peep hole optimizer */
9510 if (!options.nopeep)
9511 peepHole (&lineHead);
9513 /* now do the actual printing */
9514 printLine (lineHead, codeOutFile);