1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
80 static char *rb1regs[] = {
81 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
84 extern int mcs51_ptrRegReq;
85 extern int mcs51_nRegs;
86 extern FILE *codeOutFile;
87 static void saveRBank (int, iCode *, bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
93 #define CLRC emitcode("clr","c")
94 #define SETC emitcode("setb","c")
96 static lineNode *lineHead = NULL;
97 static lineNode *lineCurr = NULL;
99 static unsigned char SLMask[] =
100 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
101 0xE0, 0xC0, 0x80, 0x00};
102 static unsigned char SRMask[] =
103 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
104 0x07, 0x03, 0x01, 0x00};
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple */
113 /*-----------------------------------------------------------------*/
115 emitcode (char *inst, const char *fmt,...)
118 char lb[INITIAL_INLINEASM];
126 sprintf (lb, "%s\t", inst);
128 sprintf (lb, "%s", inst);
129 vsprintf (lb + (strlen (lb)), fmt, ap);
132 vsprintf (lb, fmt, ap);
134 while (isspace (*lbp))
138 lineCurr = (lineCurr ?
139 connectLine (lineCurr, newLineNode (lb)) :
140 (lineHead = newLineNode (lb)));
141 lineCurr->isInline = _G.inLine;
142 lineCurr->isDebug = _G.debugLine;
143 lineCurr->ic = _G.current_iCode;
144 lineCurr->isComment = (*lbp==';');
148 /*-----------------------------------------------------------------*/
149 /* mova - moves specified value into accumulator */
150 /*-----------------------------------------------------------------*/
154 /* do some early peephole optimization */
155 if (!strcmp(x, "a") || !strcmp(x, "acc"))
158 emitcode("mov","a,%s", x);
161 /*-----------------------------------------------------------------*/
162 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
163 /*-----------------------------------------------------------------*/
165 getFreePtr (iCode * ic, asmop ** aopp, bool result)
167 bool r0iu = FALSE, r1iu = FALSE;
168 bool r0ou = FALSE, r1ou = FALSE;
170 /* the logic: if r0 & r1 used in the instruction
171 then we are in trouble otherwise */
173 /* first check if r0 & r1 are used by this
174 instruction, in which case we are in trouble */
175 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
176 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
181 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
182 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
184 /* if no usage of r0 then return it */
187 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
188 (*aopp)->type = AOP_R0;
190 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
193 /* if no usage of r1 then return it */
196 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
197 (*aopp)->type = AOP_R1;
199 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
202 /* now we know they both have usage */
203 /* if r0 not used in this instruction */
206 /* push it if not already pushed */
209 emitcode ("push", "%s",
210 mcs51_regWithIdx (R0_IDX)->dname);
214 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
215 (*aopp)->type = AOP_R0;
217 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
220 /* if r1 not used then */
224 /* push it if not already pushed */
227 emitcode ("push", "%s",
228 mcs51_regWithIdx (R1_IDX)->dname);
232 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
233 (*aopp)->type = AOP_R1;
234 return mcs51_regWithIdx (R1_IDX);
237 /* I said end of world, but not quite end of world yet */
239 /* we can push it on the stack */
240 (*aopp)->type = AOP_STK;
243 /* in the case that result AND left AND right needs a pointer reg
244 we can safely use the result's */
245 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
246 (*aopp)->type = AOP_R0;
247 return mcs51_regWithIdx (R0_IDX);
249 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
250 (*aopp)->type = AOP_R1;
251 return mcs51_regWithIdx (R1_IDX);
255 /* now this is REALLY the end of the world */
256 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
257 "getFreePtr should never reach here");
261 /*-----------------------------------------------------------------*/
262 /* newAsmop - creates a new asmOp */
263 /*-----------------------------------------------------------------*/
265 newAsmop (short type)
269 aop = Safe_calloc (1, sizeof (asmop));
274 /*-----------------------------------------------------------------*/
275 /* pointerCode - returns the code for a pointer type */
276 /*-----------------------------------------------------------------*/
278 pointerCode (sym_link * etype)
281 return PTR_TYPE (SPEC_OCLS (etype));
286 /*-----------------------------------------------------------------*/
287 /* leftRightUseAcc - returns size of accumulator use by operands */
288 /*-----------------------------------------------------------------*/
290 leftRightUseAcc(iCode *ic)
299 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
300 "null iCode pointer");
307 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
310 size = getSize (OP_SYMBOL (op)->type);
315 else if (ic->op == JUMPTABLE)
318 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
321 size = getSize (OP_SYMBOL (op)->type);
329 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
332 size = getSize (OP_SYMBOL (op)->type);
337 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
340 size = getSize (OP_SYMBOL (op)->type);
353 /*-----------------------------------------------------------------*/
354 /* aopForSym - for a true symbol */
355 /*-----------------------------------------------------------------*/
357 aopForSym (iCode * ic, symbol * sym, bool result)
362 wassertl (ic != NULL, "Got a null iCode");
363 wassertl (sym != NULL, "Got a null symbol");
365 space = SPEC_OCLS (sym->etype);
367 /* if already has one */
371 /* assign depending on the storage class */
372 /* if it is on the stack or indirectly addressable */
373 /* space we need to assign either r0 or r1 to it */
374 if (sym->onStack || sym->iaccess)
376 sym->aop = aop = newAsmop (0);
377 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
378 aop->size = getSize (sym->type);
380 /* now assign the address of the variable to
381 the pointer register */
382 if (aop->type != AOP_STK)
387 if (_G.accInUse || leftRightUseAcc (ic))
388 emitcode ("push", "acc");
390 emitcode ("mov", "a,_bp");
391 emitcode ("add", "a,#0x%02x",
393 ((char) (sym->stack - _G.nRegsSaved)) :
394 ((char) sym->stack)) & 0xff);
395 emitcode ("mov", "%s,a",
396 aop->aopu.aop_ptr->name);
398 if (_G.accInUse || leftRightUseAcc (ic))
399 emitcode ("pop", "acc");
402 emitcode ("mov", "%s,#%s",
403 aop->aopu.aop_ptr->name,
405 aop->paged = space->paged;
408 aop->aopu.aop_stk = sym->stack;
412 /* if in bit space */
413 if (IN_BITSPACE (space))
415 sym->aop = aop = newAsmop (AOP_CRY);
416 aop->aopu.aop_dir = sym->rname;
417 aop->size = getSize (sym->type);
420 /* if it is in direct space */
421 if (IN_DIRSPACE (space))
423 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
424 //printTypeChainRaw(sym->type, NULL);
425 //printf("space = %s\n", space ? space->sname : "NULL");
426 sym->aop = aop = newAsmop (AOP_DIR);
427 aop->aopu.aop_dir = sym->rname;
428 aop->size = getSize (sym->type);
432 /* special case for a function */
433 if (IS_FUNC (sym->type))
435 sym->aop = aop = newAsmop (AOP_IMMD);
436 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
437 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
438 aop->size = FPTRSIZE;
442 /* only remaining is far space */
443 /* in which case DPTR gets the address */
444 sym->aop = aop = newAsmop (AOP_DPTR);
445 emitcode ("mov", "dptr,#%s", sym->rname);
446 aop->size = getSize (sym->type);
448 /* if it is in code space */
449 if (IN_CODESPACE (space))
455 /*-----------------------------------------------------------------*/
456 /* aopForRemat - rematerialzes an object */
457 /*-----------------------------------------------------------------*/
459 aopForRemat (symbol * sym)
461 iCode *ic = sym->rematiCode;
462 asmop *aop = newAsmop (AOP_IMMD);
469 val += (int) operandLitValue (IC_RIGHT (ic));
470 else if (ic->op == '-')
471 val -= (int) operandLitValue (IC_RIGHT (ic));
472 else if (IS_CAST_ICODE(ic)) {
473 sym_link *from_type = operandType(IC_RIGHT(ic));
474 aop->aopu.aop_immd.from_cast_remat = 1;
475 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
476 ptr_type = DCL_TYPE(from_type);
477 if (ptr_type == IPOINTER) {
484 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
488 sprintf (buffer, "(%s %c 0x%04x)",
489 OP_SYMBOL (IC_LEFT (ic))->rname,
490 val >= 0 ? '+' : '-',
493 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
495 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
496 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
497 /* set immd2 field if required */
498 if (aop->aopu.aop_immd.from_cast_remat) {
499 sprintf(buffer,"#0x%02x",ptr_type);
500 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
501 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
507 /*-----------------------------------------------------------------*/
508 /* regsInCommon - two operands have some registers in common */
509 /*-----------------------------------------------------------------*/
511 regsInCommon (operand * op1, operand * op2)
516 /* if they have registers in common */
517 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
520 sym1 = OP_SYMBOL (op1);
521 sym2 = OP_SYMBOL (op2);
523 if (sym1->nRegs == 0 || sym2->nRegs == 0)
526 for (i = 0; i < sym1->nRegs; i++)
532 for (j = 0; j < sym2->nRegs; j++)
537 if (sym2->regs[j] == sym1->regs[i])
545 /*-----------------------------------------------------------------*/
546 /* operandsEqu - equivalent */
547 /*-----------------------------------------------------------------*/
549 operandsEqu (operand * op1, operand * op2)
553 /* if they not symbols */
554 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
557 sym1 = OP_SYMBOL (op1);
558 sym2 = OP_SYMBOL (op2);
560 /* if both are itemps & one is spilt
561 and the other is not then false */
562 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
563 sym1->isspilt != sym2->isspilt)
566 /* if they are the same */
570 if (strcmp (sym1->rname, sym2->rname) == 0)
574 /* if left is a tmp & right is not */
575 if (IS_ITEMP (op1) &&
578 (sym1->usl.spillLoc == sym2))
581 if (IS_ITEMP (op2) &&
585 (sym2->usl.spillLoc == sym1))
591 /*-----------------------------------------------------------------*/
592 /* sameRegs - two asmops have the same registers */
593 /*-----------------------------------------------------------------*/
595 sameRegs (asmop * aop1, asmop * aop2)
602 if (aop1->type != AOP_REG ||
603 aop2->type != AOP_REG)
606 if (aop1->size != aop2->size)
609 for (i = 0; i < aop1->size; i++)
610 if (aop1->aopu.aop_reg[i] !=
611 aop2->aopu.aop_reg[i])
617 /*-----------------------------------------------------------------*/
618 /* aopOp - allocates an asmop for an operand : */
619 /*-----------------------------------------------------------------*/
621 aopOp (operand * op, iCode * ic, bool result)
630 /* if this a literal */
631 if (IS_OP_LITERAL (op))
633 op->aop = aop = newAsmop (AOP_LIT);
634 aop->aopu.aop_lit = op->operand.valOperand;
635 aop->size = getSize (operandType (op));
639 /* if already has a asmop then continue */
643 /* if the underlying symbol has a aop */
644 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
646 op->aop = OP_SYMBOL (op)->aop;
650 /* if this is a true symbol */
651 if (IS_TRUE_SYMOP (op))
653 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
657 /* this is a temporary : this has
663 e) can be a return use only */
665 sym = OP_SYMBOL (op);
667 /* if the type is a conditional */
668 if (sym->regType == REG_CND)
670 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
675 /* if it is spilt then two situations
677 b) has a spill location */
678 if (sym->isspilt || sym->nRegs == 0)
681 /* rematerialize it NOW */
684 sym->aop = op->aop = aop =
686 aop->size = getSize (sym->type);
693 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
694 aop->size = getSize (sym->type);
695 for (i = 0; i < 2; i++)
696 aop->aopu.aop_str[i] = accUse[i];
704 aop = op->aop = sym->aop = newAsmop (AOP_STR);
705 aop->size = getSize (sym->type);
706 for (i = 0; i < fReturnSizeMCS51; i++)
707 aop->aopu.aop_str[i] = fReturn[i];
711 if (sym->usl.spillLoc)
713 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
715 /* force a new aop if sizes differ */
716 sym->usl.spillLoc->aop = NULL;
718 sym->aop = op->aop = aop =
719 aopForSym (ic, sym->usl.spillLoc, result);
720 aop->size = getSize (sym->type);
724 /* else must be a dummy iTemp */
725 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
726 aop->size = getSize (sym->type);
730 /* must be in a register */
731 sym->aop = op->aop = aop = newAsmop (AOP_REG);
732 aop->size = sym->nRegs;
733 for (i = 0; i < sym->nRegs; i++)
734 aop->aopu.aop_reg[i] = sym->regs[i];
737 /*-----------------------------------------------------------------*/
738 /* freeAsmop - free up the asmop given to an operand */
739 /*----------------------------------------------------------------*/
741 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
758 /* depending on the asmop type only three cases need work AOP_RO
759 , AOP_R1 && AOP_STK */
767 emitcode ("pop", "ar0");
771 bitVectUnSetBit (ic->rUsed, R0_IDX);
779 emitcode ("pop", "ar1");
783 bitVectUnSetBit (ic->rUsed, R1_IDX);
789 int stk = aop->aopu.aop_stk + aop->size - 1;
790 bitVectUnSetBit (ic->rUsed, R0_IDX);
791 bitVectUnSetBit (ic->rUsed, R1_IDX);
793 getFreePtr (ic, &aop, FALSE);
797 emitcode ("mov", "a,_bp");
798 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
799 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
803 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
808 emitcode ("pop", "acc");
809 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
812 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
815 freeAsmop (op, NULL, ic, TRUE);
818 emitcode ("pop", "ar1");
824 emitcode ("pop", "ar0");
831 /* all other cases just dealloc */
837 OP_SYMBOL (op)->aop = NULL;
838 /* if the symbol has a spill */
840 SPIL_LOC (op)->aop = NULL;
845 /*-----------------------------------------------------------------*/
846 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
847 /* clobber the accumulator */
848 /*-----------------------------------------------------------------*/
850 aopGetUsesAcc (asmop *aop, int offset)
852 if (offset > (aop->size - 1))
870 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
879 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
885 /* Error case --- will have been caught already */
891 /*-----------------------------------------------------------------*/
892 /* aopGet - for fetching value of the aop */
893 /*-----------------------------------------------------------------*/
895 aopGet (asmop * aop, int offset, bool bit16, bool dname)
900 /* offset is greater than
902 if (offset > (aop->size - 1) &&
903 aop->type != AOP_LIT)
906 /* depending on type */
914 /* if we need to increment it */
915 while (offset > aop->coff)
917 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
921 while (offset < aop->coff)
923 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
930 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
931 return (dname ? "acc" : "a");
933 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
934 rs = Safe_calloc (1, strlen (s) + 1);
939 if (aop->code && aop->coff==0 && offset>=1) {
940 emitcode ("mov", "a,#0x%02x", offset);
941 emitcode ("movc", "a,@a+dptr");
942 return (dname ? "acc" : "a");
945 while (offset > aop->coff)
947 emitcode ("inc", "dptr");
951 while (offset < aop->coff)
953 emitcode ("lcall", "__decdptr");
960 emitcode ("clr", "a");
961 emitcode ("movc", "a,@a+dptr");
965 emitcode ("movx", "a,@dptr");
967 return (dname ? "acc" : "a");
971 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
972 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
974 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
976 sprintf (s, "#(%s >> %d)",
977 aop->aopu.aop_immd.aop_immd1,
981 aop->aopu.aop_immd.aop_immd1);
982 rs = Safe_calloc (1, strlen (s) + 1);
988 sprintf (s, "(%s + %d)",
992 sprintf (s, "%s", aop->aopu.aop_dir);
993 rs = Safe_calloc (1, strlen (s) + 1);
999 return aop->aopu.aop_reg[offset]->dname;
1001 return aop->aopu.aop_reg[offset]->name;
1004 emitcode ("clr", "a");
1005 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1006 emitcode ("rlc", "a");
1007 return (dname ? "acc" : "a");
1010 if (!offset && dname)
1012 return aop->aopu.aop_str[offset];
1015 return aopLiteral (aop->aopu.aop_lit, offset);
1019 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1023 return aop->aopu.aop_str[offset];
1027 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1028 "aopget got unsupported aop->type");
1031 /*-----------------------------------------------------------------*/
1032 /* aopPut - puts a string for a aop */
1033 /*-----------------------------------------------------------------*/
1035 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1039 if (aop->size && offset > (aop->size - 1))
1041 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1042 "aopPut got offset > aop->size");
1046 /* will assign value to value */
1047 /* depending on where it is ofcourse */
1051 MOVA (s); /* read s in case it was volatile */
1056 sprintf (d, "(%s + %d)",
1057 aop->aopu.aop_dir, offset);
1059 sprintf (d, "%s", aop->aopu.aop_dir);
1061 if (strcmp (d, s) ||
1063 emitcode ("mov", "%s,%s", d, s);
1068 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1069 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1072 strcmp (s, "r0") == 0 ||
1073 strcmp (s, "r1") == 0 ||
1074 strcmp (s, "r2") == 0 ||
1075 strcmp (s, "r3") == 0 ||
1076 strcmp (s, "r4") == 0 ||
1077 strcmp (s, "r5") == 0 ||
1078 strcmp (s, "r6") == 0 ||
1079 strcmp (s, "r7") == 0)
1080 emitcode ("mov", "%s,%s",
1081 aop->aopu.aop_reg[offset]->dname, s);
1083 emitcode ("mov", "%s,%s",
1084 aop->aopu.aop_reg[offset]->name, s);
1091 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1092 "aopPut writing to code space");
1096 while (offset > aop->coff)
1099 emitcode ("inc", "dptr");
1102 while (offset < aop->coff)
1105 emitcode ("lcall", "__decdptr");
1110 /* if not in accumulater */
1113 emitcode ("movx", "@dptr,a");
1118 while (offset > aop->coff)
1121 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1123 while (offset < aop->coff)
1126 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1133 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1139 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1141 else if (strcmp (s, "r0") == 0 ||
1142 strcmp (s, "r1") == 0 ||
1143 strcmp (s, "r2") == 0 ||
1144 strcmp (s, "r3") == 0 ||
1145 strcmp (s, "r4") == 0 ||
1146 strcmp (s, "r5") == 0 ||
1147 strcmp (s, "r6") == 0 ||
1148 strcmp (s, "r7") == 0)
1151 sprintf (buffer, "a%s", s);
1152 emitcode ("mov", "@%s,%s",
1153 aop->aopu.aop_ptr->name, buffer);
1156 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1161 if (strcmp (s, "a") == 0)
1162 emitcode ("push", "acc");
1166 emitcode ("push", "acc");
1168 emitcode ("push", s);
1174 /* if bit variable */
1175 if (!aop->aopu.aop_dir)
1177 emitcode ("clr", "a");
1178 emitcode ("rlc", "a");
1183 emitcode ("clr", "%s", aop->aopu.aop_dir);
1185 emitcode ("setb", "%s", aop->aopu.aop_dir);
1186 else if (!strcmp (s, "c"))
1187 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1190 if (strcmp (s, "a"))
1195 /* set C, if a >= 1 */
1196 emitcode ("add", "a,#0xff");
1197 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1205 if (strcmp (aop->aopu.aop_str[offset], s) ||
1207 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1212 if (!offset && (strcmp (s, "acc") == 0) &&
1216 if (strcmp (aop->aopu.aop_str[offset], s) &&
1218 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1222 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1223 "aopPut got unsupported aop->type");
1231 /*-----------------------------------------------------------------*/
1232 /* pointToEnd :- points to the last byte of the operand */
1233 /*-----------------------------------------------------------------*/
1235 pointToEnd (asmop * aop)
1241 aop->coff = count = (aop->size - 1);
1247 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1251 emitcode ("inc", "dptr");
1258 /*-----------------------------------------------------------------*/
1259 /* reAdjustPreg - points a register back to where it should */
1260 /*-----------------------------------------------------------------*/
1262 reAdjustPreg (asmop * aop)
1264 if ((aop->coff==0) || aop->size <= 1)
1272 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1277 emitcode ("lcall", "__decdptr");
1284 #define AOP(op) op->aop
1285 #define AOP_TYPE(op) AOP(op)->type
1286 #define AOP_SIZE(op) AOP(op)->size
1287 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1288 AOP_TYPE(x) == AOP_R0))
1290 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1291 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1293 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1294 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1295 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1298 /*-----------------------------------------------------------------*/
1299 /* opIsGptr: returns non-zero if the passed operand is */
1300 /* a generic pointer type. */
1301 /*-----------------------------------------------------------------*/
1303 opIsGptr (operand * op)
1305 sym_link *type = operandType (op);
1307 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1314 /*-----------------------------------------------------------------*/
1315 /* getDataSize - get the operand data size */
1316 /*-----------------------------------------------------------------*/
1318 getDataSize (operand * op)
1321 size = AOP_SIZE (op);
1322 if (size == GPTRSIZE)
1324 sym_link *type = operandType (op);
1325 if (IS_GENPTR (type))
1327 /* generic pointer; arithmetic operations
1328 * should ignore the high byte (pointer type).
1336 /*-----------------------------------------------------------------*/
1337 /* outAcc - output Acc */
1338 /*-----------------------------------------------------------------*/
1340 outAcc (operand * result)
1343 size = getDataSize (result);
1346 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1349 /* unsigned or positive */
1352 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1357 /*-----------------------------------------------------------------*/
1358 /* outBitC - output a bit C */
1359 /*-----------------------------------------------------------------*/
1361 outBitC (operand * result)
1363 /* if the result is bit */
1364 if (AOP_TYPE (result) == AOP_CRY)
1365 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1368 emitcode ("clr", "a");
1369 emitcode ("rlc", "a");
1374 /*-----------------------------------------------------------------*/
1375 /* toBoolean - emit code for orl a,operator(sizeop) */
1376 /*-----------------------------------------------------------------*/
1378 toBoolean (operand * oper)
1380 int size = AOP_SIZE (oper) - 1;
1382 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1384 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1388 /*-----------------------------------------------------------------*/
1389 /* genNot - generate code for ! operation */
1390 /*-----------------------------------------------------------------*/
1396 D(emitcode ("; genNot",""));
1398 /* assign asmOps to operand & result */
1399 aopOp (IC_LEFT (ic), ic, FALSE);
1400 aopOp (IC_RESULT (ic), ic, TRUE);
1402 /* if in bit space then a special case */
1403 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1405 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1406 emitcode ("cpl", "c");
1407 outBitC (IC_RESULT (ic));
1411 toBoolean (IC_LEFT (ic));
1413 tlbl = newiTempLabel (NULL);
1414 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1415 emitcode ("", "%05d$:", tlbl->key + 100);
1416 outBitC (IC_RESULT (ic));
1419 /* release the aops */
1420 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1421 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1425 /*-----------------------------------------------------------------*/
1426 /* genCpl - generate code for complement */
1427 /*-----------------------------------------------------------------*/
1435 D(emitcode ("; genCpl",""));
1437 /* assign asmOps to operand & result */
1438 aopOp (IC_LEFT (ic), ic, FALSE);
1439 aopOp (IC_RESULT (ic), ic, TRUE);
1441 /* special case if in bit space */
1442 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1444 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1446 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1447 emitcode ("cpl", "c");
1448 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1452 tlbl=newiTempLabel(NULL);
1453 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1454 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1455 IS_AOP_PREG (IC_LEFT (ic)))
1457 emitcode ("cjne", "%s,#0x01,%05d$",
1458 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1463 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1465 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1467 emitcode ("", "%05d$:", tlbl->key + 100);
1468 outBitC (IC_RESULT(ic));
1472 size = AOP_SIZE (IC_RESULT (ic));
1475 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1477 emitcode ("cpl", "a");
1478 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1483 /* release the aops */
1484 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1485 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1488 /*-----------------------------------------------------------------*/
1489 /* genUminusFloat - unary minus for floating points */
1490 /*-----------------------------------------------------------------*/
1492 genUminusFloat (operand * op, operand * result)
1494 int size, offset = 0;
1497 D(emitcode ("; genUminusFloat",""));
1499 /* for this we just copy and then flip the bit */
1501 size = AOP_SIZE (op) - 1;
1505 aopPut (AOP (result),
1506 aopGet (AOP (op), offset, FALSE, FALSE),
1508 isOperandVolatile (result, FALSE));
1512 l = aopGet (AOP (op), offset, FALSE, FALSE);
1516 emitcode ("cpl", "acc.7");
1517 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1520 /*-----------------------------------------------------------------*/
1521 /* genUminus - unary minus code generation */
1522 /*-----------------------------------------------------------------*/
1524 genUminus (iCode * ic)
1527 sym_link *optype, *rtype;
1530 D(emitcode ("; genUminus",""));
1533 aopOp (IC_LEFT (ic), ic, FALSE);
1534 aopOp (IC_RESULT (ic), ic, TRUE);
1536 /* if both in bit space then special
1538 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1539 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1542 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1543 emitcode ("cpl", "c");
1544 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1548 optype = operandType (IC_LEFT (ic));
1549 rtype = operandType (IC_RESULT (ic));
1551 /* if float then do float stuff */
1552 if (IS_FLOAT (optype))
1554 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1558 /* otherwise subtract from zero */
1559 size = AOP_SIZE (IC_LEFT (ic));
1564 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1565 if (!strcmp (l, "a"))
1569 emitcode ("cpl", "a");
1570 emitcode ("addc", "a,#0");
1576 emitcode ("clr", "a");
1577 emitcode ("subb", "a,%s", l);
1579 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1582 /* if any remaining bytes in the result */
1583 /* we just need to propagate the sign */
1584 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1586 emitcode ("rlc", "a");
1587 emitcode ("subb", "a,acc");
1589 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1593 /* release the aops */
1594 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1595 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1598 /*-----------------------------------------------------------------*/
1599 /* saveRegisters - will look for a call and save the registers */
1600 /*-----------------------------------------------------------------*/
1602 saveRegisters (iCode * lic)
1609 for (ic = lic; ic; ic = ic->next)
1610 if (ic->op == CALL || ic->op == PCALL)
1615 fprintf (stderr, "found parameter push with no function call\n");
1619 /* if the registers have been saved already or don't need to be then
1623 if (IS_SYMOP(IC_LEFT(ic)) &&
1624 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1625 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1628 /* safe the registers in use at this time but skip the
1629 ones for the result */
1630 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1631 mcs51_rUmaskForOp (IC_RESULT(ic)));
1634 if (options.useXstack)
1636 if (bitVectBitValue (rsave, R0_IDX))
1637 emitcode ("mov", "b,r0");
1638 emitcode ("mov", "r0,%s", spname);
1639 for (i = 0; i < mcs51_nRegs; i++)
1641 if (bitVectBitValue (rsave, i))
1644 emitcode ("mov", "a,b");
1646 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1647 emitcode ("movx", "@r0,a");
1648 emitcode ("inc", "r0");
1651 emitcode ("mov", "%s,r0", spname);
1652 if (bitVectBitValue (rsave, R0_IDX))
1653 emitcode ("mov", "r0,b");
1656 for (i = 0; i < mcs51_nRegs; i++)
1658 if (bitVectBitValue (rsave, i))
1659 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1663 /*-----------------------------------------------------------------*/
1664 /* unsaveRegisters - pop the pushed registers */
1665 /*-----------------------------------------------------------------*/
1667 unsaveRegisters (iCode * ic)
1672 /* restore the registers in use at this time but skip the
1673 ones for the result */
1674 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1675 mcs51_rUmaskForOp (IC_RESULT(ic)));
1677 if (options.useXstack)
1679 emitcode ("mov", "r0,%s", spname);
1680 for (i = mcs51_nRegs; i >= 0; i--)
1682 if (bitVectBitValue (rsave, i))
1684 emitcode ("dec", "r0");
1685 emitcode ("movx", "a,@r0");
1687 emitcode ("mov", "b,a");
1689 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1693 emitcode ("mov", "%s,r0", spname);
1694 if (bitVectBitValue (rsave, R0_IDX))
1695 emitcode ("mov", "r0,b");
1698 for (i = mcs51_nRegs; i >= 0; i--)
1700 if (bitVectBitValue (rsave, i))
1701 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1707 /*-----------------------------------------------------------------*/
1709 /*-----------------------------------------------------------------*/
1711 pushSide (operand * oper, int size)
1716 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1717 if (AOP_TYPE (oper) != AOP_REG &&
1718 AOP_TYPE (oper) != AOP_DIR &&
1721 emitcode ("mov", "a,%s", l);
1722 emitcode ("push", "acc");
1725 emitcode ("push", "%s", l);
1729 /*-----------------------------------------------------------------*/
1730 /* assignResultValue - */
1731 /*-----------------------------------------------------------------*/
1733 assignResultValue (operand * oper)
1736 int size = AOP_SIZE (oper);
1739 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1745 /*-----------------------------------------------------------------*/
1746 /* genXpush - pushes onto the external stack */
1747 /*-----------------------------------------------------------------*/
1749 genXpush (iCode * ic)
1751 asmop *aop = newAsmop (0);
1753 int size, offset = 0;
1755 D(emitcode ("; genXpush",""));
1757 aopOp (IC_LEFT (ic), ic, FALSE);
1758 r = getFreePtr (ic, &aop, FALSE);
1761 emitcode ("mov", "%s,_spx", r->name);
1763 size = AOP_SIZE (IC_LEFT (ic));
1767 char *l = aopGet (AOP (IC_LEFT (ic)),
1768 offset++, FALSE, FALSE);
1770 emitcode ("movx", "@%s,a", r->name);
1771 emitcode ("inc", "%s", r->name);
1776 emitcode ("mov", "_spx,%s", r->name);
1778 freeAsmop (NULL, aop, ic, TRUE);
1779 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1782 /*-----------------------------------------------------------------*/
1783 /* genIpush - genrate code for pushing this gets a little complex */
1784 /*-----------------------------------------------------------------*/
1786 genIpush (iCode * ic)
1788 int size, offset = 0;
1791 D(emitcode ("; genIpush",""));
1793 /* if this is not a parm push : ie. it is spill push
1794 and spill push is always done on the local stack */
1798 /* and the item is spilt then do nothing */
1799 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1802 aopOp (IC_LEFT (ic), ic, FALSE);
1803 size = AOP_SIZE (IC_LEFT (ic));
1804 /* push it on the stack */
1807 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1813 emitcode ("push", "%s", l);
1818 /* this is a paramter push: in this case we call
1819 the routine to find the call and save those
1820 registers that need to be saved */
1823 /* if use external stack then call the external
1824 stack pushing routine */
1825 if (options.useXstack)
1831 /* then do the push */
1832 aopOp (IC_LEFT (ic), ic, FALSE);
1835 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1836 size = AOP_SIZE (IC_LEFT (ic));
1840 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1841 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1842 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1845 emitcode ("mov", "a,%s", l);
1846 emitcode ("push", "acc");
1849 emitcode ("push", "%s", l);
1852 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1855 /*-----------------------------------------------------------------*/
1856 /* genIpop - recover the registers: can happen only for spilling */
1857 /*-----------------------------------------------------------------*/
1859 genIpop (iCode * ic)
1863 D(emitcode ("; genIpop",""));
1865 /* if the temp was not pushed then */
1866 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1869 aopOp (IC_LEFT (ic), ic, FALSE);
1870 size = AOP_SIZE (IC_LEFT (ic));
1871 offset = (size - 1);
1873 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1876 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1879 /*-----------------------------------------------------------------*/
1880 /* unsaveRBank - restores the resgister bank from stack */
1881 /*-----------------------------------------------------------------*/
1883 unsaveRBank (int bank, iCode * ic, bool popPsw)
1889 if (options.useXstack)
1893 /* Assume r0 is available for use. */
1894 r = mcs51_regWithIdx (R0_IDX);;
1899 r = getFreePtr (ic, &aop, FALSE);
1901 emitcode ("mov", "%s,_spx", r->name);
1906 if (options.useXstack)
1908 emitcode ("movx", "a,@%s", r->name);
1909 emitcode ("mov", "psw,a");
1910 emitcode ("dec", "%s", r->name);
1914 emitcode ("pop", "psw");
1918 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1920 if (options.useXstack)
1922 emitcode ("movx", "a,@%s", r->name);
1923 emitcode ("mov", "(%s+%d),a",
1924 regs8051[i].base, 8 * bank + regs8051[i].offset);
1925 emitcode ("dec", "%s", r->name);
1929 emitcode ("pop", "(%s+%d)",
1930 regs8051[i].base, 8 * bank + regs8051[i].offset);
1933 if (options.useXstack)
1935 emitcode ("mov", "_spx,%s", r->name);
1940 freeAsmop (NULL, aop, ic, TRUE);
1944 /*-----------------------------------------------------------------*/
1945 /* saveRBank - saves an entire register bank on the stack */
1946 /*-----------------------------------------------------------------*/
1948 saveRBank (int bank, iCode * ic, bool pushPsw)
1954 if (options.useXstack)
1958 /* Assume r0 is available for use. */
1959 r = mcs51_regWithIdx (R0_IDX);;
1964 r = getFreePtr (ic, &aop, FALSE);
1966 emitcode ("mov", "%s,_spx", r->name);
1969 for (i = 0; i < mcs51_nRegs; i++)
1971 if (options.useXstack)
1973 emitcode ("inc", "%s", r->name);
1974 emitcode ("mov", "a,(%s+%d)",
1975 regs8051[i].base, 8 * bank + regs8051[i].offset);
1976 emitcode ("movx", "@%s,a", r->name);
1979 emitcode ("push", "(%s+%d)",
1980 regs8051[i].base, 8 * bank + regs8051[i].offset);
1985 if (options.useXstack)
1987 emitcode ("mov", "a,psw");
1988 emitcode ("movx", "@%s,a", r->name);
1989 emitcode ("inc", "%s", r->name);
1990 emitcode ("mov", "_spx,%s", r->name);
1995 emitcode ("push", "psw");
1998 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2003 freeAsmop (NULL, aop, ic, TRUE);
2012 /*-----------------------------------------------------------------*/
2013 /* genSend - gen code for SEND */
2014 /*-----------------------------------------------------------------*/
2015 static void genSend(set *sendSet)
2020 for (sic = setFirstItem (_G.sendSet); sic;
2021 sic = setNextItem (_G.sendSet)) {
2022 int size, offset = 0;
2023 aopOp (IC_LEFT (sic), sic, FALSE);
2024 size = AOP_SIZE (IC_LEFT (sic));
2026 if (sic->argreg == 1) {
2028 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2030 if (strcmp (l, fReturn[offset]))
2031 emitcode ("mov", "%s,%s", fReturn[offset], l);
2037 emitcode ("mov","b1_%d,%s",rb1_count++,
2038 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2041 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2045 /*-----------------------------------------------------------------*/
2046 /* genCall - generates a call statement */
2047 /*-----------------------------------------------------------------*/
2049 genCall (iCode * ic)
2052 // bool restoreBank = FALSE;
2053 bool swapBanks = FALSE;
2055 D(emitcode("; genCall",""));
2057 dtype = operandType (IC_LEFT (ic));
2058 /* if send set is not empty the assign */
2061 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2062 genSend(reverseSet(_G.sendSet));
2064 genSend(_G.sendSet);
2070 /* if we are calling a not _naked function that is not using
2071 the same register bank then we need to save the
2072 destination registers on the stack */
2073 dtype = operandType (IC_LEFT (ic));
2074 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2075 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2076 !IFFUNC_ISISR (dtype))
2081 /* if caller saves & we have not saved then */
2087 emitcode ("mov", "psw,#0x%02x",
2088 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2092 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2093 OP_SYMBOL (IC_LEFT (ic))->rname :
2094 OP_SYMBOL (IC_LEFT (ic))->name));
2098 emitcode ("mov", "psw,#0x%02x",
2099 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2102 /* if we need assign a result value */
2103 if ((IS_ITEMP (IC_RESULT (ic)) &&
2104 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2105 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2106 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2107 IS_TRUE_SYMOP (IC_RESULT (ic)))
2111 aopOp (IC_RESULT (ic), ic, FALSE);
2114 assignResultValue (IC_RESULT (ic));
2116 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2119 /* adjust the stack for parameters if
2124 if (ic->parmBytes > 3)
2126 emitcode ("mov", "a,%s", spname);
2127 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2128 emitcode ("mov", "%s,a", spname);
2131 for (i = 0; i < ic->parmBytes; i++)
2132 emitcode ("dec", "%s", spname);
2135 /* if we hade saved some registers then unsave them */
2136 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2137 unsaveRegisters (ic);
2139 // /* if register bank was saved then pop them */
2141 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2144 /*-----------------------------------------------------------------*/
2145 /* -10l - generates a call by pointer statement */
2146 /*-----------------------------------------------------------------*/
2148 genPcall (iCode * ic)
2151 symbol *rlbl = newiTempLabel (NULL);
2152 // bool restoreBank=FALSE;
2153 bool swapBanks = FALSE;
2155 D(emitcode("; genPCall",""));
2157 /* if caller saves & we have not saved then */
2161 /* if we are calling a not _naked function that is not using
2162 the same register bank then we need to save the
2163 destination registers on the stack */
2164 dtype = operandType (IC_LEFT (ic))->next;
2165 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2166 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2167 !IFFUNC_ISISR (dtype))
2169 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2170 // restoreBank=TRUE;
2172 // need caution message to user here
2175 /* push the return address on to the stack */
2176 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2177 emitcode ("push", "acc");
2178 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2179 emitcode ("push", "acc");
2181 /* now push the calling address */
2182 aopOp (IC_LEFT (ic), ic, FALSE);
2184 pushSide (IC_LEFT (ic), FPTRSIZE);
2186 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2188 /* if send set is not empty the assign */
2191 genSend(reverseSet(_G.sendSet));
2197 emitcode ("mov", "psw,#0x%02x",
2198 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2202 emitcode ("ret", "");
2203 emitcode ("", "%05d$:", (rlbl->key + 100));
2208 emitcode ("mov", "psw,#0x%02x",
2209 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2212 /* if we need assign a result value */
2213 if ((IS_ITEMP (IC_RESULT (ic)) &&
2214 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2215 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2216 IS_TRUE_SYMOP (IC_RESULT (ic)))
2220 aopOp (IC_RESULT (ic), ic, FALSE);
2223 assignResultValue (IC_RESULT (ic));
2225 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2228 /* adjust the stack for parameters if
2233 if (ic->parmBytes > 3)
2235 emitcode ("mov", "a,%s", spname);
2236 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2237 emitcode ("mov", "%s,a", spname);
2240 for (i = 0; i < ic->parmBytes; i++)
2241 emitcode ("dec", "%s", spname);
2245 // /* if register bank was saved then unsave them */
2247 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2249 /* if we hade saved some registers then
2251 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2252 unsaveRegisters (ic);
2255 /*-----------------------------------------------------------------*/
2256 /* resultRemat - result is rematerializable */
2257 /*-----------------------------------------------------------------*/
2259 resultRemat (iCode * ic)
2261 if (SKIP_IC (ic) || ic->op == IFX)
2264 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2266 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2267 if (sym->remat && !POINTER_SET (ic))
2274 #if defined(__BORLANDC__) || defined(_MSC_VER)
2275 #define STRCASECMP stricmp
2277 #define STRCASECMP strcasecmp
2280 /*-----------------------------------------------------------------*/
2281 /* inExcludeList - return 1 if the string is in exclude Reg list */
2282 /*-----------------------------------------------------------------*/
2284 regsCmp(void *p1, void *p2)
2286 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2290 inExcludeList (char *s)
2292 const char *p = setFirstItem(options.excludeRegsSet);
2294 if (p == NULL || STRCASECMP(p, "none") == 0)
2298 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2301 /*-----------------------------------------------------------------*/
2302 /* genFunction - generated code for function entry */
2303 /*-----------------------------------------------------------------*/
2305 genFunction (iCode * ic)
2309 bool switchedPSW = FALSE;
2310 int calleesaves_saved_register = -1;
2313 /* create the function header */
2314 emitcode (";", "-----------------------------------------");
2315 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2316 emitcode (";", "-----------------------------------------");
2318 emitcode ("", "%s:", sym->rname);
2319 ftype = operandType (IC_LEFT (ic));
2321 if (IFFUNC_ISNAKED(ftype))
2323 emitcode(";", "naked function: no prologue.");
2327 /* here we need to generate the equates for the
2328 register bank if required */
2329 if (FUNC_REGBANK (ftype) != rbank)
2333 rbank = FUNC_REGBANK (ftype);
2334 for (i = 0; i < mcs51_nRegs; i++)
2336 if (strcmp (regs8051[i].base, "0") == 0)
2337 emitcode ("", "%s = 0x%02x",
2339 8 * rbank + regs8051[i].offset);
2341 emitcode ("", "%s = %s + 0x%02x",
2344 8 * rbank + regs8051[i].offset);
2348 /* if this is an interrupt service routine then
2349 save acc, b, dpl, dph */
2350 if (IFFUNC_ISISR (sym->type))
2353 if (!inExcludeList ("acc"))
2354 emitcode ("push", "acc");
2355 if (!inExcludeList ("b"))
2356 emitcode ("push", "b");
2357 if (!inExcludeList ("dpl"))
2358 emitcode ("push", "dpl");
2359 if (!inExcludeList ("dph"))
2360 emitcode ("push", "dph");
2361 /* if this isr has no bank i.e. is going to
2362 run with bank 0 , then we need to save more
2364 if (!FUNC_REGBANK (sym->type))
2367 /* if this function does not call any other
2368 function then we can be economical and
2369 save only those registers that are used */
2370 if (!IFFUNC_HASFCALL(sym->type))
2374 /* if any registers used */
2377 /* save the registers used */
2378 for (i = 0; i < sym->regsUsed->size; i++)
2380 if (bitVectBitValue (sym->regsUsed, i) ||
2381 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2382 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2390 /* this function has a function call cannot
2391 determines register usage so we will have to push the
2393 saveRBank (0, ic, FALSE);
2394 if (options.parms_in_bank1) {
2396 for (i=0; i < 8 ; i++ ) {
2397 emitcode ("push","%s",rb1regs[i]);
2404 /* This ISR uses a non-zero bank.
2406 * We assume that the bank is available for our
2409 * However, if this ISR calls a function which uses some
2410 * other bank, we must save that bank entirely.
2412 unsigned long banksToSave = 0;
2414 if (IFFUNC_HASFCALL(sym->type))
2417 #define MAX_REGISTER_BANKS 4
2422 for (i = ic; i; i = i->next)
2424 if (i->op == ENDFUNCTION)
2426 /* we got to the end OK. */
2434 dtype = operandType (IC_LEFT(i));
2436 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2438 /* Mark this bank for saving. */
2439 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2441 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2445 banksToSave |= (1 << FUNC_REGBANK(dtype));
2448 /* And note that we don't need to do it in
2456 /* This is a mess; we have no idea what
2457 * register bank the called function might
2460 * The only thing I can think of to do is
2461 * throw a warning and hope.
2463 werror(W_FUNCPTR_IN_USING_ISR);
2467 if (banksToSave && options.useXstack)
2469 /* Since we aren't passing it an ic,
2470 * saveRBank will assume r0 is available to abuse.
2472 * So switch to our (trashable) bank now, so
2473 * the caller's R0 isn't trashed.
2475 emitcode ("push", "psw");
2476 emitcode ("mov", "psw,#0x%02x",
2477 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2481 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2483 if (banksToSave & (1 << ix))
2485 saveRBank(ix, NULL, FALSE);
2489 // TODO: this needs a closer look
2490 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2495 /* if callee-save to be used for this function
2496 then save the registers being used in this function */
2497 if (IFFUNC_CALLEESAVES(sym->type))
2501 /* if any registers used */
2504 /* save the registers used */
2505 for (i = 0; i < sym->regsUsed->size; i++)
2507 if (bitVectBitValue (sym->regsUsed, i) ||
2508 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2510 /* remember one saved register for later usage */
2511 if (calleesaves_saved_register < 0)
2512 calleesaves_saved_register = i;
2513 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2521 /* set the register bank to the desired value */
2522 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2525 emitcode ("push", "psw");
2526 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2529 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2532 if (options.useXstack)
2534 emitcode ("mov", "r0,%s", spname);
2535 emitcode ("mov", "a,_bp");
2536 emitcode ("movx", "@r0,a");
2537 emitcode ("inc", "%s", spname);
2541 /* set up the stack */
2542 emitcode ("push", "_bp"); /* save the callers stack */
2544 emitcode ("mov", "_bp,%s", spname);
2547 /* adjust the stack for the function */
2553 werror (W_STACK_OVERFLOW, sym->name);
2555 if (i > 3 && sym->recvSize < 4)
2558 emitcode ("mov", "a,sp");
2559 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2560 emitcode ("mov", "sp,a");
2565 if (IFFUNC_CALLEESAVES(sym->type))
2567 /* if it's a callee-saves function we need a saved register */
2568 if (calleesaves_saved_register >= 0)
2570 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2571 emitcode ("mov", "a,sp");
2572 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2573 emitcode ("mov", "sp,a");
2574 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2577 /* do it the hard way */
2579 emitcode ("inc", "sp");
2583 /* not callee-saves, we can clobber r0 */
2584 emitcode ("mov", "r0,a");
2585 emitcode ("mov", "a,sp");
2586 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2587 emitcode ("mov", "sp,a");
2588 emitcode ("mov", "a,r0");
2593 emitcode ("inc", "sp");
2599 emitcode ("mov", "a,_spx");
2600 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2601 emitcode ("mov", "_spx,a");
2604 /* if critical function then turn interrupts off */
2605 if (IFFUNC_ISCRITICAL (ftype))
2607 symbol *tlbl = newiTempLabel (NULL);
2608 emitcode ("setb", "c");
2609 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2610 emitcode ("clr", "c");
2611 emitcode ("", "%05d$:", (tlbl->key + 100));
2612 emitcode ("push", "psw"); /* save old ea via c in psw */
2616 /*-----------------------------------------------------------------*/
2617 /* genEndFunction - generates epilogue for functions */
2618 /*-----------------------------------------------------------------*/
2620 genEndFunction (iCode * ic)
2622 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2624 if (IFFUNC_ISNAKED(sym->type))
2626 emitcode(";", "naked function: no epilogue.");
2630 if (IFFUNC_ISCRITICAL (sym->type))
2632 emitcode ("pop", "psw"); /* restore ea via c in psw */
2633 emitcode ("mov", "ea,c");
2636 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2638 emitcode ("mov", "%s,_bp", spname);
2641 /* if use external stack but some variables were
2642 added to the local stack then decrement the
2644 if (options.useXstack && sym->stack)
2646 emitcode ("mov", "a,sp");
2647 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2648 emitcode ("mov", "sp,a");
2652 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2654 if (options.useXstack)
2656 emitcode ("mov", "r0,%s", spname);
2657 emitcode ("movx", "a,@r0");
2658 emitcode ("mov", "_bp,a");
2659 emitcode ("dec", "%s", spname);
2663 emitcode ("pop", "_bp");
2667 /* restore the register bank */
2668 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2670 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2671 || !options.useXstack)
2673 /* Special case of ISR using non-zero bank with useXstack
2676 emitcode ("pop", "psw");
2680 if (IFFUNC_ISISR (sym->type))
2683 /* now we need to restore the registers */
2684 /* if this isr has no bank i.e. is going to
2685 run with bank 0 , then we need to save more
2687 if (!FUNC_REGBANK (sym->type))
2689 /* if this function does not call any other
2690 function then we can be economical and
2691 save only those registers that are used */
2692 if (!IFFUNC_HASFCALL(sym->type))
2696 /* if any registers used */
2699 /* save the registers used */
2700 for (i = sym->regsUsed->size; i >= 0; i--)
2702 if (bitVectBitValue (sym->regsUsed, i) ||
2703 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2704 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2711 if (options.parms_in_bank1) {
2713 for (i = 7 ; i >= 0 ; i-- ) {
2714 emitcode ("pop","%s",rb1regs[i]);
2717 /* this function has a function call cannot
2718 determines register usage so we will have to pop the
2720 unsaveRBank (0, ic, FALSE);
2725 /* This ISR uses a non-zero bank.
2727 * Restore any register banks saved by genFunction
2730 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2733 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2735 if (savedBanks & (1 << ix))
2737 unsaveRBank(ix, NULL, FALSE);
2741 if (options.useXstack)
2743 /* Restore bank AFTER calling unsaveRBank,
2744 * since it can trash r0.
2746 emitcode ("pop", "psw");
2750 if (!inExcludeList ("dph"))
2751 emitcode ("pop", "dph");
2752 if (!inExcludeList ("dpl"))
2753 emitcode ("pop", "dpl");
2754 if (!inExcludeList ("b"))
2755 emitcode ("pop", "b");
2756 if (!inExcludeList ("acc"))
2757 emitcode ("pop", "acc");
2759 /* if debug then send end of function */
2760 if (options.debug && currFunc)
2763 emitcode ("", "C$%s$%d$%d$%d ==.",
2764 FileBaseName (ic->filename), currFunc->lastLine,
2765 ic->level, ic->block);
2766 if (IS_STATIC (currFunc->etype))
2767 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2769 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2773 emitcode ("reti", "");
2777 if (IFFUNC_CALLEESAVES(sym->type))
2781 /* if any registers used */
2784 /* save the registers used */
2785 for (i = sym->regsUsed->size; i >= 0; i--)
2787 if (bitVectBitValue (sym->regsUsed, i) ||
2788 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2789 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2795 /* if debug then send end of function */
2796 if (options.debug && currFunc)
2799 emitcode ("", "C$%s$%d$%d$%d ==.",
2800 FileBaseName (ic->filename), currFunc->lastLine,
2801 ic->level, ic->block);
2802 if (IS_STATIC (currFunc->etype))
2803 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2805 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2809 emitcode ("ret", "");
2814 /*-----------------------------------------------------------------*/
2815 /* genRet - generate code for return statement */
2816 /*-----------------------------------------------------------------*/
2820 int size, offset = 0, pushed = 0;
2822 D(emitcode ("; genRet",""));
2824 /* if we have no return value then
2825 just generate the "ret" */
2829 /* we have something to return then
2830 move the return value into place */
2831 aopOp (IC_LEFT (ic), ic, FALSE);
2832 size = AOP_SIZE (IC_LEFT (ic));
2837 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2840 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2842 emitcode ("push", "%s", l);
2847 l = aopGet (AOP (IC_LEFT (ic)), offset,
2849 if (strcmp (fReturn[offset], l))
2850 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2859 if (strcmp (fReturn[pushed], "a"))
2860 emitcode ("pop", fReturn[pushed]);
2862 emitcode ("pop", "acc");
2865 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2868 /* generate a jump to the return label
2869 if the next is not the return statement */
2870 if (!(ic->next && ic->next->op == LABEL &&
2871 IC_LABEL (ic->next) == returnLabel))
2873 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2877 /*-----------------------------------------------------------------*/
2878 /* genLabel - generates a label */
2879 /*-----------------------------------------------------------------*/
2881 genLabel (iCode * ic)
2883 /* special case never generate */
2884 if (IC_LABEL (ic) == entryLabel)
2887 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2890 /*-----------------------------------------------------------------*/
2891 /* genGoto - generates a ljmp */
2892 /*-----------------------------------------------------------------*/
2894 genGoto (iCode * ic)
2896 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2899 /*-----------------------------------------------------------------*/
2900 /* findLabelBackwards: walks back through the iCode chain looking */
2901 /* for the given label. Returns number of iCode instructions */
2902 /* between that label and given ic. */
2903 /* Returns zero if label not found. */
2904 /*-----------------------------------------------------------------*/
2906 findLabelBackwards (iCode * ic, int key)
2915 /* If we have any pushes or pops, we cannot predict the distance.
2916 I don't like this at all, this should be dealt with in the
2918 if (ic->op == IPUSH || ic->op == IPOP) {
2922 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2931 /*-----------------------------------------------------------------*/
2932 /* genPlusIncr :- does addition with increment if possible */
2933 /*-----------------------------------------------------------------*/
2935 genPlusIncr (iCode * ic)
2937 unsigned int icount;
2938 unsigned int size = getDataSize (IC_RESULT (ic));
2940 /* will try to generate an increment */
2941 /* if the right side is not a literal
2943 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2946 /* if the literal value of the right hand side
2947 is greater than 4 then it is not worth it */
2948 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2951 D(emitcode ("; genPlusIncr",""));
2953 /* if increment >=16 bits in register or direct space */
2954 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2955 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2963 /* If the next instruction is a goto and the goto target
2964 * is < 10 instructions previous to this, we can generate
2965 * jumps straight to that target.
2967 if (ic->next && ic->next->op == GOTO
2968 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2969 && labelRange <= 10)
2971 emitcode (";", "tail increment optimized");
2972 tlbl = IC_LABEL (ic->next);
2977 tlbl = newiTempLabel (NULL);
2980 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2981 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2982 IS_AOP_PREG (IC_RESULT (ic)))
2983 emitcode ("cjne", "%s,#0x00,%05d$",
2984 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2988 emitcode ("clr", "a");
2989 emitcode ("cjne", "a,%s,%05d$",
2990 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2994 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2997 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2998 IS_AOP_PREG (IC_RESULT (ic)))
2999 emitcode ("cjne", "%s,#0x00,%05d$",
3000 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3003 emitcode ("cjne", "a,%s,%05d$",
3004 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3007 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3011 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3012 IS_AOP_PREG (IC_RESULT (ic)))
3013 emitcode ("cjne", "%s,#0x00,%05d$",
3014 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3018 emitcode ("cjne", "a,%s,%05d$",
3019 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3022 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3027 emitcode ("", "%05d$:", tlbl->key + 100);
3032 /* if the sizes are greater than 1 then we cannot */
3033 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3034 AOP_SIZE (IC_LEFT (ic)) > 1)
3037 /* we can if the aops of the left & result match or
3038 if they are in registers and the registers are the
3040 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3045 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3046 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3047 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3053 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3062 /*-----------------------------------------------------------------*/
3063 /* outBitAcc - output a bit in acc */
3064 /*-----------------------------------------------------------------*/
3066 outBitAcc (operand * result)
3068 symbol *tlbl = newiTempLabel (NULL);
3069 /* if the result is a bit */
3070 if (AOP_TYPE (result) == AOP_CRY)
3072 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3076 emitcode ("jz", "%05d$", tlbl->key + 100);
3077 emitcode ("mov", "a,%s", one);
3078 emitcode ("", "%05d$:", tlbl->key + 100);
3083 /*-----------------------------------------------------------------*/
3084 /* genPlusBits - generates code for addition of two bits */
3085 /*-----------------------------------------------------------------*/
3087 genPlusBits (iCode * ic)
3089 D(emitcode ("; genPlusBits",""));
3091 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3093 symbol *lbl = newiTempLabel (NULL);
3094 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3095 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3096 emitcode ("cpl", "c");
3097 emitcode ("", "%05d$:", (lbl->key + 100));
3098 outBitC (IC_RESULT (ic));
3102 emitcode ("clr", "a");
3103 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3104 emitcode ("rlc", "a");
3105 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3106 emitcode ("addc", "a,#0x00");
3107 outAcc (IC_RESULT (ic));
3112 /* This is the original version of this code.
3114 * This is being kept around for reference,
3115 * because I am not entirely sure I got it right...
3118 adjustArithmeticResult (iCode * ic)
3120 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3121 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3122 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3123 aopPut (AOP (IC_RESULT (ic)),
3124 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3126 isOperandVolatile (IC_RESULT (ic), FALSE));
3128 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3129 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3130 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3131 aopPut (AOP (IC_RESULT (ic)),
3132 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3134 isOperandVolatile (IC_RESULT (ic), FALSE));
3136 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3137 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3138 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3139 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3140 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3143 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3144 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3148 /* This is the pure and virtuous version of this code.
3149 * I'm pretty certain it's right, but not enough to toss the old
3153 adjustArithmeticResult (iCode * ic)
3155 if (opIsGptr (IC_RESULT (ic)) &&
3156 opIsGptr (IC_LEFT (ic)) &&
3157 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3159 aopPut (AOP (IC_RESULT (ic)),
3160 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3162 isOperandVolatile (IC_RESULT (ic), FALSE));
3165 if (opIsGptr (IC_RESULT (ic)) &&
3166 opIsGptr (IC_RIGHT (ic)) &&
3167 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3169 aopPut (AOP (IC_RESULT (ic)),
3170 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3172 isOperandVolatile (IC_RESULT (ic), FALSE));
3175 if (opIsGptr (IC_RESULT (ic)) &&
3176 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3177 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3178 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3179 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3182 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3183 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3188 /*-----------------------------------------------------------------*/
3189 /* genPlus - generates code for addition */
3190 /*-----------------------------------------------------------------*/
3192 genPlus (iCode * ic)
3194 int size, offset = 0;
3197 asmop *leftOp, *rightOp;
3199 /* special cases :- */
3201 D(emitcode ("; genPlus",""));
3203 aopOp (IC_LEFT (ic), ic, FALSE);
3204 aopOp (IC_RIGHT (ic), ic, FALSE);
3205 aopOp (IC_RESULT (ic), ic, TRUE);
3207 /* if literal, literal on the right or
3208 if left requires ACC or right is already
3210 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3211 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3212 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3214 operand *t = IC_RIGHT (ic);
3215 IC_RIGHT (ic) = IC_LEFT (ic);
3219 /* if both left & right are in bit
3221 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3222 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3228 /* if left in bit space & right literal */
3229 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3230 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3232 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3233 /* if result in bit space */
3234 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3236 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3237 emitcode ("cpl", "c");
3238 outBitC (IC_RESULT (ic));
3242 size = getDataSize (IC_RESULT (ic));
3245 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3246 emitcode ("addc", "a,#00");
3247 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3253 /* if I can do an increment instead
3254 of add then GOOD for ME */
3255 if (genPlusIncr (ic) == TRUE)
3258 size = getDataSize (IC_RESULT (ic));
3260 /* if the lower bytes of a literal are zero skip the addition */
3261 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3263 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3264 (skip_bytes+1 < size))
3269 D(emitcode ("; genPlus shortcut",""));
3272 leftOp = AOP(IC_LEFT(ic));
3273 rightOp = AOP(IC_RIGHT(ic));
3277 if( offset >= skip_bytes )
3279 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3281 emitcode("mov", "b,a");
3282 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3283 emitcode("xch", "a,b");
3284 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3285 emitcode (add, "a,b");
3287 else if (aopGetUsesAcc (leftOp, offset))
3289 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3290 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3294 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3295 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3297 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3298 add = "addc"; /* further adds must propagate carry */
3302 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3303 isOperandVolatile (IC_RESULT (ic), FALSE))
3306 aopPut (AOP (IC_RESULT (ic)),
3307 aopGet (leftOp, offset, FALSE, FALSE),
3309 isOperandVolatile (IC_RESULT (ic), FALSE));
3315 adjustArithmeticResult (ic);
3318 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3319 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3320 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3323 /*-----------------------------------------------------------------*/
3324 /* genMinusDec :- does subtraction with deccrement if possible */
3325 /*-----------------------------------------------------------------*/
3327 genMinusDec (iCode * ic)
3329 unsigned int icount;
3330 unsigned int size = getDataSize (IC_RESULT (ic));
3332 /* will try to generate an increment */
3333 /* if the right side is not a literal
3335 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3338 /* if the literal value of the right hand side
3339 is greater than 4 then it is not worth it */
3340 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3343 D(emitcode ("; genMinusDec",""));
3345 /* if decrement >=16 bits in register or direct space */
3346 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3347 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3355 /* If the next instruction is a goto and the goto target
3356 * is <= 10 instructions previous to this, we can generate
3357 * jumps straight to that target.
3359 if (ic->next && ic->next->op == GOTO
3360 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3361 && labelRange <= 10)
3363 emitcode (";", "tail decrement optimized");
3364 tlbl = IC_LABEL (ic->next);
3369 tlbl = newiTempLabel (NULL);
3373 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3374 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3375 IS_AOP_PREG (IC_RESULT (ic)))
3376 emitcode ("cjne", "%s,#0xff,%05d$"
3377 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3381 emitcode ("mov", "a,#0xff");
3382 emitcode ("cjne", "a,%s,%05d$"
3383 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3386 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3389 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3390 IS_AOP_PREG (IC_RESULT (ic)))
3391 emitcode ("cjne", "%s,#0xff,%05d$"
3392 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3396 emitcode ("cjne", "a,%s,%05d$"
3397 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3400 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3404 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3405 IS_AOP_PREG (IC_RESULT (ic)))
3406 emitcode ("cjne", "%s,#0xff,%05d$"
3407 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3411 emitcode ("cjne", "a,%s,%05d$"
3412 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3415 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3419 emitcode ("", "%05d$:", tlbl->key + 100);
3424 /* if the sizes are greater than 1 then we cannot */
3425 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3426 AOP_SIZE (IC_LEFT (ic)) > 1)
3429 /* we can if the aops of the left & result match or
3430 if they are in registers and the registers are the
3432 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3436 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3444 /*-----------------------------------------------------------------*/
3445 /* addSign - complete with sign */
3446 /*-----------------------------------------------------------------*/
3448 addSign (operand * result, int offset, int sign)
3450 int size = (getDataSize (result) - offset);
3455 emitcode ("rlc", "a");
3456 emitcode ("subb", "a,acc");
3458 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3462 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3466 /*-----------------------------------------------------------------*/
3467 /* genMinusBits - generates code for subtraction of two bits */
3468 /*-----------------------------------------------------------------*/
3470 genMinusBits (iCode * ic)
3472 symbol *lbl = newiTempLabel (NULL);
3474 D(emitcode ("; genMinusBits",""));
3476 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3478 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3479 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3480 emitcode ("cpl", "c");
3481 emitcode ("", "%05d$:", (lbl->key + 100));
3482 outBitC (IC_RESULT (ic));
3486 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3487 emitcode ("subb", "a,acc");
3488 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3489 emitcode ("inc", "a");
3490 emitcode ("", "%05d$:", (lbl->key + 100));
3491 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3492 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3496 /*-----------------------------------------------------------------*/
3497 /* genMinus - generates code for subtraction */
3498 /*-----------------------------------------------------------------*/
3500 genMinus (iCode * ic)
3502 int size, offset = 0;
3504 D(emitcode ("; genMinus",""));
3506 aopOp (IC_LEFT (ic), ic, FALSE);
3507 aopOp (IC_RIGHT (ic), ic, FALSE);
3508 aopOp (IC_RESULT (ic), ic, TRUE);
3510 /* special cases :- */
3511 /* if both left & right are in bit space */
3512 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3513 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3519 /* if I can do an decrement instead
3520 of subtract then GOOD for ME */
3521 if (genMinusDec (ic) == TRUE)
3524 size = getDataSize (IC_RESULT (ic));
3526 /* if literal, add a,#-lit, else normal subb */
3527 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3529 unsigned long lit = 0L;
3531 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3536 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3537 /* first add without previous c */
3539 if (!size && lit== (unsigned long) -1) {
3540 emitcode ("dec", "a");
3542 emitcode ("add", "a,#0x%02x",
3543 (unsigned int) (lit & 0x0FFL));
3546 emitcode ("addc", "a,#0x%02x",
3547 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3549 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3554 asmop *leftOp, *rightOp;
3556 leftOp = AOP(IC_LEFT(ic));
3557 rightOp = AOP(IC_RIGHT(ic));
3561 if (aopGetUsesAcc(rightOp, offset)) {
3562 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3563 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3565 emitcode( "setb", "c");
3567 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3568 emitcode("cpl", "a");
3570 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3573 emitcode ("subb", "a,%s",
3574 aopGet(rightOp, offset, FALSE, TRUE));
3577 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3582 adjustArithmeticResult (ic);
3585 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3586 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3587 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3591 /*-----------------------------------------------------------------*/
3592 /* genMultbits :- multiplication of bits */
3593 /*-----------------------------------------------------------------*/
3595 genMultbits (operand * left,
3599 D(emitcode ("; genMultbits",""));
3601 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3602 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3607 /*-----------------------------------------------------------------*/
3608 /* genMultOneByte : 8*8=8/16 bit multiplication */
3609 /*-----------------------------------------------------------------*/
3611 genMultOneByte (operand * left,
3615 sym_link *opetype = operandType (result);
3617 int size=AOP_SIZE(result);
3619 D(emitcode ("; genMultOneByte",""));
3621 if (size<1 || size>2) {
3622 // this should never happen
3623 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3624 AOP_SIZE(result), __FILE__, lineno);
3628 /* (if two literals: the value is computed before) */
3629 /* if one literal, literal on the right */
3630 if (AOP_TYPE (left) == AOP_LIT)
3635 //emitcode (";", "swapped left and right");
3638 if (SPEC_USIGN(opetype)
3639 // ignore the sign of left and right, what else can we do?
3640 || (SPEC_USIGN(operandType(left)) &&
3641 SPEC_USIGN(operandType(right)))) {
3642 // just an unsigned 8*8=8/16 multiply
3643 //emitcode (";","unsigned");
3644 // TODO: check for accumulator clash between left & right aops?
3646 if( AOP_TYPE(right)==AOP_LIT ){
3647 // moving to accumulator first helps peepholes
3648 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3649 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3651 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3652 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3655 emitcode ("mul", "ab");
3656 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3658 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3663 // we have to do a signed multiply
3665 //emitcode (";", "signed");
3666 emitcode ("clr", "F0"); // reset sign flag
3667 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3669 lbl=newiTempLabel(NULL);
3670 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3671 // left side is negative, 8-bit two's complement, this fails for -128
3672 emitcode ("setb", "F0"); // set sign flag
3673 emitcode ("cpl", "a");
3674 emitcode ("inc", "a");
3676 emitcode ("", "%05d$:", lbl->key+100);
3679 if (AOP_TYPE(right)==AOP_LIT) {
3680 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3681 /* AND literal negative */
3683 emitcode ("cpl", "F0"); // complement sign flag
3684 emitcode ("mov", "b,#0x%02x", -val);
3686 emitcode ("mov", "b,#0x%02x", val);
3689 lbl=newiTempLabel(NULL);
3690 emitcode ("mov", "b,a");
3691 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3692 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3693 // right side is negative, 8-bit two's complement
3694 emitcode ("cpl", "F0"); // complement sign flag
3695 emitcode ("cpl", "a");
3696 emitcode ("inc", "a");
3697 emitcode ("", "%05d$:", lbl->key+100);
3699 emitcode ("mul", "ab");
3701 lbl=newiTempLabel(NULL);
3702 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3703 // only ONE op was negative, we have to do a 8/16-bit two's complement
3704 emitcode ("cpl", "a"); // lsb
3706 emitcode ("inc", "a");
3708 emitcode ("add", "a,#1");
3709 emitcode ("xch", "a,b");
3710 emitcode ("cpl", "a"); // msb
3711 emitcode ("addc", "a,#0");
3712 emitcode ("xch", "a,b");
3715 emitcode ("", "%05d$:", lbl->key+100);
3716 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3718 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3722 /*-----------------------------------------------------------------*/
3723 /* genMult - generates code for multiplication */
3724 /*-----------------------------------------------------------------*/
3726 genMult (iCode * ic)
3728 operand *left = IC_LEFT (ic);
3729 operand *right = IC_RIGHT (ic);
3730 operand *result = IC_RESULT (ic);
3732 D(emitcode ("; genMult",""));
3734 /* assign the amsops */
3735 aopOp (left, ic, FALSE);
3736 aopOp (right, ic, FALSE);
3737 aopOp (result, ic, TRUE);
3739 /* special cases first */
3741 if (AOP_TYPE (left) == AOP_CRY &&
3742 AOP_TYPE (right) == AOP_CRY)
3744 genMultbits (left, right, result);
3748 /* if both are of size == 1 */
3749 #if 0 // one of them can be a sloc shared with the result
3750 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3752 if (getSize(operandType(left)) == 1 &&
3753 getSize(operandType(right)) == 1)
3756 genMultOneByte (left, right, result);
3760 /* should have been converted to function call */
3761 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3762 getSize(OP_SYMBOL(right)->type));
3766 freeAsmop (result, NULL, ic, TRUE);
3767 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3768 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3771 /*-----------------------------------------------------------------*/
3772 /* genDivbits :- division of bits */
3773 /*-----------------------------------------------------------------*/
3775 genDivbits (operand * left,
3782 D(emitcode ("; genDivbits",""));
3784 /* the result must be bit */
3785 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3786 l = aopGet (AOP (left), 0, FALSE, FALSE);
3790 emitcode ("div", "ab");
3791 emitcode ("rrc", "a");
3792 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3795 /*-----------------------------------------------------------------*/
3796 /* genDivOneByte : 8 bit division */
3797 /*-----------------------------------------------------------------*/
3799 genDivOneByte (operand * left,
3803 sym_link *opetype = operandType (result);
3808 D(emitcode ("; genDivOneByte",""));
3810 size = AOP_SIZE (result) - 1;
3812 /* signed or unsigned */
3813 if (SPEC_USIGN (opetype))
3815 /* unsigned is easy */
3816 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3817 l = aopGet (AOP (left), 0, FALSE, FALSE);
3819 emitcode ("div", "ab");
3820 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3822 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3826 /* signed is a little bit more difficult */
3828 /* save the signs of the operands */
3829 l = aopGet (AOP (left), 0, FALSE, FALSE);
3831 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3832 emitcode ("push", "acc"); /* save it on the stack */
3834 /* now sign adjust for both left & right */
3835 l = aopGet (AOP (right), 0, FALSE, FALSE);
3837 lbl = newiTempLabel (NULL);
3838 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3839 emitcode ("cpl", "a");
3840 emitcode ("inc", "a");
3841 emitcode ("", "%05d$:", (lbl->key + 100));
3842 emitcode ("mov", "b,a");
3844 /* sign adjust left side */
3845 l = aopGet (AOP (left), 0, FALSE, FALSE);
3848 lbl = newiTempLabel (NULL);
3849 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3850 emitcode ("cpl", "a");
3851 emitcode ("inc", "a");
3852 emitcode ("", "%05d$:", (lbl->key + 100));
3854 /* now the division */
3855 emitcode ("div", "ab");
3856 /* we are interested in the lower order
3858 emitcode ("mov", "b,a");
3859 lbl = newiTempLabel (NULL);
3860 emitcode ("pop", "acc");
3861 /* if there was an over flow we don't
3862 adjust the sign of the result */
3863 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3864 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3866 emitcode ("clr", "a");
3867 emitcode ("subb", "a,b");
3868 emitcode ("mov", "b,a");
3869 emitcode ("", "%05d$:", (lbl->key + 100));
3871 /* now we are done */
3872 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3875 emitcode ("mov", "c,b.7");
3876 emitcode ("subb", "a,acc");
3879 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3883 /*-----------------------------------------------------------------*/
3884 /* genDiv - generates code for division */
3885 /*-----------------------------------------------------------------*/
3889 operand *left = IC_LEFT (ic);
3890 operand *right = IC_RIGHT (ic);
3891 operand *result = IC_RESULT (ic);
3893 D(emitcode ("; genDiv",""));
3895 /* assign the amsops */
3896 aopOp (left, ic, FALSE);
3897 aopOp (right, ic, FALSE);
3898 aopOp (result, ic, TRUE);
3900 /* special cases first */
3902 if (AOP_TYPE (left) == AOP_CRY &&
3903 AOP_TYPE (right) == AOP_CRY)
3905 genDivbits (left, right, result);
3909 /* if both are of size == 1 */
3910 if (AOP_SIZE (left) == 1 &&
3911 AOP_SIZE (right) == 1)
3913 genDivOneByte (left, right, result);
3917 /* should have been converted to function call */
3920 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3921 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3922 freeAsmop (result, NULL, ic, TRUE);
3925 /*-----------------------------------------------------------------*/
3926 /* genModbits :- modulus of bits */
3927 /*-----------------------------------------------------------------*/
3929 genModbits (operand * left,
3936 D(emitcode ("; genModbits",""));
3938 /* the result must be bit */
3939 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3940 l = aopGet (AOP (left), 0, FALSE, FALSE);
3944 emitcode ("div", "ab");
3945 emitcode ("mov", "a,b");
3946 emitcode ("rrc", "a");
3947 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3950 /*-----------------------------------------------------------------*/
3951 /* genModOneByte : 8 bit modulus */
3952 /*-----------------------------------------------------------------*/
3954 genModOneByte (operand * left,
3958 sym_link *opetype = operandType (result);
3962 D(emitcode ("; genModOneByte",""));
3964 /* signed or unsigned */
3965 if (SPEC_USIGN (opetype))
3967 /* unsigned is easy */
3968 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3969 l = aopGet (AOP (left), 0, FALSE, FALSE);
3971 emitcode ("div", "ab");
3972 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3976 /* signed is a little bit more difficult */
3978 /* save the signs of the operands */
3979 l = aopGet (AOP (left), 0, FALSE, FALSE);
3982 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3983 emitcode ("push", "acc"); /* save it on the stack */
3985 /* now sign adjust for both left & right */
3986 l = aopGet (AOP (right), 0, FALSE, FALSE);
3989 lbl = newiTempLabel (NULL);
3990 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3991 emitcode ("cpl", "a");
3992 emitcode ("inc", "a");
3993 emitcode ("", "%05d$:", (lbl->key + 100));
3994 emitcode ("mov", "b,a");
3996 /* sign adjust left side */
3997 l = aopGet (AOP (left), 0, FALSE, FALSE);
4000 lbl = newiTempLabel (NULL);
4001 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4002 emitcode ("cpl", "a");
4003 emitcode ("inc", "a");
4004 emitcode ("", "%05d$:", (lbl->key + 100));
4006 /* now the multiplication */
4007 emitcode ("div", "ab");
4008 /* we are interested in the lower order
4010 lbl = newiTempLabel (NULL);
4011 emitcode ("pop", "acc");
4012 /* if there was an over flow we don't
4013 adjust the sign of the result */
4014 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
4015 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4017 emitcode ("clr", "a");
4018 emitcode ("subb", "a,b");
4019 emitcode ("mov", "b,a");
4020 emitcode ("", "%05d$:", (lbl->key + 100));
4022 /* now we are done */
4023 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4027 /*-----------------------------------------------------------------*/
4028 /* genMod - generates code for division */
4029 /*-----------------------------------------------------------------*/
4033 operand *left = IC_LEFT (ic);
4034 operand *right = IC_RIGHT (ic);
4035 operand *result = IC_RESULT (ic);
4037 D(emitcode ("; genMod",""));
4039 /* assign the amsops */
4040 aopOp (left, ic, FALSE);
4041 aopOp (right, ic, FALSE);
4042 aopOp (result, ic, TRUE);
4044 /* special cases first */
4046 if (AOP_TYPE (left) == AOP_CRY &&
4047 AOP_TYPE (right) == AOP_CRY)
4049 genModbits (left, right, result);
4053 /* if both are of size == 1 */
4054 if (AOP_SIZE (left) == 1 &&
4055 AOP_SIZE (right) == 1)
4057 genModOneByte (left, right, result);
4061 /* should have been converted to function call */
4065 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4066 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4067 freeAsmop (result, NULL, ic, TRUE);
4070 /*-----------------------------------------------------------------*/
4071 /* genIfxJump :- will create a jump depending on the ifx */
4072 /*-----------------------------------------------------------------*/
4074 genIfxJump (iCode * ic, char *jval)
4077 symbol *tlbl = newiTempLabel (NULL);
4080 D(emitcode ("; genIfxJump",""));
4082 /* if true label then we jump if condition
4086 jlbl = IC_TRUE (ic);
4087 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4088 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4092 /* false label is present */
4093 jlbl = IC_FALSE (ic);
4094 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4095 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4097 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4098 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4100 emitcode (inst, "%05d$", tlbl->key + 100);
4101 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4102 emitcode ("", "%05d$:", tlbl->key + 100);
4104 /* mark the icode as generated */
4108 /*-----------------------------------------------------------------*/
4109 /* genCmp :- greater or less than comparison */
4110 /*-----------------------------------------------------------------*/
4112 genCmp (operand * left, operand * right,
4113 operand * result, iCode * ifx, int sign, iCode *ic)
4115 int size, offset = 0;
4116 unsigned long lit = 0L;
4119 D(emitcode ("; genCmp",""));
4121 /* if left & right are bit variables */
4122 if (AOP_TYPE (left) == AOP_CRY &&
4123 AOP_TYPE (right) == AOP_CRY)
4125 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4126 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4130 /* subtract right from left if at the
4131 end the carry flag is set then we know that
4132 left is greater than right */
4133 size = max (AOP_SIZE (left), AOP_SIZE (right));
4135 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4136 if ((size == 1) && !sign &&
4137 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4139 symbol *lbl = newiTempLabel (NULL);
4140 emitcode ("cjne", "%s,%s,%05d$",
4141 aopGet (AOP (left), offset, FALSE, FALSE),
4142 aopGet (AOP (right), offset, FALSE, FALSE),
4144 emitcode ("", "%05d$:", lbl->key + 100);
4148 if (AOP_TYPE (right) == AOP_LIT)
4150 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4151 /* optimize if(x < 0) or if(x >= 0) */
4160 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4161 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4163 genIfxJump (ifx, "acc.7");
4167 emitcode ("rlc", "a");
4175 rightInB = aopGetUsesAcc(AOP (right), offset);
4177 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4178 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4179 if (sign && size == 0)
4181 emitcode ("xrl", "a,#0x80");
4182 if (AOP_TYPE (right) == AOP_LIT)
4184 unsigned long lit = (unsigned long)
4185 floatFromVal (AOP (right)->aopu.aop_lit);
4186 emitcode ("subb", "a,#0x%02x",
4187 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4192 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4193 emitcode ("xrl", "b,#0x80");
4194 emitcode ("subb", "a,b");
4200 emitcode ("subb", "a,b");
4202 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4210 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4211 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4212 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4218 /* if the result is used in the next
4219 ifx conditional branch then generate
4220 code a little differently */
4222 genIfxJump (ifx, "c");
4225 /* leave the result in acc */
4229 /*-----------------------------------------------------------------*/
4230 /* genCmpGt :- greater than comparison */
4231 /*-----------------------------------------------------------------*/
4233 genCmpGt (iCode * ic, iCode * ifx)
4235 operand *left, *right, *result;
4236 sym_link *letype, *retype;
4239 D(emitcode ("; genCmpGt",""));
4241 left = IC_LEFT (ic);
4242 right = IC_RIGHT (ic);
4243 result = IC_RESULT (ic);
4245 letype = getSpec (operandType (left));
4246 retype = getSpec (operandType (right));
4247 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4248 /* assign the amsops */
4249 aopOp (left, ic, FALSE);
4250 aopOp (right, ic, FALSE);
4251 aopOp (result, ic, TRUE);
4253 genCmp (right, left, result, ifx, sign,ic);
4255 freeAsmop (result, NULL, ic, TRUE);
4258 /*-----------------------------------------------------------------*/
4259 /* genCmpLt - less than comparisons */
4260 /*-----------------------------------------------------------------*/
4262 genCmpLt (iCode * ic, iCode * ifx)
4264 operand *left, *right, *result;
4265 sym_link *letype, *retype;
4268 D(emitcode ("; genCmpLt",""));
4270 left = IC_LEFT (ic);
4271 right = IC_RIGHT (ic);
4272 result = IC_RESULT (ic);
4274 letype = getSpec (operandType (left));
4275 retype = getSpec (operandType (right));
4276 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4278 /* assign the amsops */
4279 aopOp (left, ic, FALSE);
4280 aopOp (right, ic, FALSE);
4281 aopOp (result, ic, TRUE);
4283 genCmp (left, right, result, ifx, sign,ic);
4285 freeAsmop (result, NULL, ic, TRUE);
4288 /*-----------------------------------------------------------------*/
4289 /* gencjneshort - compare and jump if not equal */
4290 /*-----------------------------------------------------------------*/
4292 gencjneshort (operand * left, operand * right, symbol * lbl)
4294 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4296 unsigned long lit = 0L;
4298 /* if the left side is a literal or
4299 if the right is in a pointer register and left
4301 if ((AOP_TYPE (left) == AOP_LIT) ||
4302 (AOP_TYPE (left) == AOP_IMMD) ||
4303 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4310 if (AOP_TYPE (right) == AOP_LIT)
4311 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4313 /* if the right side is a literal then anything goes */
4314 if (AOP_TYPE (right) == AOP_LIT &&
4315 AOP_TYPE (left) != AOP_DIR &&
4316 AOP_TYPE (left) != AOP_IMMD)
4320 emitcode ("cjne", "%s,%s,%05d$",
4321 aopGet (AOP (left), offset, FALSE, FALSE),
4322 aopGet (AOP (right), offset, FALSE, FALSE),
4328 /* if the right side is in a register or in direct space or
4329 if the left is a pointer register & right is not */
4330 else if (AOP_TYPE (right) == AOP_REG ||
4331 AOP_TYPE (right) == AOP_DIR ||
4332 AOP_TYPE (right) == AOP_LIT ||
4333 AOP_TYPE (right) == AOP_IMMD ||
4334 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4335 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4339 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4340 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4341 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4342 emitcode ("jnz", "%05d$", lbl->key + 100);
4344 emitcode ("cjne", "a,%s,%05d$",
4345 aopGet (AOP (right), offset, FALSE, TRUE),
4352 /* right is a pointer reg need both a & b */
4355 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4356 if (strcmp (l, "b"))
4357 emitcode ("mov", "b,%s", l);
4358 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4359 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4365 /*-----------------------------------------------------------------*/
4366 /* gencjne - compare and jump if not equal */
4367 /*-----------------------------------------------------------------*/
4369 gencjne (operand * left, operand * right, symbol * lbl)
4371 symbol *tlbl = newiTempLabel (NULL);
4373 gencjneshort (left, right, lbl);
4375 emitcode ("mov", "a,%s", one);
4376 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4377 emitcode ("", "%05d$:", lbl->key + 100);
4378 emitcode ("clr", "a");
4379 emitcode ("", "%05d$:", tlbl->key + 100);
4382 /*-----------------------------------------------------------------*/
4383 /* genCmpEq - generates code for equal to */
4384 /*-----------------------------------------------------------------*/
4386 genCmpEq (iCode * ic, iCode * ifx)
4388 operand *left, *right, *result;
4390 D(emitcode ("; genCmpEq",""));
4392 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4393 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4394 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4396 /* if literal, literal on the right or
4397 if the right is in a pointer register and left
4399 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4400 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4402 operand *t = IC_RIGHT (ic);
4403 IC_RIGHT (ic) = IC_LEFT (ic);
4407 if (ifx && !AOP_SIZE (result))
4410 /* if they are both bit variables */
4411 if (AOP_TYPE (left) == AOP_CRY &&
4412 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4414 if (AOP_TYPE (right) == AOP_LIT)
4416 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4419 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4420 emitcode ("cpl", "c");
4424 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4428 emitcode ("clr", "c");
4430 /* AOP_TYPE(right) == AOP_CRY */
4434 symbol *lbl = newiTempLabel (NULL);
4435 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4436 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4437 emitcode ("cpl", "c");
4438 emitcode ("", "%05d$:", (lbl->key + 100));
4440 /* if true label then we jump if condition
4442 tlbl = newiTempLabel (NULL);
4445 emitcode ("jnc", "%05d$", tlbl->key + 100);
4446 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4450 emitcode ("jc", "%05d$", tlbl->key + 100);
4451 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4453 emitcode ("", "%05d$:", tlbl->key + 100);
4457 tlbl = newiTempLabel (NULL);
4458 gencjneshort (left, right, tlbl);
4461 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4462 emitcode ("", "%05d$:", tlbl->key + 100);
4466 symbol *lbl = newiTempLabel (NULL);
4467 emitcode ("sjmp", "%05d$", lbl->key + 100);
4468 emitcode ("", "%05d$:", tlbl->key + 100);
4469 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4470 emitcode ("", "%05d$:", lbl->key + 100);
4473 /* mark the icode as generated */
4478 /* if they are both bit variables */
4479 if (AOP_TYPE (left) == AOP_CRY &&
4480 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4482 if (AOP_TYPE (right) == AOP_LIT)
4484 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4487 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4488 emitcode ("cpl", "c");
4492 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4496 emitcode ("clr", "c");
4498 /* AOP_TYPE(right) == AOP_CRY */
4502 symbol *lbl = newiTempLabel (NULL);
4503 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4504 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4505 emitcode ("cpl", "c");
4506 emitcode ("", "%05d$:", (lbl->key + 100));
4509 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4516 genIfxJump (ifx, "c");
4519 /* if the result is used in an arithmetic operation
4520 then put the result in place */
4525 gencjne (left, right, newiTempLabel (NULL));
4526 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4528 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4533 genIfxJump (ifx, "a");
4536 /* if the result is used in an arithmetic operation
4537 then put the result in place */
4538 if (AOP_TYPE (result) != AOP_CRY)
4540 /* leave the result in acc */
4544 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4545 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4546 freeAsmop (result, NULL, ic, TRUE);
4549 /*-----------------------------------------------------------------*/
4550 /* ifxForOp - returns the icode containing the ifx for operand */
4551 /*-----------------------------------------------------------------*/
4553 ifxForOp (operand * op, iCode * ic)
4555 /* if true symbol then needs to be assigned */
4556 if (IS_TRUE_SYMOP (op))
4559 /* if this has register type condition and
4560 the next instruction is ifx with the same operand
4561 and live to of the operand is upto the ifx only then */
4563 ic->next->op == IFX &&
4564 IC_COND (ic->next)->key == op->key &&
4565 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4571 /*-----------------------------------------------------------------*/
4572 /* hasInc - operand is incremented before any other use */
4573 /*-----------------------------------------------------------------*/
4575 hasInc (operand *op, iCode *ic,int osize)
4577 sym_link *type = operandType(op);
4578 sym_link *retype = getSpec (type);
4579 iCode *lic = ic->next;
4582 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4583 if (!IS_SYMOP(op)) return NULL;
4585 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4586 if (IS_AGGREGATE(type->next)) return NULL;
4587 if (osize != (isize = getSize(type->next))) return NULL;
4590 /* if operand of the form op = op + <sizeof *op> */
4591 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4592 isOperandEqual(IC_RESULT(lic),op) &&
4593 isOperandLiteral(IC_RIGHT(lic)) &&
4594 operandLitValue(IC_RIGHT(lic)) == isize) {
4597 /* if the operand used or deffed */
4598 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4601 /* if GOTO or IFX */
4602 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4608 /*-----------------------------------------------------------------*/
4609 /* genAndOp - for && operation */
4610 /*-----------------------------------------------------------------*/
4612 genAndOp (iCode * ic)
4614 operand *left, *right, *result;
4617 D(emitcode ("; genAndOp",""));
4619 /* note here that && operations that are in an
4620 if statement are taken away by backPatchLabels
4621 only those used in arthmetic operations remain */
4622 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4623 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4624 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4626 /* if both are bit variables */
4627 if (AOP_TYPE (left) == AOP_CRY &&
4628 AOP_TYPE (right) == AOP_CRY)
4630 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4631 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4636 tlbl = newiTempLabel (NULL);
4638 emitcode ("jz", "%05d$", tlbl->key + 100);
4640 emitcode ("", "%05d$:", tlbl->key + 100);
4644 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4645 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4646 freeAsmop (result, NULL, ic, TRUE);
4650 /*-----------------------------------------------------------------*/
4651 /* genOrOp - for || operation */
4652 /*-----------------------------------------------------------------*/
4654 genOrOp (iCode * ic)
4656 operand *left, *right, *result;
4659 D(emitcode ("; genOrOp",""));
4661 /* note here that || operations that are in an
4662 if statement are taken away by backPatchLabels
4663 only those used in arthmetic operations remain */
4664 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4665 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4666 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4668 /* if both are bit variables */
4669 if (AOP_TYPE (left) == AOP_CRY &&
4670 AOP_TYPE (right) == AOP_CRY)
4672 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4673 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4678 tlbl = newiTempLabel (NULL);
4680 emitcode ("jnz", "%05d$", tlbl->key + 100);
4682 emitcode ("", "%05d$:", tlbl->key + 100);
4686 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4687 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4688 freeAsmop (result, NULL, ic, TRUE);
4691 /*-----------------------------------------------------------------*/
4692 /* isLiteralBit - test if lit == 2^n */
4693 /*-----------------------------------------------------------------*/
4695 isLiteralBit (unsigned long lit)
4697 unsigned long pw[32] =
4698 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4699 0x100L, 0x200L, 0x400L, 0x800L,
4700 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4701 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4702 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4703 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4704 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4707 for (idx = 0; idx < 32; idx++)
4713 /*-----------------------------------------------------------------*/
4714 /* continueIfTrue - */
4715 /*-----------------------------------------------------------------*/
4717 continueIfTrue (iCode * ic)
4720 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4724 /*-----------------------------------------------------------------*/
4726 /*-----------------------------------------------------------------*/
4728 jumpIfTrue (iCode * ic)
4731 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4735 /*-----------------------------------------------------------------*/
4736 /* jmpTrueOrFalse - */
4737 /*-----------------------------------------------------------------*/
4739 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4741 // ugly but optimized by peephole
4744 symbol *nlbl = newiTempLabel (NULL);
4745 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4746 emitcode ("", "%05d$:", tlbl->key + 100);
4747 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4748 emitcode ("", "%05d$:", nlbl->key + 100);
4752 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4753 emitcode ("", "%05d$:", tlbl->key + 100);
4758 /*-----------------------------------------------------------------*/
4759 /* genAnd - code for and */
4760 /*-----------------------------------------------------------------*/
4762 genAnd (iCode * ic, iCode * ifx)
4764 operand *left, *right, *result;
4765 int size, offset = 0;
4766 unsigned long lit = 0L;
4770 D(emitcode ("; genAnd",""));
4772 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4773 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4774 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4777 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4779 AOP_TYPE (left), AOP_TYPE (right));
4780 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4782 AOP_SIZE (left), AOP_SIZE (right));
4785 /* if left is a literal & right is not then exchange them */
4786 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4787 AOP_NEEDSACC (left))
4789 operand *tmp = right;
4794 /* if result = right then exchange them */
4795 if (sameRegs (AOP (result), AOP (right)))
4797 operand *tmp = right;
4802 /* if right is bit then exchange them */
4803 if (AOP_TYPE (right) == AOP_CRY &&
4804 AOP_TYPE (left) != AOP_CRY)
4806 operand *tmp = right;
4810 if (AOP_TYPE (right) == AOP_LIT)
4811 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4813 size = AOP_SIZE (result);
4816 // result = bit & yy;
4817 if (AOP_TYPE (left) == AOP_CRY)
4819 // c = bit & literal;
4820 if (AOP_TYPE (right) == AOP_LIT)
4824 if (size && sameRegs (AOP (result), AOP (left)))
4827 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4832 if (size && (AOP_TYPE (result) == AOP_CRY))
4834 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4837 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4842 emitcode ("clr", "c");
4847 if (AOP_TYPE (right) == AOP_CRY)
4850 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4851 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4856 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4858 emitcode ("rrc", "a");
4859 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4867 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4868 genIfxJump (ifx, "c");
4872 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4873 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4874 if ((AOP_TYPE (right) == AOP_LIT) &&
4875 (AOP_TYPE (result) == AOP_CRY) &&
4876 (AOP_TYPE (left) != AOP_CRY))
4878 int posbit = isLiteralBit (lit);
4883 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4886 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4892 sprintf (buffer, "acc.%d", posbit & 0x07);
4893 genIfxJump (ifx, buffer);
4900 symbol *tlbl = newiTempLabel (NULL);
4901 int sizel = AOP_SIZE (left);
4903 emitcode ("setb", "c");
4906 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4908 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4910 if ((posbit = isLiteralBit (bytelit)) != 0)
4911 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4914 if (bytelit != 0x0FFL)
4915 emitcode ("anl", "a,%s",
4916 aopGet (AOP (right), offset, FALSE, TRUE));
4917 emitcode ("jnz", "%05d$", tlbl->key + 100);
4922 // bit = left & literal
4925 emitcode ("clr", "c");
4926 emitcode ("", "%05d$:", tlbl->key + 100);
4928 // if(left & literal)
4932 jmpTrueOrFalse (ifx, tlbl);
4934 emitcode ("", "%05d$:", tlbl->key + 100);
4942 /* if left is same as result */
4943 if (sameRegs (AOP (result), AOP (left)))
4945 for (; size--; offset++)
4947 if (AOP_TYPE (right) == AOP_LIT)
4949 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4951 else if (bytelit == 0)
4953 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4955 else if (IS_AOP_PREG (result))
4957 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4958 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4959 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4962 emitcode ("anl", "%s,%s",
4963 aopGet (AOP (left), offset, FALSE, TRUE),
4964 aopGet (AOP (right), offset, FALSE, FALSE));
4968 if (AOP_TYPE (left) == AOP_ACC)
4969 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4972 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4973 if (IS_AOP_PREG (result))
4975 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4976 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4980 emitcode ("anl", "%s,a",
4981 aopGet (AOP (left), offset, FALSE, TRUE));
4988 // left & result in different registers
4989 if (AOP_TYPE (result) == AOP_CRY)
4992 // if(size), result in bit
4993 // if(!size && ifx), conditional oper: if(left & right)
4994 symbol *tlbl = newiTempLabel (NULL);
4995 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4997 emitcode ("setb", "c");
5000 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5001 emitcode ("anl", "a,%s",
5002 aopGet (AOP (right), offset, FALSE, FALSE));
5004 if (AOP_TYPE(left)==AOP_ACC) {
5005 emitcode("mov", "b,a");
5006 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5007 emitcode("anl", "a,b");
5009 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5010 emitcode ("anl", "a,%s",
5011 aopGet (AOP (left), offset, FALSE, FALSE));
5014 emitcode ("jnz", "%05d$", tlbl->key + 100);
5020 emitcode ("", "%05d$:", tlbl->key + 100);
5024 jmpTrueOrFalse (ifx, tlbl);
5026 emitcode ("", "%05d$:", tlbl->key + 100);
5030 for (; (size--); offset++)
5033 // result = left & right
5034 if (AOP_TYPE (right) == AOP_LIT)
5036 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
5038 aopPut (AOP (result),
5039 aopGet (AOP (left), offset, FALSE, FALSE),
5041 isOperandVolatile (result, FALSE));
5044 else if (bytelit == 0)
5046 /* dummy read of volatile operand */
5047 if (isOperandVolatile (left, FALSE))
5048 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5049 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5053 // faster than result <- left, anl result,right
5054 // and better if result is SFR
5055 if (AOP_TYPE (left) == AOP_ACC)
5056 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5059 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5060 emitcode ("anl", "a,%s",
5061 aopGet (AOP (left), offset, FALSE, FALSE));
5063 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5069 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5070 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5071 freeAsmop (result, NULL, ic, TRUE);
5074 /*-----------------------------------------------------------------*/
5075 /* genOr - code for or */
5076 /*-----------------------------------------------------------------*/
5078 genOr (iCode * ic, iCode * ifx)
5080 operand *left, *right, *result;
5081 int size, offset = 0;
5082 unsigned long lit = 0L;
5084 D(emitcode ("; genOr",""));
5086 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5087 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5088 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5091 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5093 AOP_TYPE (left), AOP_TYPE (right));
5094 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5096 AOP_SIZE (left), AOP_SIZE (right));
5099 /* if left is a literal & right is not then exchange them */
5100 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5101 AOP_NEEDSACC (left))
5103 operand *tmp = right;
5108 /* if result = right then exchange them */
5109 if (sameRegs (AOP (result), AOP (right)))
5111 operand *tmp = right;
5116 /* if right is bit then exchange them */
5117 if (AOP_TYPE (right) == AOP_CRY &&
5118 AOP_TYPE (left) != AOP_CRY)
5120 operand *tmp = right;
5124 if (AOP_TYPE (right) == AOP_LIT)
5125 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5127 size = AOP_SIZE (result);
5131 if (AOP_TYPE (left) == AOP_CRY)
5133 if (AOP_TYPE (right) == AOP_LIT)
5135 // c = bit | literal;
5138 // lit != 0 => result = 1
5139 if (AOP_TYPE (result) == AOP_CRY)
5142 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5144 continueIfTrue (ifx);
5147 emitcode ("setb", "c");
5151 // lit == 0 => result = left
5152 if (size && sameRegs (AOP (result), AOP (left)))
5154 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5159 if (AOP_TYPE (right) == AOP_CRY)
5162 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5163 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5168 symbol *tlbl = newiTempLabel (NULL);
5169 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5170 emitcode ("setb", "c");
5171 emitcode ("jb", "%s,%05d$",
5172 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5174 emitcode ("jnz", "%05d$", tlbl->key + 100);
5175 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5177 jmpTrueOrFalse (ifx, tlbl);
5183 emitcode ("", "%05d$:", tlbl->key + 100);
5192 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5193 genIfxJump (ifx, "c");
5197 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5198 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5199 if ((AOP_TYPE (right) == AOP_LIT) &&
5200 (AOP_TYPE (result) == AOP_CRY) &&
5201 (AOP_TYPE (left) != AOP_CRY))
5207 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5209 continueIfTrue (ifx);
5214 // lit = 0, result = boolean(left)
5216 emitcode ("setb", "c");
5220 symbol *tlbl = newiTempLabel (NULL);
5221 emitcode ("jnz", "%05d$", tlbl->key + 100);
5223 emitcode ("", "%05d$:", tlbl->key + 100);
5227 genIfxJump (ifx, "a");
5235 /* if left is same as result */
5236 if (sameRegs (AOP (result), AOP (left)))
5238 for (; size--; offset++)
5240 if (AOP_TYPE (right) == AOP_LIT)
5242 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5244 /* dummy read of volatile operand */
5245 if (isOperandVolatile (left, FALSE))
5246 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5250 else if (IS_AOP_PREG (left))
5252 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5253 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5254 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5257 emitcode ("orl", "%s,%s",
5258 aopGet (AOP (left), offset, FALSE, TRUE),
5259 aopGet (AOP (right), offset, FALSE, FALSE));
5263 if (AOP_TYPE (left) == AOP_ACC)
5264 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5267 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5268 if (IS_AOP_PREG (left))
5270 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5271 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5274 emitcode ("orl", "%s,a",
5275 aopGet (AOP (left), offset, FALSE, TRUE));
5282 // left & result in different registers
5283 if (AOP_TYPE (result) == AOP_CRY)
5286 // if(size), result in bit
5287 // if(!size && ifx), conditional oper: if(left | right)
5288 symbol *tlbl = newiTempLabel (NULL);
5289 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5291 emitcode ("setb", "c");
5294 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5295 emitcode ("orl", "a,%s",
5296 aopGet (AOP (right), offset, FALSE, FALSE));
5298 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5299 emitcode ("orl", "a,%s",
5300 aopGet (AOP (left), offset, FALSE, FALSE));
5302 emitcode ("jnz", "%05d$", tlbl->key + 100);
5308 emitcode ("", "%05d$:", tlbl->key + 100);
5312 jmpTrueOrFalse (ifx, tlbl);
5314 emitcode ("", "%05d$:", tlbl->key + 100);
5317 for (; (size--); offset++)
5320 // result = left & right
5321 if (AOP_TYPE (right) == AOP_LIT)
5323 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5325 aopPut (AOP (result),
5326 aopGet (AOP (left), offset, FALSE, FALSE),
5328 isOperandVolatile (result, FALSE));
5332 // faster than result <- left, anl result,right
5333 // and better if result is SFR
5334 if (AOP_TYPE (left) == AOP_ACC)
5335 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5338 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5339 emitcode ("orl", "a,%s",
5340 aopGet (AOP (left), offset, FALSE, FALSE));
5342 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5347 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5348 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5349 freeAsmop (result, NULL, ic, TRUE);
5352 /*-----------------------------------------------------------------*/
5353 /* genXor - code for xclusive or */
5354 /*-----------------------------------------------------------------*/
5356 genXor (iCode * ic, iCode * ifx)
5358 operand *left, *right, *result;
5359 int size, offset = 0;
5360 unsigned long lit = 0L;
5362 D(emitcode ("; genXor",""));
5364 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5365 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5366 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5369 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5371 AOP_TYPE (left), AOP_TYPE (right));
5372 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5374 AOP_SIZE (left), AOP_SIZE (right));
5377 /* if left is a literal & right is not ||
5378 if left needs acc & right does not */
5379 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5380 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5382 operand *tmp = right;
5387 /* if result = right then exchange them */
5388 if (sameRegs (AOP (result), AOP (right)))
5390 operand *tmp = right;
5395 /* if right is bit then exchange them */
5396 if (AOP_TYPE (right) == AOP_CRY &&
5397 AOP_TYPE (left) != AOP_CRY)
5399 operand *tmp = right;
5403 if (AOP_TYPE (right) == AOP_LIT)
5404 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5406 size = AOP_SIZE (result);
5410 if (AOP_TYPE (left) == AOP_CRY)
5412 if (AOP_TYPE (right) == AOP_LIT)
5414 // c = bit & literal;
5417 // lit>>1 != 0 => result = 1
5418 if (AOP_TYPE (result) == AOP_CRY)
5421 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5423 continueIfTrue (ifx);
5426 emitcode ("setb", "c");
5433 // lit == 0, result = left
5434 if (size && sameRegs (AOP (result), AOP (left)))
5436 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5440 // lit == 1, result = not(left)
5441 if (size && sameRegs (AOP (result), AOP (left)))
5443 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5448 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5449 emitcode ("cpl", "c");
5458 symbol *tlbl = newiTempLabel (NULL);
5459 if (AOP_TYPE (right) == AOP_CRY)
5462 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5466 int sizer = AOP_SIZE (right);
5468 // if val>>1 != 0, result = 1
5469 emitcode ("setb", "c");
5472 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5474 // test the msb of the lsb
5475 emitcode ("anl", "a,#0xfe");
5476 emitcode ("jnz", "%05d$", tlbl->key + 100);
5480 emitcode ("rrc", "a");
5482 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5483 emitcode ("cpl", "c");
5484 emitcode ("", "%05d$:", (tlbl->key + 100));
5491 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5492 genIfxJump (ifx, "c");
5496 if (sameRegs (AOP (result), AOP (left)))
5498 /* if left is same as result */
5499 for (; size--; offset++)
5501 if (AOP_TYPE (right) == AOP_LIT)
5503 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5505 else if (IS_AOP_PREG (left))
5507 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5508 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5509 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5512 emitcode ("xrl", "%s,%s",
5513 aopGet (AOP (left), offset, FALSE, TRUE),
5514 aopGet (AOP (right), offset, FALSE, FALSE));
5518 if (AOP_TYPE (left) == AOP_ACC)
5519 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5522 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5523 if (IS_AOP_PREG (left))
5525 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5526 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5529 emitcode ("xrl", "%s,a",
5530 aopGet (AOP (left), offset, FALSE, TRUE));
5537 // left & result in different registers
5538 if (AOP_TYPE (result) == AOP_CRY)
5541 // if(size), result in bit
5542 // if(!size && ifx), conditional oper: if(left ^ right)
5543 symbol *tlbl = newiTempLabel (NULL);
5544 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5546 emitcode ("setb", "c");
5549 if ((AOP_TYPE (right) == AOP_LIT) &&
5550 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5552 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5556 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5557 emitcode ("xrl", "a,%s",
5558 aopGet (AOP (right), offset, FALSE, FALSE));
5560 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5561 emitcode ("xrl", "a,%s",
5562 aopGet (AOP (left), offset, FALSE, FALSE));
5565 emitcode ("jnz", "%05d$", tlbl->key + 100);
5571 emitcode ("", "%05d$:", tlbl->key + 100);
5575 jmpTrueOrFalse (ifx, tlbl);
5578 for (; (size--); offset++)
5581 // result = left & right
5582 if (AOP_TYPE (right) == AOP_LIT)
5584 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5586 aopPut (AOP (result),
5587 aopGet (AOP (left), offset, FALSE, FALSE),
5589 isOperandVolatile (result, FALSE));
5593 // faster than result <- left, anl result,right
5594 // and better if result is SFR
5595 if (AOP_TYPE (left) == AOP_ACC)
5596 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5599 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5600 emitcode ("xrl", "a,%s",
5601 aopGet (AOP (left), offset, FALSE, TRUE));
5603 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5608 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5609 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5610 freeAsmop (result, NULL, ic, TRUE);
5613 /*-----------------------------------------------------------------*/
5614 /* genInline - write the inline code out */
5615 /*-----------------------------------------------------------------*/
5617 genInline (iCode * ic)
5619 char *buffer, *bp, *bp1;
5621 D(emitcode ("; genInline",""));
5623 _G.inLine += (!options.asmpeep);
5625 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5626 strcpy (buffer, IC_INLINE (ic));
5628 /* emit each line as a code */
5653 /* emitcode("",buffer); */
5654 _G.inLine -= (!options.asmpeep);
5657 /*-----------------------------------------------------------------*/
5658 /* genRRC - rotate right with carry */
5659 /*-----------------------------------------------------------------*/
5663 operand *left, *result;
5664 int size, offset = 0;
5667 D(emitcode ("; genRRC",""));
5669 /* rotate right with carry */
5670 left = IC_LEFT (ic);
5671 result = IC_RESULT (ic);
5672 aopOp (left, ic, FALSE);
5673 aopOp (result, ic, FALSE);
5675 /* move it to the result */
5676 size = AOP_SIZE (result);
5678 if (size == 1) { /* special case for 1 byte */
5679 l = aopGet (AOP (left), offset, FALSE, FALSE);
5681 emitcode ("rr", "a");
5687 l = aopGet (AOP (left), offset, FALSE, FALSE);
5689 emitcode ("rrc", "a");
5690 if (AOP_SIZE (result) > 1)
5691 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5693 /* now we need to put the carry into the
5694 highest order byte of the result */
5695 if (AOP_SIZE (result) > 1)
5697 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5700 emitcode ("mov", "acc.7,c");
5702 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5703 freeAsmop (left, NULL, ic, TRUE);
5704 freeAsmop (result, NULL, ic, TRUE);
5707 /*-----------------------------------------------------------------*/
5708 /* genRLC - generate code for rotate left with carry */
5709 /*-----------------------------------------------------------------*/
5713 operand *left, *result;
5714 int size, offset = 0;
5717 D(emitcode ("; genRLC",""));
5719 /* rotate right with carry */
5720 left = IC_LEFT (ic);
5721 result = IC_RESULT (ic);
5722 aopOp (left, ic, FALSE);
5723 aopOp (result, ic, FALSE);
5725 /* move it to the result */
5726 size = AOP_SIZE (result);
5730 l = aopGet (AOP (left), offset, FALSE, FALSE);
5732 if (size == 0) { /* special case for 1 byte */
5736 emitcode ("add", "a,acc");
5737 if (AOP_SIZE (result) > 1)
5738 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5741 l = aopGet (AOP (left), offset, FALSE, FALSE);
5743 emitcode ("rlc", "a");
5744 if (AOP_SIZE (result) > 1)
5745 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5748 /* now we need to put the carry into the
5749 highest order byte of the result */
5750 if (AOP_SIZE (result) > 1)
5752 l = aopGet (AOP (result), 0, FALSE, FALSE);
5755 emitcode ("mov", "acc.0,c");
5757 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5758 freeAsmop (left, NULL, ic, TRUE);
5759 freeAsmop (result, NULL, ic, TRUE);
5762 /*-----------------------------------------------------------------*/
5763 /* genGetHbit - generates code get highest order bit */
5764 /*-----------------------------------------------------------------*/
5766 genGetHbit (iCode * ic)
5768 operand *left, *result;
5770 D(emitcode ("; genGetHbit",""));
5772 left = IC_LEFT (ic);
5773 result = IC_RESULT (ic);
5774 aopOp (left, ic, FALSE);
5775 aopOp (result, ic, FALSE);
5777 /* get the highest order byte into a */
5778 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5779 if (AOP_TYPE (result) == AOP_CRY)
5781 emitcode ("rlc", "a");
5786 emitcode ("rl", "a");
5787 emitcode ("anl", "a,#0x01");
5792 freeAsmop (left, NULL, ic, TRUE);
5793 freeAsmop (result, NULL, ic, TRUE);
5796 /*-----------------------------------------------------------------*/
5797 /* genSwap - generates code to swap nibbles or bytes */
5798 /*-----------------------------------------------------------------*/
5800 genSwap (iCode * ic)
5802 operand *left, *result;
5804 D(emitcode ("; genSwap",""));
5806 left = IC_LEFT (ic);
5807 result = IC_RESULT (ic);
5808 aopOp (left, ic, FALSE);
5809 aopOp (result, ic, FALSE);
5811 switch (AOP_SIZE (left))
5813 case 1: /* swap nibbles in byte */
5814 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5815 emitcode ("swap", "a");
5816 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5818 case 2: /* swap bytes in word */
5819 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
5821 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5822 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5823 0, isOperandVolatile (result, FALSE));
5824 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
5826 else if (operandsEqu (left, result))
5829 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5830 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
5832 emitcode ("mov", "b,a");
5835 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5836 0, isOperandVolatile (result, FALSE));
5837 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
5841 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5842 0, isOperandVolatile (result, FALSE));
5843 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
5844 1, isOperandVolatile (result, FALSE));
5848 wassertl(FALSE, "unsupported SWAP operand size");
5851 freeAsmop (left, NULL, ic, TRUE);
5852 freeAsmop (result, NULL, ic, TRUE);
5856 /*-----------------------------------------------------------------*/
5857 /* AccRol - rotate left accumulator by known count */
5858 /*-----------------------------------------------------------------*/
5860 AccRol (int shCount)
5862 shCount &= 0x0007; // shCount : 0..7
5869 emitcode ("rl", "a");
5872 emitcode ("rl", "a");
5873 emitcode ("rl", "a");
5876 emitcode ("swap", "a");
5877 emitcode ("rr", "a");
5880 emitcode ("swap", "a");
5883 emitcode ("swap", "a");
5884 emitcode ("rl", "a");
5887 emitcode ("rr", "a");
5888 emitcode ("rr", "a");
5891 emitcode ("rr", "a");
5896 /*-----------------------------------------------------------------*/
5897 /* AccLsh - left shift accumulator by known count */
5898 /*-----------------------------------------------------------------*/
5900 AccLsh (int shCount)
5905 emitcode ("add", "a,acc");
5906 else if (shCount == 2)
5908 emitcode ("add", "a,acc");
5909 emitcode ("add", "a,acc");
5913 /* rotate left accumulator */
5915 /* and kill the lower order bits */
5916 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5921 /*-----------------------------------------------------------------*/
5922 /* AccRsh - right shift accumulator by known count */
5923 /*-----------------------------------------------------------------*/
5925 AccRsh (int shCount)
5932 emitcode ("rrc", "a");
5936 /* rotate right accumulator */
5937 AccRol (8 - shCount);
5938 /* and kill the higher order bits */
5939 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5944 /*-----------------------------------------------------------------*/
5945 /* AccSRsh - signed right shift accumulator by known count */
5946 /*-----------------------------------------------------------------*/
5948 AccSRsh (int shCount)
5955 emitcode ("mov", "c,acc.7");
5956 emitcode ("rrc", "a");
5958 else if (shCount == 2)
5960 emitcode ("mov", "c,acc.7");
5961 emitcode ("rrc", "a");
5962 emitcode ("mov", "c,acc.7");
5963 emitcode ("rrc", "a");
5967 tlbl = newiTempLabel (NULL);
5968 /* rotate right accumulator */
5969 AccRol (8 - shCount);
5970 /* and kill the higher order bits */
5971 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5972 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5973 emitcode ("orl", "a,#0x%02x",
5974 (unsigned char) ~SRMask[shCount]);
5975 emitcode ("", "%05d$:", tlbl->key + 100);
5980 /*-----------------------------------------------------------------*/
5981 /* shiftR1Left2Result - shift right one byte from left to result */
5982 /*-----------------------------------------------------------------*/
5984 shiftR1Left2Result (operand * left, int offl,
5985 operand * result, int offr,
5986 int shCount, int sign)
5988 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5989 /* shift right accumulator */
5994 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5997 /*-----------------------------------------------------------------*/
5998 /* shiftL1Left2Result - shift left one byte from left to result */
5999 /*-----------------------------------------------------------------*/
6001 shiftL1Left2Result (operand * left, int offl,
6002 operand * result, int offr, int shCount)
6005 l = aopGet (AOP (left), offl, FALSE, FALSE);
6007 /* shift left accumulator */
6009 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6012 /*-----------------------------------------------------------------*/
6013 /* movLeft2Result - move byte from left to result */
6014 /*-----------------------------------------------------------------*/
6016 movLeft2Result (operand * left, int offl,
6017 operand * result, int offr, int sign)
6020 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6022 l = aopGet (AOP (left), offl, FALSE, FALSE);
6024 if (*l == '@' && (IS_AOP_PREG (result)))
6026 emitcode ("mov", "a,%s", l);
6027 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6032 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
6035 /* MSB sign in acc.7 ! */
6036 if (getDataSize (left) == offl + 1)
6038 emitcode ("mov", "a,%s", l);
6039 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6046 /*-----------------------------------------------------------------*/
6047 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6048 /*-----------------------------------------------------------------*/
6052 emitcode ("rrc", "a");
6053 emitcode ("xch", "a,%s", x);
6054 emitcode ("rrc", "a");
6055 emitcode ("xch", "a,%s", x);
6058 /*-----------------------------------------------------------------*/
6059 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6060 /*-----------------------------------------------------------------*/
6064 emitcode ("xch", "a,%s", x);
6065 emitcode ("rlc", "a");
6066 emitcode ("xch", "a,%s", x);
6067 emitcode ("rlc", "a");
6070 /*-----------------------------------------------------------------*/
6071 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6072 /*-----------------------------------------------------------------*/
6076 emitcode ("xch", "a,%s", x);
6077 emitcode ("add", "a,acc");
6078 emitcode ("xch", "a,%s", x);
6079 emitcode ("rlc", "a");
6082 /*-----------------------------------------------------------------*/
6083 /* AccAXLsh - left shift a:x by known count (0..7) */
6084 /*-----------------------------------------------------------------*/
6086 AccAXLsh (char *x, int shCount)
6101 case 5: // AAAAABBB:CCCCCDDD
6103 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6105 emitcode ("anl", "a,#0x%02x",
6106 SLMask[shCount]); // BBB00000:CCCCCDDD
6108 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6110 AccRol (shCount); // DDDCCCCC:BBB00000
6112 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6114 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6116 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6118 emitcode ("anl", "a,#0x%02x",
6119 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6121 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6123 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6126 case 6: // AAAAAABB:CCCCCCDD
6127 emitcode ("anl", "a,#0x%02x",
6128 SRMask[shCount]); // 000000BB:CCCCCCDD
6129 emitcode ("mov", "c,acc.0"); // c = B
6130 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6132 AccAXRrl1 (x); // BCCCCCCD:D000000B
6133 AccAXRrl1 (x); // BBCCCCCC:DD000000
6135 emitcode("rrc","a");
6136 emitcode("xch","a,%s", x);
6137 emitcode("rrc","a");
6138 emitcode("mov","c,acc.0"); //<< get correct bit
6139 emitcode("xch","a,%s", x);
6141 emitcode("rrc","a");
6142 emitcode("xch","a,%s", x);
6143 emitcode("rrc","a");
6144 emitcode("xch","a,%s", x);
6147 case 7: // a:x <<= 7
6149 emitcode ("anl", "a,#0x%02x",
6150 SRMask[shCount]); // 0000000B:CCCCCCCD
6152 emitcode ("mov", "c,acc.0"); // c = B
6154 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6156 AccAXRrl1 (x); // BCCCCCCC:D0000000
6164 /*-----------------------------------------------------------------*/
6165 /* AccAXRsh - right shift a:x known count (0..7) */
6166 /*-----------------------------------------------------------------*/
6168 AccAXRsh (char *x, int shCount)
6176 AccAXRrl1 (x); // 0->a:x
6181 AccAXRrl1 (x); // 0->a:x
6184 AccAXRrl1 (x); // 0->a:x
6189 case 5: // AAAAABBB:CCCCCDDD = a:x
6191 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6193 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6195 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6197 emitcode ("anl", "a,#0x%02x",
6198 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6200 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6202 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6204 emitcode ("anl", "a,#0x%02x",
6205 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6207 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6209 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6211 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6214 case 6: // AABBBBBB:CCDDDDDD
6216 emitcode ("mov", "c,acc.7");
6217 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6219 emitcode ("mov", "c,acc.7");
6220 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6222 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6224 emitcode ("anl", "a,#0x%02x",
6225 SRMask[shCount]); // 000000AA:BBBBBBCC
6228 case 7: // ABBBBBBB:CDDDDDDD
6230 emitcode ("mov", "c,acc.7"); // c = A
6232 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6234 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6236 emitcode ("anl", "a,#0x%02x",
6237 SRMask[shCount]); // 0000000A:BBBBBBBC
6245 /*-----------------------------------------------------------------*/
6246 /* AccAXRshS - right shift signed a:x known count (0..7) */
6247 /*-----------------------------------------------------------------*/
6249 AccAXRshS (char *x, int shCount)
6257 emitcode ("mov", "c,acc.7");
6258 AccAXRrl1 (x); // s->a:x
6262 emitcode ("mov", "c,acc.7");
6263 AccAXRrl1 (x); // s->a:x
6265 emitcode ("mov", "c,acc.7");
6266 AccAXRrl1 (x); // s->a:x
6271 case 5: // AAAAABBB:CCCCCDDD = a:x
6273 tlbl = newiTempLabel (NULL);
6274 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6276 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6278 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6280 emitcode ("anl", "a,#0x%02x",
6281 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6283 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6285 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6287 emitcode ("anl", "a,#0x%02x",
6288 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6290 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6292 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6294 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6296 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6297 emitcode ("orl", "a,#0x%02x",
6298 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6300 emitcode ("", "%05d$:", tlbl->key + 100);
6301 break; // SSSSAAAA:BBBCCCCC
6303 case 6: // AABBBBBB:CCDDDDDD
6305 tlbl = newiTempLabel (NULL);
6306 emitcode ("mov", "c,acc.7");
6307 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6309 emitcode ("mov", "c,acc.7");
6310 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6312 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6314 emitcode ("anl", "a,#0x%02x",
6315 SRMask[shCount]); // 000000AA:BBBBBBCC
6317 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6318 emitcode ("orl", "a,#0x%02x",
6319 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6321 emitcode ("", "%05d$:", tlbl->key + 100);
6323 case 7: // ABBBBBBB:CDDDDDDD
6325 tlbl = newiTempLabel (NULL);
6326 emitcode ("mov", "c,acc.7"); // c = A
6328 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6330 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6332 emitcode ("anl", "a,#0x%02x",
6333 SRMask[shCount]); // 0000000A:BBBBBBBC
6335 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6336 emitcode ("orl", "a,#0x%02x",
6337 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6339 emitcode ("", "%05d$:", tlbl->key + 100);
6346 /*-----------------------------------------------------------------*/
6347 /* shiftL2Left2Result - shift left two bytes from left to result */
6348 /*-----------------------------------------------------------------*/
6350 shiftL2Left2Result (operand * left, int offl,
6351 operand * result, int offr, int shCount)
6353 if (sameRegs (AOP (result), AOP (left)) &&
6354 ((offl + MSB16) == offr))
6356 /* don't crash result[offr] */
6357 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6358 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6362 movLeft2Result (left, offl, result, offr, 0);
6363 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6365 /* ax << shCount (x = lsb(result)) */
6366 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6367 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6371 /*-----------------------------------------------------------------*/
6372 /* shiftR2Left2Result - shift right two bytes from left to result */
6373 /*-----------------------------------------------------------------*/
6375 shiftR2Left2Result (operand * left, int offl,
6376 operand * result, int offr,
6377 int shCount, int sign)
6379 if (sameRegs (AOP (result), AOP (left)) &&
6380 ((offl + MSB16) == offr))
6382 /* don't crash result[offr] */
6383 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6384 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6388 movLeft2Result (left, offl, result, offr, 0);
6389 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6391 /* a:x >> shCount (x = lsb(result)) */
6393 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6395 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6396 if (getDataSize (result) > 1)
6397 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6400 /*-----------------------------------------------------------------*/
6401 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6402 /*-----------------------------------------------------------------*/
6404 shiftLLeftOrResult (operand * left, int offl,
6405 operand * result, int offr, int shCount)
6407 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6408 /* shift left accumulator */
6410 /* or with result */
6411 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6412 /* back to result */
6413 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6416 /*-----------------------------------------------------------------*/
6417 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6418 /*-----------------------------------------------------------------*/
6420 shiftRLeftOrResult (operand * left, int offl,
6421 operand * result, int offr, int shCount)
6423 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6424 /* shift right accumulator */
6426 /* or with result */
6427 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6428 /* back to result */
6429 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6432 /*-----------------------------------------------------------------*/
6433 /* genlshOne - left shift a one byte quantity by known count */
6434 /*-----------------------------------------------------------------*/
6436 genlshOne (operand * result, operand * left, int shCount)
6438 D(emitcode ("; genlshOne",""));
6440 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6443 /*-----------------------------------------------------------------*/
6444 /* genlshTwo - left shift two bytes by known amount != 0 */
6445 /*-----------------------------------------------------------------*/
6447 genlshTwo (operand * result, operand * left, int shCount)
6451 D(emitcode ("; genlshTwo",""));
6453 size = getDataSize (result);
6455 /* if shCount >= 8 */
6463 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6465 movLeft2Result (left, LSB, result, MSB16, 0);
6467 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6470 /* 1 <= shCount <= 7 */
6474 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6476 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6480 /*-----------------------------------------------------------------*/
6481 /* shiftLLong - shift left one long from left to result */
6482 /* offl = LSB or MSB16 */
6483 /*-----------------------------------------------------------------*/
6485 shiftLLong (operand * left, operand * result, int offr)
6488 int size = AOP_SIZE (result);
6490 if (size >= LSB + offr)
6492 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6494 emitcode ("add", "a,acc");
6495 if (sameRegs (AOP (left), AOP (result)) &&
6496 size >= MSB16 + offr && offr != LSB)
6497 emitcode ("xch", "a,%s",
6498 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6500 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6503 if (size >= MSB16 + offr)
6505 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6507 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6510 emitcode ("rlc", "a");
6511 if (sameRegs (AOP (left), AOP (result)) &&
6512 size >= MSB24 + offr && offr != LSB)
6513 emitcode ("xch", "a,%s",
6514 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6516 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6519 if (size >= MSB24 + offr)
6521 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6523 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6526 emitcode ("rlc", "a");
6527 if (sameRegs (AOP (left), AOP (result)) &&
6528 size >= MSB32 + offr && offr != LSB)
6529 emitcode ("xch", "a,%s",
6530 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6532 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6535 if (size > MSB32 + offr)
6537 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6539 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6542 emitcode ("rlc", "a");
6543 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6546 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6549 /*-----------------------------------------------------------------*/
6550 /* genlshFour - shift four byte by a known amount != 0 */
6551 /*-----------------------------------------------------------------*/
6553 genlshFour (operand * result, operand * left, int shCount)
6557 D(emitcode ("; genlshFour",""));
6559 size = AOP_SIZE (result);
6561 /* if shifting more that 3 bytes */
6566 /* lowest order of left goes to the highest
6567 order of the destination */
6568 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6570 movLeft2Result (left, LSB, result, MSB32, 0);
6571 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6572 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6573 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6577 /* more than two bytes */
6578 else if (shCount >= 16)
6580 /* lower order two bytes goes to higher order two bytes */
6582 /* if some more remaining */
6584 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6587 movLeft2Result (left, MSB16, result, MSB32, 0);
6588 movLeft2Result (left, LSB, result, MSB24, 0);
6590 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6591 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6595 /* if more than 1 byte */
6596 else if (shCount >= 8)
6598 /* lower order three bytes goes to higher order three bytes */
6603 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6605 movLeft2Result (left, LSB, result, MSB16, 0);
6611 movLeft2Result (left, MSB24, result, MSB32, 0);
6612 movLeft2Result (left, MSB16, result, MSB24, 0);
6613 movLeft2Result (left, LSB, result, MSB16, 0);
6614 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6616 else if (shCount == 1)
6617 shiftLLong (left, result, MSB16);
6620 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6621 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6622 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6623 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6628 /* 1 <= shCount <= 7 */
6629 else if (shCount <= 2)
6631 shiftLLong (left, result, LSB);
6633 shiftLLong (result, result, LSB);
6635 /* 3 <= shCount <= 7, optimize */
6638 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6639 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6640 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6644 /*-----------------------------------------------------------------*/
6645 /* genLeftShiftLiteral - left shifting by known count */
6646 /*-----------------------------------------------------------------*/
6648 genLeftShiftLiteral (operand * left,
6653 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6656 D(emitcode ("; genLeftShiftLiteral",""));
6658 freeAsmop (right, NULL, ic, TRUE);
6660 aopOp (left, ic, FALSE);
6661 aopOp (result, ic, FALSE);
6663 size = getSize (operandType (result));
6666 emitcode ("; shift left ", "result %d, left %d", size,
6670 /* I suppose that the left size >= result size */
6675 movLeft2Result (left, size, result, size, 0);
6679 else if (shCount >= (size * 8))
6681 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6687 genlshOne (result, left, shCount);
6691 genlshTwo (result, left, shCount);
6695 genlshFour (result, left, shCount);
6698 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6699 "*** ack! mystery literal shift!\n");
6703 freeAsmop (left, NULL, ic, TRUE);
6704 freeAsmop (result, NULL, ic, TRUE);
6707 /*-----------------------------------------------------------------*/
6708 /* genLeftShift - generates code for left shifting */
6709 /*-----------------------------------------------------------------*/
6711 genLeftShift (iCode * ic)
6713 operand *left, *right, *result;
6716 symbol *tlbl, *tlbl1;
6718 D(emitcode ("; genLeftShift",""));
6720 right = IC_RIGHT (ic);
6721 left = IC_LEFT (ic);
6722 result = IC_RESULT (ic);
6724 aopOp (right, ic, FALSE);
6726 /* if the shift count is known then do it
6727 as efficiently as possible */
6728 if (AOP_TYPE (right) == AOP_LIT)
6730 genLeftShiftLiteral (left, right, result, ic);
6734 /* shift count is unknown then we have to form
6735 a loop get the loop count in B : Note: we take
6736 only the lower order byte since shifting
6737 more that 32 bits make no sense anyway, ( the
6738 largest size of an object can be only 32 bits ) */
6740 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6741 emitcode ("inc", "b");
6742 freeAsmop (right, NULL, ic, TRUE);
6743 aopOp (left, ic, FALSE);
6744 aopOp (result, ic, FALSE);
6746 /* now move the left to the result if they are not the
6748 if (!sameRegs (AOP (left), AOP (result)) &&
6749 AOP_SIZE (result) > 1)
6752 size = AOP_SIZE (result);
6756 l = aopGet (AOP (left), offset, FALSE, TRUE);
6757 if (*l == '@' && (IS_AOP_PREG (result)))
6760 emitcode ("mov", "a,%s", l);
6761 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6764 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6769 tlbl = newiTempLabel (NULL);
6770 size = AOP_SIZE (result);
6772 tlbl1 = newiTempLabel (NULL);
6774 /* if it is only one byte then */
6777 symbol *tlbl1 = newiTempLabel (NULL);
6779 l = aopGet (AOP (left), 0, FALSE, FALSE);
6781 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6782 emitcode ("", "%05d$:", tlbl->key + 100);
6783 emitcode ("add", "a,acc");
6784 emitcode ("", "%05d$:", tlbl1->key + 100);
6785 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6786 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6790 reAdjustPreg (AOP (result));
6792 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6793 emitcode ("", "%05d$:", tlbl->key + 100);
6794 l = aopGet (AOP (result), offset, FALSE, FALSE);
6796 emitcode ("add", "a,acc");
6797 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6800 l = aopGet (AOP (result), offset, FALSE, FALSE);
6802 emitcode ("rlc", "a");
6803 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6805 reAdjustPreg (AOP (result));
6807 emitcode ("", "%05d$:", tlbl1->key + 100);
6808 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6810 freeAsmop (left, NULL, ic, TRUE);
6811 freeAsmop (result, NULL, ic, TRUE);
6814 /*-----------------------------------------------------------------*/
6815 /* genrshOne - right shift a one byte quantity by known count */
6816 /*-----------------------------------------------------------------*/
6818 genrshOne (operand * result, operand * left,
6819 int shCount, int sign)
6821 D(emitcode ("; genrshOne",""));
6823 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6826 /*-----------------------------------------------------------------*/
6827 /* genrshTwo - right shift two bytes by known amount != 0 */
6828 /*-----------------------------------------------------------------*/
6830 genrshTwo (operand * result, operand * left,
6831 int shCount, int sign)
6833 D(emitcode ("; genrshTwo",""));
6835 /* if shCount >= 8 */
6840 shiftR1Left2Result (left, MSB16, result, LSB,
6843 movLeft2Result (left, MSB16, result, LSB, sign);
6844 addSign (result, MSB16, sign);
6847 /* 1 <= shCount <= 7 */
6849 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6852 /*-----------------------------------------------------------------*/
6853 /* shiftRLong - shift right one long from left to result */
6854 /* offl = LSB or MSB16 */
6855 /*-----------------------------------------------------------------*/
6857 shiftRLong (operand * left, int offl,
6858 operand * result, int sign)
6860 int isSameRegs=sameRegs(AOP(left),AOP(result));
6862 if (isSameRegs && offl>1) {
6863 // we are in big trouble, but this shouldn't happen
6864 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6867 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6872 emitcode ("rlc", "a");
6873 emitcode ("subb", "a,acc");
6875 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6877 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6878 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6881 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6886 emitcode ("clr", "c");
6888 emitcode ("mov", "c,acc.7");
6891 emitcode ("rrc", "a");
6893 if (isSameRegs && offl==MSB16) {
6894 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6896 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6897 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6900 emitcode ("rrc", "a");
6901 if (isSameRegs && offl==1) {
6902 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6904 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6905 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6907 emitcode ("rrc", "a");
6908 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6912 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6913 emitcode ("rrc", "a");
6914 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6918 /*-----------------------------------------------------------------*/
6919 /* genrshFour - shift four byte by a known amount != 0 */
6920 /*-----------------------------------------------------------------*/
6922 genrshFour (operand * result, operand * left,
6923 int shCount, int sign)
6925 D(emitcode ("; genrshFour",""));
6927 /* if shifting more that 3 bytes */
6932 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6934 movLeft2Result (left, MSB32, result, LSB, sign);
6935 addSign (result, MSB16, sign);
6937 else if (shCount >= 16)
6941 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6944 movLeft2Result (left, MSB24, result, LSB, 0);
6945 movLeft2Result (left, MSB32, result, MSB16, sign);
6947 addSign (result, MSB24, sign);
6949 else if (shCount >= 8)
6953 shiftRLong (left, MSB16, result, sign);
6954 else if (shCount == 0)
6956 movLeft2Result (left, MSB16, result, LSB, 0);
6957 movLeft2Result (left, MSB24, result, MSB16, 0);
6958 movLeft2Result (left, MSB32, result, MSB24, sign);
6959 addSign (result, MSB32, sign);
6963 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6964 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6965 /* the last shift is signed */
6966 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6967 addSign (result, MSB32, sign);
6971 { /* 1 <= shCount <= 7 */
6974 shiftRLong (left, LSB, result, sign);
6976 shiftRLong (result, LSB, result, sign);
6980 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6981 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6982 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6987 /*-----------------------------------------------------------------*/
6988 /* genRightShiftLiteral - right shifting by known count */
6989 /*-----------------------------------------------------------------*/
6991 genRightShiftLiteral (operand * left,
6997 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7000 D(emitcode ("; genRightShiftLiteral",""));
7002 freeAsmop (right, NULL, ic, TRUE);
7004 aopOp (left, ic, FALSE);
7005 aopOp (result, ic, FALSE);
7008 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
7012 size = getDataSize (left);
7013 /* test the LEFT size !!! */
7015 /* I suppose that the left size >= result size */
7018 size = getDataSize (result);
7020 movLeft2Result (left, size, result, size, 0);
7023 else if (shCount >= (size * 8))
7026 /* get sign in acc.7 */
7027 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
7029 addSign (result, LSB, sign);
7036 genrshOne (result, left, shCount, sign);
7040 genrshTwo (result, left, shCount, sign);
7044 genrshFour (result, left, shCount, sign);
7050 freeAsmop (left, NULL, ic, TRUE);
7051 freeAsmop (result, NULL, ic, TRUE);
7054 /*-----------------------------------------------------------------*/
7055 /* genSignedRightShift - right shift of signed number */
7056 /*-----------------------------------------------------------------*/
7058 genSignedRightShift (iCode * ic)
7060 operand *right, *left, *result;
7063 symbol *tlbl, *tlbl1;
7065 D(emitcode ("; genSignedRightShift",""));
7067 /* we do it the hard way put the shift count in b
7068 and loop thru preserving the sign */
7070 right = IC_RIGHT (ic);
7071 left = IC_LEFT (ic);
7072 result = IC_RESULT (ic);
7074 aopOp (right, ic, FALSE);
7077 if (AOP_TYPE (right) == AOP_LIT)
7079 genRightShiftLiteral (left, right, result, ic, 1);
7082 /* shift count is unknown then we have to form
7083 a loop get the loop count in B : Note: we take
7084 only the lower order byte since shifting
7085 more that 32 bits make no sense anyway, ( the
7086 largest size of an object can be only 32 bits ) */
7088 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7089 emitcode ("inc", "b");
7090 freeAsmop (right, NULL, ic, TRUE);
7091 aopOp (left, ic, FALSE);
7092 aopOp (result, ic, FALSE);
7094 /* now move the left to the result if they are not the
7096 if (!sameRegs (AOP (left), AOP (result)) &&
7097 AOP_SIZE (result) > 1)
7100 size = AOP_SIZE (result);
7104 l = aopGet (AOP (left), offset, FALSE, TRUE);
7105 if (*l == '@' && IS_AOP_PREG (result))
7108 emitcode ("mov", "a,%s", l);
7109 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7112 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7117 /* mov the highest order bit to OVR */
7118 tlbl = newiTempLabel (NULL);
7119 tlbl1 = newiTempLabel (NULL);
7121 size = AOP_SIZE (result);
7123 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7124 emitcode ("rlc", "a");
7125 emitcode ("mov", "ov,c");
7126 /* if it is only one byte then */
7129 l = aopGet (AOP (left), 0, FALSE, FALSE);
7131 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7132 emitcode ("", "%05d$:", tlbl->key + 100);
7133 emitcode ("mov", "c,ov");
7134 emitcode ("rrc", "a");
7135 emitcode ("", "%05d$:", tlbl1->key + 100);
7136 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7137 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7141 reAdjustPreg (AOP (result));
7142 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7143 emitcode ("", "%05d$:", tlbl->key + 100);
7144 emitcode ("mov", "c,ov");
7147 l = aopGet (AOP (result), offset, FALSE, FALSE);
7149 emitcode ("rrc", "a");
7150 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7152 reAdjustPreg (AOP (result));
7153 emitcode ("", "%05d$:", tlbl1->key + 100);
7154 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7157 freeAsmop (left, NULL, ic, TRUE);
7158 freeAsmop (result, NULL, ic, TRUE);
7161 /*-----------------------------------------------------------------*/
7162 /* genRightShift - generate code for right shifting */
7163 /*-----------------------------------------------------------------*/
7165 genRightShift (iCode * ic)
7167 operand *right, *left, *result;
7171 symbol *tlbl, *tlbl1;
7173 D(emitcode ("; genRightShift",""));
7175 /* if signed then we do it the hard way preserve the
7176 sign bit moving it inwards */
7177 retype = getSpec (operandType (IC_RESULT (ic)));
7179 if (!SPEC_USIGN (retype))
7181 genSignedRightShift (ic);
7185 /* signed & unsigned types are treated the same : i.e. the
7186 signed is NOT propagated inwards : quoting from the
7187 ANSI - standard : "for E1 >> E2, is equivalent to division
7188 by 2**E2 if unsigned or if it has a non-negative value,
7189 otherwise the result is implementation defined ", MY definition
7190 is that the sign does not get propagated */
7192 right = IC_RIGHT (ic);
7193 left = IC_LEFT (ic);
7194 result = IC_RESULT (ic);
7196 aopOp (right, ic, FALSE);
7198 /* if the shift count is known then do it
7199 as efficiently as possible */
7200 if (AOP_TYPE (right) == AOP_LIT)
7202 genRightShiftLiteral (left, right, result, ic, 0);
7206 /* shift count is unknown then we have to form
7207 a loop get the loop count in B : Note: we take
7208 only the lower order byte since shifting
7209 more that 32 bits make no sense anyway, ( the
7210 largest size of an object can be only 32 bits ) */
7212 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7213 emitcode ("inc", "b");
7214 freeAsmop (right, NULL, ic, TRUE);
7215 aopOp (left, ic, FALSE);
7216 aopOp (result, ic, FALSE);
7218 /* now move the left to the result if they are not the
7220 if (!sameRegs (AOP (left), AOP (result)) &&
7221 AOP_SIZE (result) > 1)
7224 size = AOP_SIZE (result);
7228 l = aopGet (AOP (left), offset, FALSE, TRUE);
7229 if (*l == '@' && IS_AOP_PREG (result))
7232 emitcode ("mov", "a,%s", l);
7233 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7236 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7241 tlbl = newiTempLabel (NULL);
7242 tlbl1 = newiTempLabel (NULL);
7243 size = AOP_SIZE (result);
7246 /* if it is only one byte then */
7249 l = aopGet (AOP (left), 0, FALSE, FALSE);
7251 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7252 emitcode ("", "%05d$:", tlbl->key + 100);
7254 emitcode ("rrc", "a");
7255 emitcode ("", "%05d$:", tlbl1->key + 100);
7256 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7257 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7261 reAdjustPreg (AOP (result));
7262 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7263 emitcode ("", "%05d$:", tlbl->key + 100);
7267 l = aopGet (AOP (result), offset, FALSE, FALSE);
7269 emitcode ("rrc", "a");
7270 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7272 reAdjustPreg (AOP (result));
7274 emitcode ("", "%05d$:", tlbl1->key + 100);
7275 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7278 freeAsmop (left, NULL, ic, TRUE);
7279 freeAsmop (result, NULL, ic, TRUE);
7282 /*-----------------------------------------------------------------*/
7283 /* emitPtrByteGet - emits code to get a byte into A through a */
7284 /* pointer register (R0, R1, or DPTR). The */
7285 /* original value of A can be preserved in B. */
7286 /*-----------------------------------------------------------------*/
7288 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7295 emitcode ("mov", "b,a");
7296 emitcode ("mov", "a,@%s", rname);
7301 emitcode ("mov", "b,a");
7302 emitcode ("movx", "a,@%s", rname);
7307 emitcode ("mov", "b,a");
7308 emitcode ("movx", "a,@dptr");
7313 emitcode ("mov", "b,a");
7314 emitcode ("clr", "a");
7315 emitcode ("movc", "a,@a+dptr");
7321 emitcode ("push", "b");
7322 emitcode ("push", "acc");
7324 emitcode ("lcall", "__gptrget");
7326 emitcode ("pop", "b");
7331 /*-----------------------------------------------------------------*/
7332 /* emitPtrByteSet - emits code to set a byte from src through a */
7333 /* pointer register (R0, R1, or DPTR). */
7334 /*-----------------------------------------------------------------*/
7336 emitPtrByteSet (char *rname, int p_type, char *src)
7345 emitcode ("mov", "@%s,a", rname);
7348 emitcode ("mov", "@%s,%s", rname, src);
7353 emitcode ("movx", "@%s,a", rname);
7358 emitcode ("movx", "@dptr,a");
7363 emitcode ("lcall", "__gptrput");
7368 /*-----------------------------------------------------------------*/
7369 /* genUnpackBits - generates code for unpacking bits */
7370 /*-----------------------------------------------------------------*/
7372 genUnpackBits (operand * result, char *rname, int ptype)
7374 int offset = 0; /* result byte offset */
7375 int rsize; /* result size */
7376 int rlen = 0; /* remaining bitfield length */
7377 sym_link *etype; /* bitfield type information */
7378 int blen; /* bitfield length */
7379 int bstr; /* bitfield starting bit within byte */
7381 D(emitcode ("; genUnpackBits",""));
7383 etype = getSpec (operandType (result));
7384 rsize = getSize (operandType (result));
7385 blen = SPEC_BLEN (etype);
7386 bstr = SPEC_BSTR (etype);
7388 /* If the bitfield length is less than a byte */
7391 emitPtrByteGet (rname, ptype, FALSE);
7393 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7394 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7398 /* Bit field did not fit in a byte. Copy all
7399 but the partial byte at the end. */
7400 for (rlen=blen;rlen>=8;rlen-=8)
7402 emitPtrByteGet (rname, ptype, FALSE);
7403 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7405 emitcode ("inc", "%s", rname);
7408 /* Handle the partial byte at the end */
7411 emitPtrByteGet (rname, ptype, FALSE);
7412 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7413 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7421 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7426 /*-----------------------------------------------------------------*/
7427 /* genDataPointerGet - generates code when ptr offset is known */
7428 /*-----------------------------------------------------------------*/
7430 genDataPointerGet (operand * left,
7436 int size, offset = 0;
7438 D(emitcode ("; genDataPointerGet",""));
7440 aopOp (result, ic, TRUE);
7442 /* get the string representation of the name */
7443 l = aopGet (AOP (left), 0, FALSE, TRUE);
7444 size = AOP_SIZE (result);
7448 sprintf (buffer, "(%s + %d)", l + 1, offset);
7450 sprintf (buffer, "%s", l + 1);
7451 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7454 freeAsmop (left, NULL, ic, TRUE);
7455 freeAsmop (result, NULL, ic, TRUE);
7458 /*-----------------------------------------------------------------*/
7459 /* genNearPointerGet - emitcode for near pointer fetch */
7460 /*-----------------------------------------------------------------*/
7462 genNearPointerGet (operand * left,
7470 sym_link *rtype, *retype;
7471 sym_link *ltype = operandType (left);
7474 D(emitcode ("; genNearPointerGet",""));
7476 rtype = operandType (result);
7477 retype = getSpec (rtype);
7479 aopOp (left, ic, FALSE);
7481 /* if left is rematerialisable and
7482 result is not bit variable type and
7483 the left is pointer to data space i.e
7484 lower 128 bytes of space */
7485 if (AOP_TYPE (left) == AOP_IMMD &&
7486 !IS_BITVAR (retype) &&
7487 DCL_TYPE (ltype) == POINTER)
7489 genDataPointerGet (left, result, ic);
7493 /* if the value is already in a pointer register
7494 then don't need anything more */
7495 if (!AOP_INPREG (AOP (left)))
7497 if (IS_AOP_PREG (left))
7499 // Aha, it is a pointer, just in disguise.
7500 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7503 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7504 __FILE__, __LINE__);
7509 emitcode ("mov", "a%s,%s", rname + 1, rname);
7510 rname++; // skip the '@'.
7515 /* otherwise get a free pointer register */
7517 preg = getFreePtr (ic, &aop, FALSE);
7518 emitcode ("mov", "%s,%s",
7520 aopGet (AOP (left), 0, FALSE, TRUE));
7525 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7527 //aopOp (result, ic, FALSE);
7528 aopOp (result, ic, result?TRUE:FALSE);
7530 /* if bitfield then unpack the bits */
7531 if (IS_BITVAR (retype))
7532 genUnpackBits (result, rname, POINTER);
7535 /* we have can just get the values */
7536 int size = AOP_SIZE (result);
7541 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7544 emitcode ("mov", "a,@%s", rname);
7545 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7549 sprintf (buffer, "@%s", rname);
7550 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7554 emitcode ("inc", "%s", rname);
7558 /* now some housekeeping stuff */
7559 if (aop) /* we had to allocate for this iCode */
7561 if (pi) { /* post increment present */
7562 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7564 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7568 /* we did not allocate which means left
7569 already in a pointer register, then
7570 if size > 0 && this could be used again
7571 we have to point it back to where it
7573 if ((AOP_SIZE (result) > 1 &&
7574 !OP_SYMBOL (left)->remat &&
7575 (OP_SYMBOL (left)->liveTo > ic->seq ||
7579 int size = AOP_SIZE (result) - 1;
7581 emitcode ("dec", "%s", rname);
7586 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7587 freeAsmop (left, NULL, ic, TRUE);
7588 if (pi) pi->generated = 1;
7591 /*-----------------------------------------------------------------*/
7592 /* genPagedPointerGet - emitcode for paged pointer fetch */
7593 /*-----------------------------------------------------------------*/
7595 genPagedPointerGet (operand * left,
7603 sym_link *rtype, *retype;
7605 D(emitcode ("; genPagedPointerGet",""));
7607 rtype = operandType (result);
7608 retype = getSpec (rtype);
7610 aopOp (left, ic, FALSE);
7612 /* if the value is already in a pointer register
7613 then don't need anything more */
7614 if (!AOP_INPREG (AOP (left)))
7616 /* otherwise get a free pointer register */
7618 preg = getFreePtr (ic, &aop, FALSE);
7619 emitcode ("mov", "%s,%s",
7621 aopGet (AOP (left), 0, FALSE, TRUE));
7625 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7627 aopOp (result, ic, FALSE);
7629 /* if bitfield then unpack the bits */
7630 if (IS_BITVAR (retype))
7631 genUnpackBits (result, rname, PPOINTER);
7634 /* we have can just get the values */
7635 int size = AOP_SIZE (result);
7641 emitcode ("movx", "a,@%s", rname);
7642 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7647 emitcode ("inc", "%s", rname);
7651 /* now some housekeeping stuff */
7652 if (aop) /* we had to allocate for this iCode */
7654 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7655 freeAsmop (NULL, aop, ic, TRUE);
7659 /* we did not allocate which means left
7660 already in a pointer register, then
7661 if size > 0 && this could be used again
7662 we have to point it back to where it
7664 if ((AOP_SIZE (result) > 1 &&
7665 !OP_SYMBOL (left)->remat &&
7666 (OP_SYMBOL (left)->liveTo > ic->seq ||
7670 int size = AOP_SIZE (result) - 1;
7672 emitcode ("dec", "%s", rname);
7677 freeAsmop (left, NULL, ic, TRUE);
7678 freeAsmop (result, NULL, ic, TRUE);
7679 if (pi) pi->generated = 1;
7683 /*--------------------------------------------------------------------*/
7684 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7685 /*--------------------------------------------------------------------*/
7687 loadDptrFromOperand (operand *op, bool loadBToo)
7689 if (AOP_TYPE (op) != AOP_STR)
7691 /* if this is remateriazable */
7692 if (AOP_TYPE (op) == AOP_IMMD)
7694 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7697 if (AOP(op)->aopu.aop_immd.from_cast_remat)
7698 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7701 wassertl(FALSE, "need pointerCode");
7702 emitcode ("", "; mov b,???");
7703 /* genPointerGet and genPointerSet originally did different
7704 ** things for this case. Both seem wrong.
7705 ** from genPointerGet:
7706 ** emitcode ("mov", "b,#%d", pointerCode (retype));
7707 ** from genPointerSet:
7708 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7713 else if (AOP_TYPE (op) == AOP_DPTR)
7717 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7718 emitcode ("push", "acc");
7719 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7720 emitcode ("push", "acc");
7721 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7722 emitcode ("pop", "dph");
7723 emitcode ("pop", "dpl");
7727 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7728 emitcode ("push", "acc");
7729 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7730 emitcode ("pop", "dpl");
7734 { /* we need to get it byte by byte */
7735 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7736 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7738 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7743 /*-----------------------------------------------------------------*/
7744 /* genFarPointerGet - gget value from far space */
7745 /*-----------------------------------------------------------------*/
7747 genFarPointerGet (operand * left,
7748 operand * result, iCode * ic, iCode * pi)
7751 sym_link *retype = getSpec (operandType (result));
7753 D(emitcode ("; genFarPointerGet",""));
7755 aopOp (left, ic, FALSE);
7756 loadDptrFromOperand (left, FALSE);
7758 /* so dptr now contains the address */
7759 aopOp (result, ic, FALSE);
7761 /* if bit then unpack */
7762 if (IS_BITVAR (retype))
7763 genUnpackBits (result, "dptr", FPOINTER);
7766 size = AOP_SIZE (result);
7771 emitcode ("movx", "a,@dptr");
7772 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7774 emitcode ("inc", "dptr");
7778 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7779 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7780 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7783 freeAsmop (left, NULL, ic, TRUE);
7784 freeAsmop (result, NULL, ic, TRUE);
7787 /*-----------------------------------------------------------------*/
7788 /* genCodePointerGet - gget value from code space */
7789 /*-----------------------------------------------------------------*/
7791 genCodePointerGet (operand * left,
7792 operand * result, iCode * ic, iCode *pi)
7795 sym_link *retype = getSpec (operandType (result));
7797 D(emitcode ("; genCodePointerGet",""));
7799 aopOp (left, ic, FALSE);
7800 loadDptrFromOperand (left, FALSE);
7802 /* so dptr now contains the address */
7803 aopOp (result, ic, FALSE);
7805 /* if bit then unpack */
7806 if (IS_BITVAR (retype))
7807 genUnpackBits (result, "dptr", CPOINTER);
7810 size = AOP_SIZE (result);
7817 emitcode ("clr", "a");
7818 emitcode ("movc", "a,@a+dptr");
7819 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7820 emitcode ("inc", "dptr");
7824 emitcode ("mov", "a,#0x%02x", offset);
7825 emitcode ("movc", "a,@a+dptr");
7826 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7831 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7832 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7833 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7836 freeAsmop (left, NULL, ic, TRUE);
7837 freeAsmop (result, NULL, ic, TRUE);
7840 /*-----------------------------------------------------------------*/
7841 /* genGenPointerGet - gget value from generic pointer space */
7842 /*-----------------------------------------------------------------*/
7844 genGenPointerGet (operand * left,
7845 operand * result, iCode * ic, iCode *pi)
7848 sym_link *retype = getSpec (operandType (result));
7850 D(emitcode ("; genGenPointerGet",""));
7852 aopOp (left, ic, FALSE);
7853 loadDptrFromOperand (left, TRUE);
7855 /* so dptr know contains the address */
7856 aopOp (result, ic, FALSE);
7858 /* if bit then unpack */
7859 if (IS_BITVAR (retype))
7860 genUnpackBits (result, "dptr", GPOINTER);
7863 size = AOP_SIZE (result);
7868 emitcode ("lcall", "__gptrget");
7869 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7871 emitcode ("inc", "dptr");
7875 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7876 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7877 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7880 freeAsmop (left, NULL, ic, TRUE);
7881 freeAsmop (result, NULL, ic, TRUE);
7884 /*-----------------------------------------------------------------*/
7885 /* genPointerGet - generate code for pointer get */
7886 /*-----------------------------------------------------------------*/
7888 genPointerGet (iCode * ic, iCode *pi)
7890 operand *left, *result;
7891 sym_link *type, *etype;
7894 D(emitcode ("; genPointerGet",""));
7896 left = IC_LEFT (ic);
7897 result = IC_RESULT (ic);
7899 /* depending on the type of pointer we need to
7900 move it to the correct pointer register */
7901 type = operandType (left);
7902 etype = getSpec (type);
7903 /* if left is of type of pointer then it is simple */
7904 if (IS_PTR (type) && !IS_FUNC (type->next))
7905 p_type = DCL_TYPE (type);
7908 /* we have to go by the storage class */
7909 p_type = PTR_TYPE (SPEC_OCLS (etype));
7912 /* special case when cast remat */
7913 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7914 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7915 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7916 type = operandType (left);
7917 p_type = DCL_TYPE (type);
7919 /* now that we have the pointer type we assign
7920 the pointer values */
7926 genNearPointerGet (left, result, ic, pi);
7930 genPagedPointerGet (left, result, ic, pi);
7934 genFarPointerGet (left, result, ic, pi);
7938 genCodePointerGet (left, result, ic, pi);
7942 genGenPointerGet (left, result, ic, pi);
7950 /*-----------------------------------------------------------------*/
7951 /* genPackBits - generates code for packed bit storage */
7952 /*-----------------------------------------------------------------*/
7954 genPackBits (sym_link * etype,
7956 char *rname, int p_type)
7958 int offset = 0; /* source byte offset */
7959 int rlen = 0; /* remaining bitfield length */
7960 int blen; /* bitfield length */
7961 int bstr; /* bitfield starting bit within byte */
7962 int litval; /* source literal value (if AOP_LIT) */
7963 unsigned char mask; /* bitmask within current byte */
7965 D(emitcode ("; genPackBits",""));
7967 blen = SPEC_BLEN (etype);
7968 bstr = SPEC_BSTR (etype);
7970 /* If the bitfield length is less than a byte */
7973 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7974 (unsigned char) (0xFF >> (8 - bstr)));
7976 if (AOP_TYPE (right) == AOP_LIT)
7978 /* Case with a bitfield length <8 and literal source
7980 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7982 litval &= (~mask) & 0xff;
7983 emitPtrByteGet (rname, p_type, FALSE);
7984 if ((mask|litval)!=0xff)
7985 emitcode ("anl","a,#0x%02x", mask);
7987 emitcode ("orl","a,#0x%02x", litval);
7991 if ((blen==1) && (p_type!=GPOINTER))
7993 /* Case with a bitfield length == 1 and no generic pointer
7995 if (AOP_TYPE (right) == AOP_CRY)
7996 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7999 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8000 emitcode ("rrc","a");
8002 emitPtrByteGet (rname, p_type, FALSE);
8003 emitcode ("mov","acc.%d,c",bstr);
8007 /* Case with a bitfield length < 8 and arbitrary source
8009 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
8010 /* shift and mask source value */
8012 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8014 /* transfer A to B and get next byte */
8015 emitPtrByteGet (rname, p_type, TRUE);
8017 emitcode ("anl", "a,#0x%02x", mask);
8018 emitcode ("orl", "a,b");
8019 if (p_type == GPOINTER)
8020 emitcode ("pop", "b");
8024 emitPtrByteSet (rname, p_type, "a");
8028 /* Bit length is greater than 7 bits. In this case, copy */
8029 /* all except the partial byte at the end */
8030 for (rlen=blen;rlen>=8;rlen-=8)
8032 emitPtrByteSet (rname, p_type,
8033 aopGet (AOP (right), offset++, FALSE, TRUE) );
8035 emitcode ("inc", "%s", rname);
8038 /* If there was a partial byte at the end */
8041 mask = (((unsigned char) -1 << rlen) & 0xff);
8043 if (AOP_TYPE (right) == AOP_LIT)
8045 /* Case with partial byte and literal source
8047 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8048 litval >>= (blen-rlen);
8049 litval &= (~mask) & 0xff;
8050 emitPtrByteGet (rname, p_type, FALSE);
8051 if ((mask|litval)!=0xff)
8052 emitcode ("anl","a,#0x%02x", mask);
8054 emitcode ("orl","a,#0x%02x", litval);
8058 /* Case with partial byte and arbitrary source
8060 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8061 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8063 /* transfer A to B and get next byte */
8064 emitPtrByteGet (rname, p_type, TRUE);
8066 emitcode ("anl", "a,#0x%02x", mask);
8067 emitcode ("orl", "a,b");
8068 if (p_type == GPOINTER)
8069 emitcode ("pop", "b");
8071 emitPtrByteSet (rname, p_type, "a");
8077 /*-----------------------------------------------------------------*/
8078 /* genDataPointerSet - remat pointer to data space */
8079 /*-----------------------------------------------------------------*/
8081 genDataPointerSet (operand * right,
8085 int size, offset = 0;
8086 char *l, buffer[256];
8088 D(emitcode ("; genDataPointerSet",""));
8090 aopOp (right, ic, FALSE);
8092 l = aopGet (AOP (result), 0, FALSE, TRUE);
8093 size = AOP_SIZE (right);
8097 sprintf (buffer, "(%s + %d)", l + 1, offset);
8099 sprintf (buffer, "%s", l + 1);
8100 emitcode ("mov", "%s,%s", buffer,
8101 aopGet (AOP (right), offset++, FALSE, FALSE));
8104 freeAsmop (right, NULL, ic, TRUE);
8105 freeAsmop (result, NULL, ic, TRUE);
8108 /*-----------------------------------------------------------------*/
8109 /* genNearPointerSet - emitcode for near pointer put */
8110 /*-----------------------------------------------------------------*/
8112 genNearPointerSet (operand * right,
8120 sym_link *retype, *letype;
8121 sym_link *ptype = operandType (result);
8123 D(emitcode ("; genNearPointerSet",""));
8125 retype = getSpec (operandType (right));
8126 letype = getSpec (ptype);
8127 aopOp (result, ic, FALSE);
8129 /* if the result is rematerializable &
8130 in data space & not a bit variable */
8131 if (AOP_TYPE (result) == AOP_IMMD &&
8132 DCL_TYPE (ptype) == POINTER &&
8133 !IS_BITVAR (retype) &&
8134 !IS_BITVAR (letype))
8136 genDataPointerSet (right, result, ic);
8140 /* if the value is already in a pointer register
8141 then don't need anything more */
8142 if (!AOP_INPREG (AOP (result)))
8145 //AOP_TYPE (result) == AOP_STK
8149 // Aha, it is a pointer, just in disguise.
8150 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8153 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8154 __FILE__, __LINE__);
8159 emitcode ("mov", "a%s,%s", rname + 1, rname);
8160 rname++; // skip the '@'.
8165 /* otherwise get a free pointer register */
8167 preg = getFreePtr (ic, &aop, FALSE);
8168 emitcode ("mov", "%s,%s",
8170 aopGet (AOP (result), 0, FALSE, TRUE));
8176 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8179 aopOp (right, ic, FALSE);
8181 /* if bitfield then unpack the bits */
8182 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8183 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8186 /* we have can just get the values */
8187 int size = AOP_SIZE (right);
8192 l = aopGet (AOP (right), offset, FALSE, TRUE);
8196 emitcode ("mov", "@%s,a", rname);
8199 emitcode ("mov", "@%s,%s", rname, l);
8201 emitcode ("inc", "%s", rname);
8206 /* now some housekeeping stuff */
8207 if (aop) /* we had to allocate for this iCode */
8210 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8211 freeAsmop (NULL, aop, ic, TRUE);
8215 /* we did not allocate which means left
8216 already in a pointer register, then
8217 if size > 0 && this could be used again
8218 we have to point it back to where it
8220 if ((AOP_SIZE (right) > 1 &&
8221 !OP_SYMBOL (result)->remat &&
8222 (OP_SYMBOL (result)->liveTo > ic->seq ||
8226 int size = AOP_SIZE (right) - 1;
8228 emitcode ("dec", "%s", rname);
8233 if (pi) pi->generated = 1;
8234 freeAsmop (result, NULL, ic, TRUE);
8235 freeAsmop (right, NULL, ic, TRUE);
8238 /*-----------------------------------------------------------------*/
8239 /* genPagedPointerSet - emitcode for Paged pointer put */
8240 /*-----------------------------------------------------------------*/
8242 genPagedPointerSet (operand * right,
8250 sym_link *retype, *letype;
8252 D(emitcode ("; genPagedPointerSet",""));
8254 retype = getSpec (operandType (right));
8255 letype = getSpec (operandType (result));
8257 aopOp (result, ic, FALSE);
8259 /* if the value is already in a pointer register
8260 then don't need anything more */
8261 if (!AOP_INPREG (AOP (result)))
8263 /* otherwise get a free pointer register */
8265 preg = getFreePtr (ic, &aop, FALSE);
8266 emitcode ("mov", "%s,%s",
8268 aopGet (AOP (result), 0, FALSE, TRUE));
8272 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8274 aopOp (right, ic, FALSE);
8276 /* if bitfield then unpack the bits */
8277 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8278 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8281 /* we have can just get the values */
8282 int size = AOP_SIZE (right);
8287 l = aopGet (AOP (right), offset, FALSE, TRUE);
8290 emitcode ("movx", "@%s,a", rname);
8293 emitcode ("inc", "%s", rname);
8299 /* now some housekeeping stuff */
8300 if (aop) /* we had to allocate for this iCode */
8303 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8304 freeAsmop (NULL, aop, ic, TRUE);
8308 /* we did not allocate which means left
8309 already in a pointer register, then
8310 if size > 0 && this could be used again
8311 we have to point it back to where it
8313 if (AOP_SIZE (right) > 1 &&
8314 !OP_SYMBOL (result)->remat &&
8315 (OP_SYMBOL (result)->liveTo > ic->seq ||
8318 int size = AOP_SIZE (right) - 1;
8320 emitcode ("dec", "%s", rname);
8325 if (pi) pi->generated = 1;
8326 freeAsmop (result, NULL, ic, TRUE);
8327 freeAsmop (right, NULL, ic, TRUE);
8332 /*-----------------------------------------------------------------*/
8333 /* genFarPointerSet - set value from far space */
8334 /*-----------------------------------------------------------------*/
8336 genFarPointerSet (operand * right,
8337 operand * result, iCode * ic, iCode * pi)
8340 sym_link *retype = getSpec (operandType (right));
8341 sym_link *letype = getSpec (operandType (result));
8343 D(emitcode ("; genFarPointerSet",""));
8345 aopOp (result, ic, FALSE);
8346 loadDptrFromOperand (result, FALSE);
8348 /* so dptr know contains the address */
8349 aopOp (right, ic, FALSE);
8351 /* if bit then unpack */
8352 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8353 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8356 size = AOP_SIZE (right);
8361 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8363 emitcode ("movx", "@dptr,a");
8365 emitcode ("inc", "dptr");
8368 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8369 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8370 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8373 freeAsmop (result, NULL, ic, TRUE);
8374 freeAsmop (right, NULL, ic, TRUE);
8377 /*-----------------------------------------------------------------*/
8378 /* genGenPointerSet - set value from generic pointer space */
8379 /*-----------------------------------------------------------------*/
8381 genGenPointerSet (operand * right,
8382 operand * result, iCode * ic, iCode * pi)
8385 sym_link *retype = getSpec (operandType (right));
8386 sym_link *letype = getSpec (operandType (result));
8388 D(emitcode ("; genGenPointerSet",""));
8390 aopOp (result, ic, FALSE);
8391 loadDptrFromOperand (result, TRUE);
8393 /* so dptr know contains the address */
8394 aopOp (right, ic, FALSE);
8396 /* if bit then unpack */
8397 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8398 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8401 size = AOP_SIZE (right);
8406 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8408 emitcode ("lcall", "__gptrput");
8410 emitcode ("inc", "dptr");
8414 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8415 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8416 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8419 freeAsmop (result, NULL, ic, TRUE);
8420 freeAsmop (right, NULL, ic, TRUE);
8423 /*-----------------------------------------------------------------*/
8424 /* genPointerSet - stores the value into a pointer location */
8425 /*-----------------------------------------------------------------*/
8427 genPointerSet (iCode * ic, iCode *pi)
8429 operand *right, *result;
8430 sym_link *type, *etype;
8433 D(emitcode ("; genPointerSet",""));
8435 right = IC_RIGHT (ic);
8436 result = IC_RESULT (ic);
8438 /* depending on the type of pointer we need to
8439 move it to the correct pointer register */
8440 type = operandType (result);
8441 etype = getSpec (type);
8442 /* if left is of type of pointer then it is simple */
8443 if (IS_PTR (type) && !IS_FUNC (type->next))
8445 p_type = DCL_TYPE (type);
8449 /* we have to go by the storage class */
8450 p_type = PTR_TYPE (SPEC_OCLS (etype));
8453 /* special case when cast remat */
8454 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8455 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8456 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8457 type = operandType (result);
8458 p_type = DCL_TYPE (type);
8460 /* now that we have the pointer type we assign
8461 the pointer values */
8467 genNearPointerSet (right, result, ic, pi);
8471 genPagedPointerSet (right, result, ic, pi);
8475 genFarPointerSet (right, result, ic, pi);
8479 genGenPointerSet (right, result, ic, pi);
8483 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8484 "genPointerSet: illegal pointer type");
8489 /*-----------------------------------------------------------------*/
8490 /* genIfx - generate code for Ifx statement */
8491 /*-----------------------------------------------------------------*/
8493 genIfx (iCode * ic, iCode * popIc)
8495 operand *cond = IC_COND (ic);
8498 D(emitcode ("; genIfx",""));
8500 aopOp (cond, ic, FALSE);
8502 /* get the value into acc */
8503 if (AOP_TYPE (cond) != AOP_CRY)
8507 /* the result is now in the accumulator */
8508 freeAsmop (cond, NULL, ic, TRUE);
8510 /* if there was something to be popped then do it */
8514 /* if the condition is a bit variable */
8515 if (isbit && IS_ITEMP (cond) &&
8517 genIfxJump (ic, SPIL_LOC (cond)->rname);
8518 else if (isbit && !IS_ITEMP (cond))
8519 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8521 genIfxJump (ic, "a");
8526 /*-----------------------------------------------------------------*/
8527 /* genAddrOf - generates code for address of */
8528 /*-----------------------------------------------------------------*/
8530 genAddrOf (iCode * ic)
8532 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8535 D(emitcode ("; genAddrOf",""));
8537 aopOp (IC_RESULT (ic), ic, FALSE);
8539 /* if the operand is on the stack then we
8540 need to get the stack offset of this
8544 /* if it has an offset then we need to compute
8548 emitcode ("mov", "a,_bp");
8549 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8550 ((char) (sym->stack - _G.nRegsSaved)) :
8551 ((char) sym->stack)) & 0xff);
8552 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8556 /* we can just move _bp */
8557 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8559 /* fill the result with zero */
8560 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8565 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8571 /* object not on stack then we need the name */
8572 size = AOP_SIZE (IC_RESULT (ic));
8577 char s[SDCC_NAME_MAX];
8579 sprintf (s, "#(%s >> %d)",
8583 sprintf (s, "#%s", sym->rname);
8584 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8588 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8592 /*-----------------------------------------------------------------*/
8593 /* genFarFarAssign - assignment when both are in far space */
8594 /*-----------------------------------------------------------------*/
8596 genFarFarAssign (operand * result, operand * right, iCode * ic)
8598 int size = AOP_SIZE (right);
8602 D(emitcode ("; genFarFarAssign",""));
8604 /* first push the right side on to the stack */
8607 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8609 emitcode ("push", "acc");
8612 freeAsmop (right, NULL, ic, FALSE);
8613 /* now assign DPTR to result */
8614 aopOp (result, ic, FALSE);
8615 size = AOP_SIZE (result);
8618 emitcode ("pop", "acc");
8619 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8621 freeAsmop (result, NULL, ic, FALSE);
8625 /*-----------------------------------------------------------------*/
8626 /* genAssign - generate code for assignment */
8627 /*-----------------------------------------------------------------*/
8629 genAssign (iCode * ic)
8631 operand *result, *right;
8633 unsigned long lit = 0L;
8635 D(emitcode("; genAssign",""));
8637 result = IC_RESULT (ic);
8638 right = IC_RIGHT (ic);
8640 /* if they are the same */
8641 if (operandsEqu (result, right) &&
8642 !isOperandVolatile (result, FALSE) &&
8643 !isOperandVolatile (right, FALSE))
8646 aopOp (right, ic, FALSE);
8648 /* special case both in far space */
8649 if (AOP_TYPE (right) == AOP_DPTR &&
8650 IS_TRUE_SYMOP (result) &&
8651 isOperandInFarSpace (result))
8654 genFarFarAssign (result, right, ic);
8658 aopOp (result, ic, TRUE);
8660 /* if they are the same registers */
8661 if (sameRegs (AOP (right), AOP (result)) &&
8662 !isOperandVolatile (result, FALSE) &&
8663 !isOperandVolatile (right, FALSE))
8666 /* if the result is a bit */
8667 if (AOP_TYPE (result) == AOP_CRY)
8670 /* if the right size is a literal then
8671 we know what the value is */
8672 if (AOP_TYPE (right) == AOP_LIT)
8674 if (((int) operandLitValue (right)))
8675 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8677 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8681 /* the right is also a bit variable */
8682 if (AOP_TYPE (right) == AOP_CRY)
8684 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8685 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8691 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8695 /* bit variables done */
8697 size = AOP_SIZE (result);
8699 if (AOP_TYPE (right) == AOP_LIT)
8700 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8702 (AOP_TYPE (result) != AOP_REG) &&
8703 (AOP_TYPE (right) == AOP_LIT) &&
8704 !IS_FLOAT (operandType (right)) &&
8707 emitcode ("clr", "a");
8710 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8711 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8713 aopPut (AOP (result),
8714 aopGet (AOP (right), size, FALSE, FALSE),
8716 isOperandVolatile (result, FALSE));
8723 aopPut (AOP (result),
8724 aopGet (AOP (right), offset, FALSE, FALSE),
8726 isOperandVolatile (result, FALSE));
8732 freeAsmop (right, NULL, ic, TRUE);
8733 freeAsmop (result, NULL, ic, TRUE);
8736 /*-----------------------------------------------------------------*/
8737 /* genJumpTab - genrates code for jump table */
8738 /*-----------------------------------------------------------------*/
8740 genJumpTab (iCode * ic)
8745 D(emitcode ("; genJumpTab",""));
8747 aopOp (IC_JTCOND (ic), ic, FALSE);
8748 /* get the condition into accumulator */
8749 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8751 /* multiply by three */
8752 emitcode ("add", "a,acc");
8753 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8754 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8756 jtab = newiTempLabel (NULL);
8757 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8758 emitcode ("jmp", "@a+dptr");
8759 emitcode ("", "%05d$:", jtab->key + 100);
8760 /* now generate the jump labels */
8761 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8762 jtab = setNextItem (IC_JTLABELS (ic)))
8763 emitcode ("ljmp", "%05d$", jtab->key + 100);
8767 /*-----------------------------------------------------------------*/
8768 /* genCast - gen code for casting */
8769 /*-----------------------------------------------------------------*/
8771 genCast (iCode * ic)
8773 operand *result = IC_RESULT (ic);
8774 sym_link *ctype = operandType (IC_LEFT (ic));
8775 sym_link *rtype = operandType (IC_RIGHT (ic));
8776 operand *right = IC_RIGHT (ic);
8779 D(emitcode("; genCast",""));
8781 /* if they are equivalent then do nothing */
8782 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8785 aopOp (right, ic, FALSE);
8786 aopOp (result, ic, FALSE);
8788 /* if the result is a bit (and not a bitfield) */
8789 // if (AOP_TYPE (result) == AOP_CRY)
8790 if (IS_BITVAR (OP_SYMBOL (result)->type)
8791 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8793 /* if the right size is a literal then
8794 we know what the value is */
8795 if (AOP_TYPE (right) == AOP_LIT)
8797 if (((int) operandLitValue (right)))
8798 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8800 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8805 /* the right is also a bit variable */
8806 if (AOP_TYPE (right) == AOP_CRY)
8808 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8809 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8815 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8820 /* if they are the same size : or less */
8821 if (AOP_SIZE (result) <= AOP_SIZE (right))
8824 /* if they are in the same place */
8825 if (sameRegs (AOP (right), AOP (result)))
8828 /* if they in different places then copy */
8829 size = AOP_SIZE (result);
8833 aopPut (AOP (result),
8834 aopGet (AOP (right), offset, FALSE, FALSE),
8836 isOperandVolatile (result, FALSE));
8843 /* if the result is of type pointer */
8848 sym_link *type = operandType (right);
8849 sym_link *etype = getSpec (type);
8851 /* pointer to generic pointer */
8852 if (IS_GENPTR (ctype))
8855 p_type = DCL_TYPE (type);
8858 if (SPEC_SCLS(etype)==S_REGISTER) {
8859 // let's assume it is a generic pointer
8862 /* we have to go by the storage class */
8863 p_type = PTR_TYPE (SPEC_OCLS (etype));
8867 /* the first two bytes are known */
8868 size = GPTRSIZE - 1;
8872 aopPut (AOP (result),
8873 aopGet (AOP (right), offset, FALSE, FALSE),
8875 isOperandVolatile (result, FALSE));
8878 /* the last byte depending on type */
8880 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8885 // pointerTypeToGPByte will have bitched.
8889 sprintf(gpValStr, "#0x%d", gpVal);
8890 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8895 /* just copy the pointers */
8896 size = AOP_SIZE (result);
8900 aopPut (AOP (result),
8901 aopGet (AOP (right), offset, FALSE, FALSE),
8903 isOperandVolatile (result, FALSE));
8909 /* so we now know that the size of destination is greater
8910 than the size of the source */
8911 /* we move to result for the size of source */
8912 size = AOP_SIZE (right);
8916 aopPut (AOP (result),
8917 aopGet (AOP (right), offset, FALSE, FALSE),
8919 isOperandVolatile (result, FALSE));
8923 /* now depending on the sign of the source && destination */
8924 size = AOP_SIZE (result) - AOP_SIZE (right);
8925 /* if unsigned or not an integral type */
8926 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8929 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8933 /* we need to extend the sign :{ */
8934 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8937 emitcode ("rlc", "a");
8938 emitcode ("subb", "a,acc");
8940 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8943 /* we are done hurray !!!! */
8946 freeAsmop (right, NULL, ic, TRUE);
8947 freeAsmop (result, NULL, ic, TRUE);
8951 /*-----------------------------------------------------------------*/
8952 /* genDjnz - generate decrement & jump if not zero instrucion */
8953 /*-----------------------------------------------------------------*/
8955 genDjnz (iCode * ic, iCode * ifx)
8961 D(emitcode ("; genDjnz",""));
8963 /* if the if condition has a false label
8964 then we cannot save */
8968 /* if the minus is not of the form
8970 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8971 !IS_OP_LITERAL (IC_RIGHT (ic)))
8974 if (operandLitValue (IC_RIGHT (ic)) != 1)
8977 /* if the size of this greater than one then no
8979 if (getSize (operandType (IC_RESULT (ic))) > 1)
8982 /* otherwise we can save BIG */
8983 lbl = newiTempLabel (NULL);
8984 lbl1 = newiTempLabel (NULL);
8986 aopOp (IC_RESULT (ic), ic, FALSE);
8988 if (AOP_NEEDSACC(IC_RESULT(ic)))
8990 /* If the result is accessed indirectly via
8991 * the accumulator, we must explicitly write
8992 * it back after the decrement.
8994 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8996 if (strcmp(rByte, "a"))
8998 /* Something is hopelessly wrong */
8999 fprintf(stderr, "*** warning: internal error at %s:%d\n",
9000 __FILE__, __LINE__);
9001 /* We can just give up; the generated code will be inefficient,
9004 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9007 emitcode ("dec", "%s", rByte);
9008 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9009 emitcode ("jnz", "%05d$", lbl->key + 100);
9011 else if (IS_AOP_PREG (IC_RESULT (ic)))
9013 emitcode ("dec", "%s",
9014 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9015 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
9016 emitcode ("jnz", "%05d$", lbl->key + 100);
9020 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
9023 emitcode ("sjmp", "%05d$", lbl1->key + 100);
9024 emitcode ("", "%05d$:", lbl->key + 100);
9025 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
9026 emitcode ("", "%05d$:", lbl1->key + 100);
9028 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9033 /*-----------------------------------------------------------------*/
9034 /* genReceive - generate code for a receive iCode */
9035 /*-----------------------------------------------------------------*/
9037 genReceive (iCode * ic)
9039 int size = getSize (operandType (IC_RESULT (ic)));
9041 D(emitcode ("; genReceive",""));
9043 if (ic->argreg == 1) { /* first parameter */
9044 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9045 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9046 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9048 offset = fReturnSizeMCS51 - size;
9050 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9051 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9054 aopOp (IC_RESULT (ic), ic, FALSE);
9055 size = AOP_SIZE (IC_RESULT (ic));
9058 emitcode ("pop", "acc");
9059 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9064 aopOp (IC_RESULT (ic), ic, FALSE);
9066 assignResultValue (IC_RESULT (ic));
9068 } else { /* second receive onwards */
9070 aopOp (IC_RESULT (ic), ic, FALSE);
9071 rb1off = ic->argreg;
9073 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9076 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9079 /*-----------------------------------------------------------------*/
9080 /* genDummyRead - generate code for dummy read of volatiles */
9081 /*-----------------------------------------------------------------*/
9083 genDummyRead (iCode * ic)
9088 D(emitcode("; genDummyRead",""));
9090 right = IC_RIGHT (ic);
9092 aopOp (right, ic, FALSE);
9094 /* if the result is a bit */
9095 if (AOP_TYPE (right) == AOP_CRY)
9097 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9101 /* bit variables done */
9103 size = AOP_SIZE (right);
9107 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
9112 freeAsmop (right, NULL, ic, TRUE);
9115 /*-----------------------------------------------------------------*/
9116 /* genCritical - generate code for start of a critical sequence */
9117 /*-----------------------------------------------------------------*/
9119 genCritical (iCode *ic)
9121 symbol *tlbl = newiTempLabel (NULL);
9123 D(emitcode("; genCritical",""));
9126 aopOp (IC_RESULT (ic), ic, TRUE);
9128 emitcode ("setb", "c");
9129 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9130 emitcode ("clr", "c");
9131 emitcode ("", "%05d$:", (tlbl->key + 100));
9134 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9136 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9139 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9142 /*-----------------------------------------------------------------*/
9143 /* genEndCritical - generate code for end of a critical sequence */
9144 /*-----------------------------------------------------------------*/
9146 genEndCritical (iCode *ic)
9148 D(emitcode("; genEndCritical",""));
9152 aopOp (IC_RIGHT (ic), ic, FALSE);
9153 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9155 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9156 emitcode ("mov", "ea,c");
9160 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9161 emitcode ("rrc", "a");
9162 emitcode ("mov", "ea,c");
9164 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9168 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9169 emitcode ("mov", "ea,c");
9174 /*-----------------------------------------------------------------*/
9175 /* gen51Code - generate code for 8051 based controllers */
9176 /*-----------------------------------------------------------------*/
9178 gen51Code (iCode * lic)
9183 lineHead = lineCurr = NULL;
9185 /* print the allocation information */
9186 if (allocInfo && currFunc)
9187 printAllocInfo (currFunc, codeOutFile);
9188 /* if debug information required */
9189 if (options.debug && currFunc)
9191 debugFile->writeFunction(currFunc);
9193 if (IS_STATIC (currFunc->etype))
9194 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9196 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9199 /* stack pointer name */
9200 if (options.useXstack)
9206 for (ic = lic; ic; ic = ic->next)
9208 _G.current_iCode = ic;
9210 if (ic->lineno && cln != ic->lineno)
9215 emitcode ("", "C$%s$%d$%d$%d ==.",
9216 FileBaseName (ic->filename), ic->lineno,
9217 ic->level, ic->block);
9220 if (!options.noCcodeInAsm) {
9221 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9222 printCLine(ic->filename, ic->lineno));
9226 if (options.iCodeInAsm) {
9230 for (i=0; i<8; i++) {
9231 sprintf (®sInUse[i],
9232 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9235 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9237 /* if the result is marked as
9238 spilt and rematerializable or code for
9239 this has already been generated then
9241 if (resultRemat (ic) || ic->generated)
9244 /* depending on the operation */
9264 /* IPOP happens only when trying to restore a
9265 spilt live range, if there is an ifx statement
9266 following this pop then the if statement might
9267 be using some of the registers being popped which
9268 would destory the contents of the register so
9269 we need to check for this condition and handle it */
9271 ic->next->op == IFX &&
9272 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9273 genIfx (ic->next, ic);
9291 genEndFunction (ic);
9311 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9328 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9332 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9339 /* note these two are xlated by algebraic equivalence
9340 during parsing SDCC.y */
9341 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9342 "got '>=' or '<=' shouldn't have come here");
9346 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9358 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9362 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9366 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9393 case GET_VALUE_AT_ADDRESS:
9394 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9398 if (POINTER_SET (ic))
9399 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9425 addSet (&_G.sendSet, ic);
9428 case DUMMY_READ_VOLATILE:
9437 genEndCritical (ic);
9449 _G.current_iCode = NULL;
9451 /* now we are ready to call the
9452 peep hole optimizer */
9453 if (!options.nopeep)
9454 peepHole (&lineHead);
9456 /* now do the actual printing */
9457 printLine (lineHead, codeOutFile);