1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
42 #include "SDCCpeeph.h"
46 char *aopLiteral (value * val, int offset);
49 /* this is the down and dirty file with all kinds of
50 kludgy & hacky stuff. This is what it is all about
51 CODE GENERATION for a specific MCU . some of the
52 routines may be reusable, will have to see */
54 static char *zero = "#0x00";
55 static char *one = "#0x01";
59 {"dpl", "dph", "b", "a"};
60 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
61 char **fReturn = fReturn8051;
62 static char *accUse[] =
65 static unsigned short rbank = -1;
80 static char *rb1regs[] = {
81 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
84 extern int mcs51_ptrRegReq;
85 extern int mcs51_nRegs;
86 extern FILE *codeOutFile;
87 static void saveRBank (int, iCode *, bool);
88 #define RESULTONSTACK(x) \
89 (IC_RESULT(x) && IC_RESULT(x)->aop && \
90 IC_RESULT(x)->aop->type == AOP_STK )
92 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
93 #define CLRC emitcode("clr","c")
94 #define SETC emitcode("setb","c")
96 static lineNode *lineHead = NULL;
97 static lineNode *lineCurr = NULL;
99 static unsigned char SLMask[] =
100 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
101 0xE0, 0xC0, 0x80, 0x00};
102 static unsigned char SRMask[] =
103 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
104 0x07, 0x03, 0x01, 0x00};
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple */
113 /*-----------------------------------------------------------------*/
115 emitcode (char *inst, const char *fmt,...)
118 char lb[INITIAL_INLINEASM];
126 sprintf (lb, "%s\t", inst);
128 sprintf (lb, "%s", inst);
129 vsprintf (lb + (strlen (lb)), fmt, ap);
132 vsprintf (lb, fmt, ap);
134 while (isspace (*lbp))
138 lineCurr = (lineCurr ?
139 connectLine (lineCurr, newLineNode (lb)) :
140 (lineHead = newLineNode (lb)));
141 lineCurr->isInline = _G.inLine;
142 lineCurr->isDebug = _G.debugLine;
143 lineCurr->ic = _G.current_iCode;
144 lineCurr->isComment = (*lbp==';');
148 /*-----------------------------------------------------------------*/
149 /* mova - moves specified value into accumulator */
150 /*-----------------------------------------------------------------*/
154 /* do some early peephole optimization */
155 if (!strcmp(x, "a") || !strcmp(x, "acc"))
158 emitcode("mov","a,%s", x);
161 /*-----------------------------------------------------------------*/
162 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
163 /*-----------------------------------------------------------------*/
165 getFreePtr (iCode * ic, asmop ** aopp, bool result)
167 bool r0iu = FALSE, r1iu = FALSE;
168 bool r0ou = FALSE, r1ou = FALSE;
170 /* the logic: if r0 & r1 used in the instruction
171 then we are in trouble otherwise */
173 /* first check if r0 & r1 are used by this
174 instruction, in which case we are in trouble */
175 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
176 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
181 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
182 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
184 /* if no usage of r0 then return it */
187 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
188 (*aopp)->type = AOP_R0;
190 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
193 /* if no usage of r1 then return it */
196 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
197 (*aopp)->type = AOP_R1;
199 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
202 /* now we know they both have usage */
203 /* if r0 not used in this instruction */
206 /* push it if not already pushed */
209 emitcode ("push", "%s",
210 mcs51_regWithIdx (R0_IDX)->dname);
214 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
215 (*aopp)->type = AOP_R0;
217 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
220 /* if r1 not used then */
224 /* push it if not already pushed */
227 emitcode ("push", "%s",
228 mcs51_regWithIdx (R1_IDX)->dname);
232 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
233 (*aopp)->type = AOP_R1;
234 return mcs51_regWithIdx (R1_IDX);
237 /* I said end of world, but not quite end of world yet */
239 /* we can push it on the stack */
240 (*aopp)->type = AOP_STK;
243 /* in the case that result AND left AND right needs a pointer reg
244 we can safely use the result's */
245 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
246 (*aopp)->type = AOP_R0;
247 return mcs51_regWithIdx (R0_IDX);
249 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
250 (*aopp)->type = AOP_R1;
251 return mcs51_regWithIdx (R1_IDX);
255 /* now this is REALLY the end of the world */
256 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
257 "getFreePtr should never reach here");
261 /*-----------------------------------------------------------------*/
262 /* newAsmop - creates a new asmOp */
263 /*-----------------------------------------------------------------*/
265 newAsmop (short type)
269 aop = Safe_calloc (1, sizeof (asmop));
274 /*-----------------------------------------------------------------*/
275 /* pointerCode - returns the code for a pointer type */
276 /*-----------------------------------------------------------------*/
278 pointerCode (sym_link * etype)
281 return PTR_TYPE (SPEC_OCLS (etype));
286 /*-----------------------------------------------------------------*/
287 /* leftRightUseAcc - returns size of accumulator use by operands */
288 /*-----------------------------------------------------------------*/
290 leftRightUseAcc(iCode *ic)
299 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
300 "null iCode pointer");
307 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
310 size = getSize (OP_SYMBOL (op)->type);
315 else if (ic->op == JUMPTABLE)
318 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
321 size = getSize (OP_SYMBOL (op)->type);
329 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
332 size = getSize (OP_SYMBOL (op)->type);
337 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
340 size = getSize (OP_SYMBOL (op)->type);
353 /*-----------------------------------------------------------------*/
354 /* aopForSym - for a true symbol */
355 /*-----------------------------------------------------------------*/
357 aopForSym (iCode * ic, symbol * sym, bool result)
362 wassertl (ic != NULL, "Got a null iCode");
363 wassertl (sym != NULL, "Got a null symbol");
365 space = SPEC_OCLS (sym->etype);
367 /* if already has one */
371 /* assign depending on the storage class */
372 /* if it is on the stack or indirectly addressable */
373 /* space we need to assign either r0 or r1 to it */
374 if (sym->onStack || sym->iaccess)
376 sym->aop = aop = newAsmop (0);
377 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
378 aop->size = getSize (sym->type);
380 /* now assign the address of the variable to
381 the pointer register */
382 if (aop->type != AOP_STK)
387 if (_G.accInUse || leftRightUseAcc (ic))
388 emitcode ("push", "acc");
390 emitcode ("mov", "a,_bp");
391 emitcode ("add", "a,#0x%02x",
393 ((char) (sym->stack - _G.nRegsSaved)) :
394 ((char) sym->stack)) & 0xff);
395 emitcode ("mov", "%s,a",
396 aop->aopu.aop_ptr->name);
398 if (_G.accInUse || leftRightUseAcc (ic))
399 emitcode ("pop", "acc");
402 emitcode ("mov", "%s,#%s",
403 aop->aopu.aop_ptr->name,
405 aop->paged = space->paged;
408 aop->aopu.aop_stk = sym->stack;
412 /* if in bit space */
413 if (IN_BITSPACE (space))
415 sym->aop = aop = newAsmop (AOP_CRY);
416 aop->aopu.aop_dir = sym->rname;
417 aop->size = getSize (sym->type);
420 /* if it is in direct space */
421 if (IN_DIRSPACE (space))
423 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
424 //printTypeChainRaw(sym->type, NULL);
425 //printf("space = %s\n", space ? space->sname : "NULL");
426 sym->aop = aop = newAsmop (AOP_DIR);
427 aop->aopu.aop_dir = sym->rname;
428 aop->size = getSize (sym->type);
432 /* special case for a function */
433 if (IS_FUNC (sym->type))
435 sym->aop = aop = newAsmop (AOP_IMMD);
436 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
437 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
438 aop->size = FPTRSIZE;
442 /* only remaining is far space */
443 /* in which case DPTR gets the address */
444 sym->aop = aop = newAsmop (AOP_DPTR);
445 emitcode ("mov", "dptr,#%s", sym->rname);
446 aop->size = getSize (sym->type);
448 /* if it is in code space */
449 if (IN_CODESPACE (space))
455 /*-----------------------------------------------------------------*/
456 /* aopForRemat - rematerialzes an object */
457 /*-----------------------------------------------------------------*/
459 aopForRemat (symbol * sym)
461 iCode *ic = sym->rematiCode;
462 asmop *aop = newAsmop (AOP_IMMD);
469 val += (int) operandLitValue (IC_RIGHT (ic));
470 else if (ic->op == '-')
471 val -= (int) operandLitValue (IC_RIGHT (ic));
472 else if (IS_CAST_ICODE(ic)) {
473 sym_link *from_type = operandType(IC_RIGHT(ic));
474 aop->aopu.aop_immd.from_cast_remat = 1;
475 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
476 ptr_type = DCL_TYPE(from_type);
477 if (ptr_type == IPOINTER) {
484 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
488 sprintf (buffer, "(%s %c 0x%04x)",
489 OP_SYMBOL (IC_LEFT (ic))->rname,
490 val >= 0 ? '+' : '-',
493 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
495 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
496 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
497 /* set immd2 field if required */
498 if (aop->aopu.aop_immd.from_cast_remat) {
499 sprintf(buffer,"#0x%02x",ptr_type);
500 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
501 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
507 /*-----------------------------------------------------------------*/
508 /* regsInCommon - two operands have some registers in common */
509 /*-----------------------------------------------------------------*/
511 regsInCommon (operand * op1, operand * op2)
516 /* if they have registers in common */
517 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
520 sym1 = OP_SYMBOL (op1);
521 sym2 = OP_SYMBOL (op2);
523 if (sym1->nRegs == 0 || sym2->nRegs == 0)
526 for (i = 0; i < sym1->nRegs; i++)
532 for (j = 0; j < sym2->nRegs; j++)
537 if (sym2->regs[j] == sym1->regs[i])
545 /*-----------------------------------------------------------------*/
546 /* operandsEqu - equivalent */
547 /*-----------------------------------------------------------------*/
549 operandsEqu (operand * op1, operand * op2)
553 /* if they not symbols */
554 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
557 sym1 = OP_SYMBOL (op1);
558 sym2 = OP_SYMBOL (op2);
560 /* if both are itemps & one is spilt
561 and the other is not then false */
562 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
563 sym1->isspilt != sym2->isspilt)
566 /* if they are the same */
570 if (strcmp (sym1->rname, sym2->rname) == 0)
574 /* if left is a tmp & right is not */
575 if (IS_ITEMP (op1) &&
578 (sym1->usl.spillLoc == sym2))
581 if (IS_ITEMP (op2) &&
585 (sym2->usl.spillLoc == sym1))
591 /*-----------------------------------------------------------------*/
592 /* sameRegs - two asmops have the same registers */
593 /*-----------------------------------------------------------------*/
595 sameRegs (asmop * aop1, asmop * aop2)
602 if (aop1->type != AOP_REG ||
603 aop2->type != AOP_REG)
606 if (aop1->size != aop2->size)
609 for (i = 0; i < aop1->size; i++)
610 if (aop1->aopu.aop_reg[i] !=
611 aop2->aopu.aop_reg[i])
617 /*-----------------------------------------------------------------*/
618 /* aopOp - allocates an asmop for an operand : */
619 /*-----------------------------------------------------------------*/
621 aopOp (operand * op, iCode * ic, bool result)
630 /* if this a literal */
631 if (IS_OP_LITERAL (op))
633 op->aop = aop = newAsmop (AOP_LIT);
634 aop->aopu.aop_lit = op->operand.valOperand;
635 aop->size = getSize (operandType (op));
639 /* if already has a asmop then continue */
643 /* if the underlying symbol has a aop */
644 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
646 op->aop = OP_SYMBOL (op)->aop;
650 /* if this is a true symbol */
651 if (IS_TRUE_SYMOP (op))
653 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
657 /* this is a temporary : this has
663 e) can be a return use only */
665 sym = OP_SYMBOL (op);
667 /* if the type is a conditional */
668 if (sym->regType == REG_CND)
670 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
675 /* if it is spilt then two situations
677 b) has a spill location */
678 if (sym->isspilt || sym->nRegs == 0)
681 /* rematerialize it NOW */
684 sym->aop = op->aop = aop =
686 aop->size = getSize (sym->type);
693 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
694 aop->size = getSize (sym->type);
695 for (i = 0; i < 2; i++)
696 aop->aopu.aop_str[i] = accUse[i];
704 aop = op->aop = sym->aop = newAsmop (AOP_STR);
705 aop->size = getSize (sym->type);
706 for (i = 0; i < fReturnSizeMCS51; i++)
707 aop->aopu.aop_str[i] = fReturn[i];
711 if (sym->usl.spillLoc)
713 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
715 /* force a new aop if sizes differ */
716 sym->usl.spillLoc->aop = NULL;
718 sym->aop = op->aop = aop =
719 aopForSym (ic, sym->usl.spillLoc, result);
720 aop->size = getSize (sym->type);
724 /* else must be a dummy iTemp */
725 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
726 aop->size = getSize (sym->type);
730 /* must be in a register */
731 sym->aop = op->aop = aop = newAsmop (AOP_REG);
732 aop->size = sym->nRegs;
733 for (i = 0; i < sym->nRegs; i++)
734 aop->aopu.aop_reg[i] = sym->regs[i];
737 /*-----------------------------------------------------------------*/
738 /* freeAsmop - free up the asmop given to an operand */
739 /*----------------------------------------------------------------*/
741 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
758 /* depending on the asmop type only three cases need work AOP_RO
759 , AOP_R1 && AOP_STK */
767 emitcode ("pop", "ar0");
771 bitVectUnSetBit (ic->rUsed, R0_IDX);
779 emitcode ("pop", "ar1");
783 bitVectUnSetBit (ic->rUsed, R1_IDX);
789 int stk = aop->aopu.aop_stk + aop->size - 1;
790 bitVectUnSetBit (ic->rUsed, R0_IDX);
791 bitVectUnSetBit (ic->rUsed, R1_IDX);
793 getFreePtr (ic, &aop, FALSE);
797 emitcode ("mov", "a,_bp");
798 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
799 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
803 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
808 emitcode ("pop", "acc");
809 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
812 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
815 freeAsmop (op, NULL, ic, TRUE);
818 emitcode ("pop", "ar1");
824 emitcode ("pop", "ar0");
831 /* all other cases just dealloc */
837 OP_SYMBOL (op)->aop = NULL;
838 /* if the symbol has a spill */
840 SPIL_LOC (op)->aop = NULL;
845 /*-----------------------------------------------------------------*/
846 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
847 /* clobber the accumulator */
848 /*-----------------------------------------------------------------*/
850 aopGetUsesAcc (asmop *aop, int offset)
852 if (offset > (aop->size - 1))
870 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
879 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
885 /* Error case --- will have been caught already */
891 /*-----------------------------------------------------------------*/
892 /* aopGet - for fetching value of the aop */
893 /*-----------------------------------------------------------------*/
895 aopGet (asmop * aop, int offset, bool bit16, bool dname)
900 /* offset is greater than
902 if (offset > (aop->size - 1) &&
903 aop->type != AOP_LIT)
906 /* depending on type */
914 /* if we need to increment it */
915 while (offset > aop->coff)
917 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
921 while (offset < aop->coff)
923 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
930 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
931 return (dname ? "acc" : "a");
933 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
934 rs = Safe_calloc (1, strlen (s) + 1);
939 if (aop->code && aop->coff==0 && offset>=1) {
940 emitcode ("mov", "a,#0x%02x", offset);
941 emitcode ("movc", "a,@a+dptr");
942 return (dname ? "acc" : "a");
945 while (offset > aop->coff)
947 emitcode ("inc", "dptr");
951 while (offset < aop->coff)
953 emitcode ("lcall", "__decdptr");
960 emitcode ("clr", "a");
961 emitcode ("movc", "a,@a+dptr");
965 emitcode ("movx", "a,@dptr");
967 return (dname ? "acc" : "a");
971 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
972 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
974 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
976 sprintf (s, "#(%s >> %d)",
977 aop->aopu.aop_immd.aop_immd1,
981 aop->aopu.aop_immd.aop_immd1);
982 rs = Safe_calloc (1, strlen (s) + 1);
988 sprintf (s, "(%s + %d)",
992 sprintf (s, "%s", aop->aopu.aop_dir);
993 rs = Safe_calloc (1, strlen (s) + 1);
999 return aop->aopu.aop_reg[offset]->dname;
1001 return aop->aopu.aop_reg[offset]->name;
1004 emitcode ("clr", "a");
1005 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1006 emitcode ("rlc", "a");
1007 return (dname ? "acc" : "a");
1010 if (!offset && dname)
1012 return aop->aopu.aop_str[offset];
1015 return aopLiteral (aop->aopu.aop_lit, offset);
1019 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1023 return aop->aopu.aop_str[offset];
1027 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1028 "aopget got unsupported aop->type");
1031 /*-----------------------------------------------------------------*/
1032 /* aopPut - puts a string for a aop */
1033 /*-----------------------------------------------------------------*/
1035 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1039 if (aop->size && offset > (aop->size - 1))
1041 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1042 "aopPut got offset > aop->size");
1046 /* will assign value to value */
1047 /* depending on where it is ofcourse */
1051 MOVA (s); /* read s in case it was volatile */
1056 sprintf (d, "(%s + %d)",
1057 aop->aopu.aop_dir, offset);
1059 sprintf (d, "%s", aop->aopu.aop_dir);
1061 if (strcmp (d, s) ||
1063 emitcode ("mov", "%s,%s", d, s);
1068 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1069 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1072 strcmp (s, "r0") == 0 ||
1073 strcmp (s, "r1") == 0 ||
1074 strcmp (s, "r2") == 0 ||
1075 strcmp (s, "r3") == 0 ||
1076 strcmp (s, "r4") == 0 ||
1077 strcmp (s, "r5") == 0 ||
1078 strcmp (s, "r6") == 0 ||
1079 strcmp (s, "r7") == 0)
1080 emitcode ("mov", "%s,%s",
1081 aop->aopu.aop_reg[offset]->dname, s);
1083 emitcode ("mov", "%s,%s",
1084 aop->aopu.aop_reg[offset]->name, s);
1091 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1092 "aopPut writing to code space");
1096 while (offset > aop->coff)
1099 emitcode ("inc", "dptr");
1102 while (offset < aop->coff)
1105 emitcode ("lcall", "__decdptr");
1110 /* if not in accumulater */
1113 emitcode ("movx", "@dptr,a");
1118 while (offset > aop->coff)
1121 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1123 while (offset < aop->coff)
1126 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1133 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1139 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1141 else if (strcmp (s, "r0") == 0 ||
1142 strcmp (s, "r1") == 0 ||
1143 strcmp (s, "r2") == 0 ||
1144 strcmp (s, "r3") == 0 ||
1145 strcmp (s, "r4") == 0 ||
1146 strcmp (s, "r5") == 0 ||
1147 strcmp (s, "r6") == 0 ||
1148 strcmp (s, "r7") == 0)
1151 sprintf (buffer, "a%s", s);
1152 emitcode ("mov", "@%s,%s",
1153 aop->aopu.aop_ptr->name, buffer);
1156 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1161 if (strcmp (s, "a") == 0)
1162 emitcode ("push", "acc");
1166 emitcode ("push", "acc");
1168 emitcode ("push", s);
1174 /* if bit variable */
1175 if (!aop->aopu.aop_dir)
1177 emitcode ("clr", "a");
1178 emitcode ("rlc", "a");
1183 emitcode ("clr", "%s", aop->aopu.aop_dir);
1185 emitcode ("setb", "%s", aop->aopu.aop_dir);
1186 else if (!strcmp (s, "c"))
1187 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1190 if (strcmp (s, "a"))
1195 /* set C, if a >= 1 */
1196 emitcode ("add", "a,#0xff");
1197 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1205 if (strcmp (aop->aopu.aop_str[offset], s) ||
1207 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1212 if (!offset && (strcmp (s, "acc") == 0) &&
1216 if (strcmp (aop->aopu.aop_str[offset], s) &&
1218 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1222 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1223 "aopPut got unsupported aop->type");
1231 /*-----------------------------------------------------------------*/
1232 /* pointToEnd :- points to the last byte of the operand */
1233 /*-----------------------------------------------------------------*/
1235 pointToEnd (asmop * aop)
1241 aop->coff = count = (aop->size - 1);
1247 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1251 emitcode ("inc", "dptr");
1258 /*-----------------------------------------------------------------*/
1259 /* reAdjustPreg - points a register back to where it should */
1260 /*-----------------------------------------------------------------*/
1262 reAdjustPreg (asmop * aop)
1264 if ((aop->coff==0) || aop->size <= 1)
1272 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1277 emitcode ("lcall", "__decdptr");
1284 #define AOP(op) op->aop
1285 #define AOP_TYPE(op) AOP(op)->type
1286 #define AOP_SIZE(op) AOP(op)->size
1287 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1288 AOP_TYPE(x) == AOP_R0))
1290 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1291 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1293 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1294 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1295 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1298 /*-----------------------------------------------------------------*/
1299 /* opIsGptr: returns non-zero if the passed operand is */
1300 /* a generic pointer type. */
1301 /*-----------------------------------------------------------------*/
1303 opIsGptr (operand * op)
1305 sym_link *type = operandType (op);
1307 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1314 /*-----------------------------------------------------------------*/
1315 /* getDataSize - get the operand data size */
1316 /*-----------------------------------------------------------------*/
1318 getDataSize (operand * op)
1321 size = AOP_SIZE (op);
1322 if (size == GPTRSIZE)
1324 sym_link *type = operandType (op);
1325 if (IS_GENPTR (type))
1327 /* generic pointer; arithmetic operations
1328 * should ignore the high byte (pointer type).
1336 /*-----------------------------------------------------------------*/
1337 /* outAcc - output Acc */
1338 /*-----------------------------------------------------------------*/
1340 outAcc (operand * result)
1343 size = getDataSize (result);
1346 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1349 /* unsigned or positive */
1352 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1357 /*-----------------------------------------------------------------*/
1358 /* outBitC - output a bit C */
1359 /*-----------------------------------------------------------------*/
1361 outBitC (operand * result)
1363 /* if the result is bit */
1364 if (AOP_TYPE (result) == AOP_CRY)
1365 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1368 emitcode ("clr", "a");
1369 emitcode ("rlc", "a");
1374 /*-----------------------------------------------------------------*/
1375 /* toBoolean - emit code for orl a,operator(sizeop) */
1376 /*-----------------------------------------------------------------*/
1378 toBoolean (operand * oper)
1380 int size = AOP_SIZE (oper) - 1;
1382 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1384 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1388 /*-----------------------------------------------------------------*/
1389 /* genNot - generate code for ! operation */
1390 /*-----------------------------------------------------------------*/
1396 D(emitcode ("; genNot",""));
1398 /* assign asmOps to operand & result */
1399 aopOp (IC_LEFT (ic), ic, FALSE);
1400 aopOp (IC_RESULT (ic), ic, TRUE);
1402 /* if in bit space then a special case */
1403 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1405 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1406 emitcode ("cpl", "c");
1407 outBitC (IC_RESULT (ic));
1411 toBoolean (IC_LEFT (ic));
1413 tlbl = newiTempLabel (NULL);
1414 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1415 emitcode ("", "%05d$:", tlbl->key + 100);
1416 outBitC (IC_RESULT (ic));
1419 /* release the aops */
1420 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1421 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1425 /*-----------------------------------------------------------------*/
1426 /* genCpl - generate code for complement */
1427 /*-----------------------------------------------------------------*/
1435 D(emitcode ("; genCpl",""));
1437 /* assign asmOps to operand & result */
1438 aopOp (IC_LEFT (ic), ic, FALSE);
1439 aopOp (IC_RESULT (ic), ic, TRUE);
1441 /* special case if in bit space */
1442 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1444 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1446 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1447 emitcode ("cpl", "c");
1448 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1452 tlbl=newiTempLabel(NULL);
1453 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1454 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1455 IS_AOP_PREG (IC_LEFT (ic)))
1457 emitcode ("cjne", "%s,#0x01,%05d$",
1458 aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE),
1463 char *l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE);
1465 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1467 emitcode ("", "%05d$:", tlbl->key + 100);
1468 outBitC (IC_RESULT(ic));
1472 size = AOP_SIZE (IC_RESULT (ic));
1475 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1477 emitcode ("cpl", "a");
1478 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1483 /* release the aops */
1484 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1485 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1488 /*-----------------------------------------------------------------*/
1489 /* genUminusFloat - unary minus for floating points */
1490 /*-----------------------------------------------------------------*/
1492 genUminusFloat (operand * op, operand * result)
1494 int size, offset = 0;
1497 D(emitcode ("; genUminusFloat",""));
1499 /* for this we just copy and then flip the bit */
1501 size = AOP_SIZE (op) - 1;
1505 aopPut (AOP (result),
1506 aopGet (AOP (op), offset, FALSE, FALSE),
1508 isOperandVolatile (result, FALSE));
1512 l = aopGet (AOP (op), offset, FALSE, FALSE);
1516 emitcode ("cpl", "acc.7");
1517 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1520 /*-----------------------------------------------------------------*/
1521 /* genUminus - unary minus code generation */
1522 /*-----------------------------------------------------------------*/
1524 genUminus (iCode * ic)
1527 sym_link *optype, *rtype;
1530 D(emitcode ("; genUminus",""));
1533 aopOp (IC_LEFT (ic), ic, FALSE);
1534 aopOp (IC_RESULT (ic), ic, TRUE);
1536 /* if both in bit space then special
1538 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1539 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1542 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1543 emitcode ("cpl", "c");
1544 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1548 optype = operandType (IC_LEFT (ic));
1549 rtype = operandType (IC_RESULT (ic));
1551 /* if float then do float stuff */
1552 if (IS_FLOAT (optype))
1554 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1558 /* otherwise subtract from zero */
1559 size = AOP_SIZE (IC_LEFT (ic));
1564 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1565 if (!strcmp (l, "a"))
1569 emitcode ("cpl", "a");
1570 emitcode ("addc", "a,#0");
1576 emitcode ("clr", "a");
1577 emitcode ("subb", "a,%s", l);
1579 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1582 /* if any remaining bytes in the result */
1583 /* we just need to propagate the sign */
1584 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1586 emitcode ("rlc", "a");
1587 emitcode ("subb", "a,acc");
1589 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1593 /* release the aops */
1594 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1595 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1598 /*-----------------------------------------------------------------*/
1599 /* saveRegisters - will look for a call and save the registers */
1600 /*-----------------------------------------------------------------*/
1602 saveRegisters (iCode * lic)
1609 for (ic = lic; ic; ic = ic->next)
1610 if (ic->op == CALL || ic->op == PCALL)
1615 fprintf (stderr, "found parameter push with no function call\n");
1619 /* if the registers have been saved already or don't need to be then
1623 if (IS_SYMOP(IC_LEFT(ic)) &&
1624 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1625 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1628 /* safe the registers in use at this time but skip the
1629 ones for the result */
1630 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1631 mcs51_rUmaskForOp (IC_RESULT(ic)));
1634 if (options.useXstack)
1636 if (bitVectBitValue (rsave, R0_IDX))
1637 emitcode ("mov", "b,r0");
1638 emitcode ("mov", "r0,%s", spname);
1639 for (i = 0; i < mcs51_nRegs; i++)
1641 if (bitVectBitValue (rsave, i))
1644 emitcode ("mov", "a,b");
1646 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1647 emitcode ("movx", "@r0,a");
1648 emitcode ("inc", "r0");
1651 emitcode ("mov", "%s,r0", spname);
1652 if (bitVectBitValue (rsave, R0_IDX))
1653 emitcode ("mov", "r0,b");
1656 for (i = 0; i < mcs51_nRegs; i++)
1658 if (bitVectBitValue (rsave, i))
1659 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1663 /*-----------------------------------------------------------------*/
1664 /* unsaveRegisters - pop the pushed registers */
1665 /*-----------------------------------------------------------------*/
1667 unsaveRegisters (iCode * ic)
1672 /* restore the registers in use at this time but skip the
1673 ones for the result */
1674 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1675 mcs51_rUmaskForOp (IC_RESULT(ic)));
1677 if (options.useXstack)
1679 emitcode ("mov", "r0,%s", spname);
1680 for (i = mcs51_nRegs; i >= 0; i--)
1682 if (bitVectBitValue (rsave, i))
1684 emitcode ("dec", "r0");
1685 emitcode ("movx", "a,@r0");
1687 emitcode ("mov", "b,a");
1689 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1693 emitcode ("mov", "%s,r0", spname);
1694 if (bitVectBitValue (rsave, R0_IDX))
1695 emitcode ("mov", "r0,b");
1698 for (i = mcs51_nRegs; i >= 0; i--)
1700 if (bitVectBitValue (rsave, i))
1701 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1707 /*-----------------------------------------------------------------*/
1709 /*-----------------------------------------------------------------*/
1711 pushSide (operand * oper, int size)
1716 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1717 if (AOP_TYPE (oper) != AOP_REG &&
1718 AOP_TYPE (oper) != AOP_DIR &&
1721 emitcode ("mov", "a,%s", l);
1722 emitcode ("push", "acc");
1725 emitcode ("push", "%s", l);
1729 /*-----------------------------------------------------------------*/
1730 /* assignResultValue - */
1731 /*-----------------------------------------------------------------*/
1733 assignResultValue (operand * oper)
1736 int size = AOP_SIZE (oper);
1739 aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
1745 /*-----------------------------------------------------------------*/
1746 /* genXpush - pushes onto the external stack */
1747 /*-----------------------------------------------------------------*/
1749 genXpush (iCode * ic)
1751 asmop *aop = newAsmop (0);
1753 int size, offset = 0;
1755 D(emitcode ("; genXpush",""));
1757 aopOp (IC_LEFT (ic), ic, FALSE);
1758 r = getFreePtr (ic, &aop, FALSE);
1761 emitcode ("mov", "%s,_spx", r->name);
1763 size = AOP_SIZE (IC_LEFT (ic));
1767 char *l = aopGet (AOP (IC_LEFT (ic)),
1768 offset++, FALSE, FALSE);
1770 emitcode ("movx", "@%s,a", r->name);
1771 emitcode ("inc", "%s", r->name);
1776 emitcode ("mov", "_spx,%s", r->name);
1778 freeAsmop (NULL, aop, ic, TRUE);
1779 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1782 /*-----------------------------------------------------------------*/
1783 /* genIpush - genrate code for pushing this gets a little complex */
1784 /*-----------------------------------------------------------------*/
1786 genIpush (iCode * ic)
1788 int size, offset = 0;
1791 D(emitcode ("; genIpush",""));
1793 /* if this is not a parm push : ie. it is spill push
1794 and spill push is always done on the local stack */
1798 /* and the item is spilt then do nothing */
1799 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1802 aopOp (IC_LEFT (ic), ic, FALSE);
1803 size = AOP_SIZE (IC_LEFT (ic));
1804 /* push it on the stack */
1807 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1813 emitcode ("push", "%s", l);
1818 /* this is a paramter push: in this case we call
1819 the routine to find the call and save those
1820 registers that need to be saved */
1823 /* if use external stack then call the external
1824 stack pushing routine */
1825 if (options.useXstack)
1831 /* then do the push */
1832 aopOp (IC_LEFT (ic), ic, FALSE);
1835 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1836 size = AOP_SIZE (IC_LEFT (ic));
1840 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1841 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1842 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1845 emitcode ("mov", "a,%s", l);
1846 emitcode ("push", "acc");
1849 emitcode ("push", "%s", l);
1852 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1855 /*-----------------------------------------------------------------*/
1856 /* genIpop - recover the registers: can happen only for spilling */
1857 /*-----------------------------------------------------------------*/
1859 genIpop (iCode * ic)
1863 D(emitcode ("; genIpop",""));
1865 /* if the temp was not pushed then */
1866 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1869 aopOp (IC_LEFT (ic), ic, FALSE);
1870 size = AOP_SIZE (IC_LEFT (ic));
1871 offset = (size - 1);
1873 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1876 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1879 /*-----------------------------------------------------------------*/
1880 /* unsaveRBank - restores the resgister bank from stack */
1881 /*-----------------------------------------------------------------*/
1883 unsaveRBank (int bank, iCode * ic, bool popPsw)
1889 if (options.useXstack)
1893 /* Assume r0 is available for use. */
1894 r = mcs51_regWithIdx (R0_IDX);;
1899 r = getFreePtr (ic, &aop, FALSE);
1901 emitcode ("mov", "%s,_spx", r->name);
1906 if (options.useXstack)
1908 emitcode ("movx", "a,@%s", r->name);
1909 emitcode ("mov", "psw,a");
1910 emitcode ("dec", "%s", r->name);
1914 emitcode ("pop", "psw");
1918 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1920 if (options.useXstack)
1922 emitcode ("movx", "a,@%s", r->name);
1923 emitcode ("mov", "(%s+%d),a",
1924 regs8051[i].base, 8 * bank + regs8051[i].offset);
1925 emitcode ("dec", "%s", r->name);
1929 emitcode ("pop", "(%s+%d)",
1930 regs8051[i].base, 8 * bank + regs8051[i].offset);
1933 if (options.useXstack)
1935 emitcode ("mov", "_spx,%s", r->name);
1940 freeAsmop (NULL, aop, ic, TRUE);
1944 /*-----------------------------------------------------------------*/
1945 /* saveRBank - saves an entire register bank on the stack */
1946 /*-----------------------------------------------------------------*/
1948 saveRBank (int bank, iCode * ic, bool pushPsw)
1954 if (options.useXstack)
1958 /* Assume r0 is available for use. */
1959 r = mcs51_regWithIdx (R0_IDX);;
1964 r = getFreePtr (ic, &aop, FALSE);
1966 emitcode ("mov", "%s,_spx", r->name);
1969 for (i = 0; i < mcs51_nRegs; i++)
1971 if (options.useXstack)
1973 emitcode ("inc", "%s", r->name);
1974 emitcode ("mov", "a,(%s+%d)",
1975 regs8051[i].base, 8 * bank + regs8051[i].offset);
1976 emitcode ("movx", "@%s,a", r->name);
1979 emitcode ("push", "(%s+%d)",
1980 regs8051[i].base, 8 * bank + regs8051[i].offset);
1985 if (options.useXstack)
1987 emitcode ("mov", "a,psw");
1988 emitcode ("movx", "@%s,a", r->name);
1989 emitcode ("inc", "%s", r->name);
1990 emitcode ("mov", "_spx,%s", r->name);
1995 emitcode ("push", "psw");
1998 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2003 freeAsmop (NULL, aop, ic, TRUE);
2012 /*-----------------------------------------------------------------*/
2013 /* genSend - gen code for SEND */
2014 /*-----------------------------------------------------------------*/
2015 static void genSend(set *sendSet)
2020 for (sic = setFirstItem (_G.sendSet); sic;
2021 sic = setNextItem (_G.sendSet)) {
2022 int size, offset = 0;
2023 aopOp (IC_LEFT (sic), sic, FALSE);
2024 size = AOP_SIZE (IC_LEFT (sic));
2026 if (sic->argreg == 1) {
2028 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2030 if (strcmp (l, fReturn[offset]))
2031 emitcode ("mov", "%s,%s", fReturn[offset], l);
2037 emitcode ("mov","b1_%d,%s",rb1_count++,
2038 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2041 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2045 /*-----------------------------------------------------------------*/
2046 /* genCall - generates a call statement */
2047 /*-----------------------------------------------------------------*/
2049 genCall (iCode * ic)
2052 // bool restoreBank = FALSE;
2053 bool swapBanks = FALSE;
2055 D(emitcode("; genCall",""));
2057 dtype = operandType (IC_LEFT (ic));
2058 /* if send set is not empty the assign */
2061 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2062 genSend(reverseSet(_G.sendSet));
2064 genSend(_G.sendSet);
2070 /* if we are calling a not _naked function that is not using
2071 the same register bank then we need to save the
2072 destination registers on the stack */
2073 dtype = operandType (IC_LEFT (ic));
2074 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2075 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2076 !IFFUNC_ISISR (dtype))
2081 /* if caller saves & we have not saved then */
2087 emitcode ("mov", "psw,#0x%02x",
2088 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2092 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2093 OP_SYMBOL (IC_LEFT (ic))->rname :
2094 OP_SYMBOL (IC_LEFT (ic))->name));
2098 emitcode ("mov", "psw,#0x%02x",
2099 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2102 /* if we need assign a result value */
2103 if ((IS_ITEMP (IC_RESULT (ic)) &&
2104 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2105 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2106 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2107 IS_TRUE_SYMOP (IC_RESULT (ic)))
2111 aopOp (IC_RESULT (ic), ic, FALSE);
2114 assignResultValue (IC_RESULT (ic));
2116 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2119 /* adjust the stack for parameters if
2124 if (ic->parmBytes > 3)
2126 emitcode ("mov", "a,%s", spname);
2127 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2128 emitcode ("mov", "%s,a", spname);
2131 for (i = 0; i < ic->parmBytes; i++)
2132 emitcode ("dec", "%s", spname);
2135 /* if we hade saved some registers then unsave them */
2136 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2137 unsaveRegisters (ic);
2139 // /* if register bank was saved then pop them */
2141 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2144 /*-----------------------------------------------------------------*/
2145 /* -10l - generates a call by pointer statement */
2146 /*-----------------------------------------------------------------*/
2148 genPcall (iCode * ic)
2151 symbol *rlbl = newiTempLabel (NULL);
2152 // bool restoreBank=FALSE;
2153 bool swapBanks = FALSE;
2155 D(emitcode("; genPCall",""));
2157 /* if caller saves & we have not saved then */
2161 /* if we are calling a not _naked function that is not using
2162 the same register bank then we need to save the
2163 destination registers on the stack */
2164 dtype = operandType (IC_LEFT (ic))->next;
2165 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2166 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2167 !IFFUNC_ISISR (dtype))
2169 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2170 // restoreBank=TRUE;
2172 // need caution message to user here
2175 /* push the return address on to the stack */
2176 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2177 emitcode ("push", "acc");
2178 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2179 emitcode ("push", "acc");
2181 /* now push the calling address */
2182 aopOp (IC_LEFT (ic), ic, FALSE);
2184 pushSide (IC_LEFT (ic), FPTRSIZE);
2186 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2188 /* if send set is not empty the assign */
2191 genSend(reverseSet(_G.sendSet));
2197 emitcode ("mov", "psw,#0x%02x",
2198 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2202 emitcode ("ret", "");
2203 emitcode ("", "%05d$:", (rlbl->key + 100));
2208 emitcode ("mov", "psw,#0x%02x",
2209 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2212 /* if we need assign a result value */
2213 if ((IS_ITEMP (IC_RESULT (ic)) &&
2214 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2215 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2216 IS_TRUE_SYMOP (IC_RESULT (ic)))
2220 aopOp (IC_RESULT (ic), ic, FALSE);
2223 assignResultValue (IC_RESULT (ic));
2225 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2228 /* adjust the stack for parameters if
2233 if (ic->parmBytes > 3)
2235 emitcode ("mov", "a,%s", spname);
2236 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2237 emitcode ("mov", "%s,a", spname);
2240 for (i = 0; i < ic->parmBytes; i++)
2241 emitcode ("dec", "%s", spname);
2245 // /* if register bank was saved then unsave them */
2247 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2249 /* if we hade saved some registers then
2251 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2252 unsaveRegisters (ic);
2255 /*-----------------------------------------------------------------*/
2256 /* resultRemat - result is rematerializable */
2257 /*-----------------------------------------------------------------*/
2259 resultRemat (iCode * ic)
2261 if (SKIP_IC (ic) || ic->op == IFX)
2264 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2266 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2267 if (sym->remat && !POINTER_SET (ic))
2274 #if defined(__BORLANDC__) || defined(_MSC_VER)
2275 #define STRCASECMP stricmp
2277 #define STRCASECMP strcasecmp
2280 /*-----------------------------------------------------------------*/
2281 /* inExcludeList - return 1 if the string is in exclude Reg list */
2282 /*-----------------------------------------------------------------*/
2284 regsCmp(void *p1, void *p2)
2286 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2290 inExcludeList (char *s)
2292 const char *p = setFirstItem(options.excludeRegsSet);
2294 if (p == NULL || STRCASECMP(p, "none") == 0)
2298 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2301 /*-----------------------------------------------------------------*/
2302 /* genFunction - generated code for function entry */
2303 /*-----------------------------------------------------------------*/
2305 genFunction (iCode * ic)
2309 bool switchedPSW = FALSE;
2310 int calleesaves_saved_register = -1;
2313 /* create the function header */
2314 emitcode (";", "-----------------------------------------");
2315 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2316 emitcode (";", "-----------------------------------------");
2318 emitcode ("", "%s:", sym->rname);
2319 ftype = operandType (IC_LEFT (ic));
2321 if (IFFUNC_ISNAKED(ftype))
2323 emitcode(";", "naked function: no prologue.");
2327 /* here we need to generate the equates for the
2328 register bank if required */
2329 if (FUNC_REGBANK (ftype) != rbank)
2333 rbank = FUNC_REGBANK (ftype);
2334 for (i = 0; i < mcs51_nRegs; i++)
2336 if (strcmp (regs8051[i].base, "0") == 0)
2337 emitcode ("", "%s = 0x%02x",
2339 8 * rbank + regs8051[i].offset);
2341 emitcode ("", "%s = %s + 0x%02x",
2344 8 * rbank + regs8051[i].offset);
2348 /* if this is an interrupt service routine then
2349 save acc, b, dpl, dph */
2350 if (IFFUNC_ISISR (sym->type))
2353 if (!inExcludeList ("acc"))
2354 emitcode ("push", "acc");
2355 if (!inExcludeList ("b"))
2356 emitcode ("push", "b");
2357 if (!inExcludeList ("dpl"))
2358 emitcode ("push", "dpl");
2359 if (!inExcludeList ("dph"))
2360 emitcode ("push", "dph");
2361 /* if this isr has no bank i.e. is going to
2362 run with bank 0 , then we need to save more
2364 if (!FUNC_REGBANK (sym->type))
2367 /* if this function does not call any other
2368 function then we can be economical and
2369 save only those registers that are used */
2370 if (!IFFUNC_HASFCALL(sym->type))
2374 /* if any registers used */
2377 /* save the registers used */
2378 for (i = 0; i < sym->regsUsed->size; i++)
2380 if (bitVectBitValue (sym->regsUsed, i) ||
2381 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2382 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2390 /* this function has a function call cannot
2391 determines register usage so we will have to push the
2393 saveRBank (0, ic, FALSE);
2394 if (options.parms_in_bank1) {
2396 for (i=0; i < 8 ; i++ ) {
2397 emitcode ("push","%s",rb1regs[i]);
2404 /* This ISR uses a non-zero bank.
2406 * We assume that the bank is available for our
2409 * However, if this ISR calls a function which uses some
2410 * other bank, we must save that bank entirely.
2412 unsigned long banksToSave = 0;
2414 if (IFFUNC_HASFCALL(sym->type))
2417 #define MAX_REGISTER_BANKS 4
2422 for (i = ic; i; i = i->next)
2424 if (i->op == ENDFUNCTION)
2426 /* we got to the end OK. */
2434 dtype = operandType (IC_LEFT(i));
2436 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2438 /* Mark this bank for saving. */
2439 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2441 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2445 banksToSave |= (1 << FUNC_REGBANK(dtype));
2448 /* And note that we don't need to do it in
2456 /* This is a mess; we have no idea what
2457 * register bank the called function might
2460 * The only thing I can think of to do is
2461 * throw a warning and hope.
2463 werror(W_FUNCPTR_IN_USING_ISR);
2467 if (banksToSave && options.useXstack)
2469 /* Since we aren't passing it an ic,
2470 * saveRBank will assume r0 is available to abuse.
2472 * So switch to our (trashable) bank now, so
2473 * the caller's R0 isn't trashed.
2475 emitcode ("push", "psw");
2476 emitcode ("mov", "psw,#0x%02x",
2477 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2481 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2483 if (banksToSave & (1 << ix))
2485 saveRBank(ix, NULL, FALSE);
2489 // TODO: this needs a closer look
2490 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2495 /* if callee-save to be used for this function
2496 then save the registers being used in this function */
2497 if (IFFUNC_CALLEESAVES(sym->type))
2501 /* if any registers used */
2504 /* save the registers used */
2505 for (i = 0; i < sym->regsUsed->size; i++)
2507 if (bitVectBitValue (sym->regsUsed, i) ||
2508 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2510 /* remember one saved register for later usage */
2511 if (calleesaves_saved_register < 0)
2512 calleesaves_saved_register = i;
2513 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2521 /* set the register bank to the desired value */
2522 if (( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2525 emitcode ("push", "psw");
2526 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2529 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2532 if (options.useXstack)
2534 emitcode ("mov", "r0,%s", spname);
2535 emitcode ("mov", "a,_bp");
2536 emitcode ("movx", "@r0,a");
2537 emitcode ("inc", "%s", spname);
2541 /* set up the stack */
2542 emitcode ("push", "_bp"); /* save the callers stack */
2544 emitcode ("mov", "_bp,%s", spname);
2547 /* adjust the stack for the function */
2553 werror (W_STACK_OVERFLOW, sym->name);
2555 if (i > 3 && sym->recvSize < 4)
2558 emitcode ("mov", "a,sp");
2559 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2560 emitcode ("mov", "sp,a");
2565 if (IFFUNC_CALLEESAVES(sym->type))
2567 /* if it's a callee-saves function we need a saved register */
2568 if (calleesaves_saved_register >= 0)
2570 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2571 emitcode ("mov", "a,sp");
2572 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2573 emitcode ("mov", "sp,a");
2574 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2577 /* do it the hard way */
2579 emitcode ("inc", "sp");
2583 /* not callee-saves, we can clobber r0 */
2584 emitcode ("mov", "r0,a");
2585 emitcode ("mov", "a,sp");
2586 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2587 emitcode ("mov", "sp,a");
2588 emitcode ("mov", "a,r0");
2593 emitcode ("inc", "sp");
2599 emitcode ("mov", "a,_spx");
2600 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2601 emitcode ("mov", "_spx,a");
2604 /* if critical function then turn interrupts off */
2605 if (IFFUNC_ISCRITICAL (ftype))
2607 symbol *tlbl = newiTempLabel (NULL);
2608 emitcode ("setb", "c");
2609 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
2610 emitcode ("clr", "c");
2611 emitcode ("", "%05d$:", (tlbl->key + 100));
2612 emitcode ("push", "psw"); /* save old ea via c in psw */
2616 /*-----------------------------------------------------------------*/
2617 /* genEndFunction - generates epilogue for functions */
2618 /*-----------------------------------------------------------------*/
2620 genEndFunction (iCode * ic)
2622 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2624 if (IFFUNC_ISNAKED(sym->type))
2626 emitcode(";", "naked function: no epilogue.");
2630 if (IFFUNC_ISCRITICAL (sym->type))
2632 emitcode ("pop", "psw"); /* restore ea via c in psw */
2633 emitcode ("mov", "ea,c");
2636 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2638 emitcode ("mov", "%s,_bp", spname);
2641 /* if use external stack but some variables were
2642 added to the local stack then decrement the
2644 if (options.useXstack && sym->stack)
2646 emitcode ("mov", "a,sp");
2647 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2648 emitcode ("mov", "sp,a");
2652 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2654 if (options.useXstack)
2656 emitcode ("mov", "r0,%s", spname);
2657 emitcode ("movx", "a,@r0");
2658 emitcode ("mov", "_bp,a");
2659 emitcode ("dec", "%s", spname);
2663 emitcode ("pop", "_bp");
2667 /* restore the register bank */
2668 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
2670 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
2671 || !options.useXstack)
2673 /* Special case of ISR using non-zero bank with useXstack
2676 emitcode ("pop", "psw");
2680 if (IFFUNC_ISISR (sym->type))
2683 /* now we need to restore the registers */
2684 /* if this isr has no bank i.e. is going to
2685 run with bank 0 , then we need to save more
2687 if (!FUNC_REGBANK (sym->type))
2689 /* if this function does not call any other
2690 function then we can be economical and
2691 save only those registers that are used */
2692 if (!IFFUNC_HASFCALL(sym->type))
2696 /* if any registers used */
2699 /* save the registers used */
2700 for (i = sym->regsUsed->size; i >= 0; i--)
2702 if (bitVectBitValue (sym->regsUsed, i) ||
2703 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2704 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2711 if (options.parms_in_bank1) {
2713 for (i = 7 ; i >= 0 ; i-- ) {
2714 emitcode ("pop","%s",rb1regs[i]);
2717 /* this function has a function call cannot
2718 determines register usage so we will have to pop the
2720 unsaveRBank (0, ic, FALSE);
2725 /* This ISR uses a non-zero bank.
2727 * Restore any register banks saved by genFunction
2730 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2733 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2735 if (savedBanks & (1 << ix))
2737 unsaveRBank(ix, NULL, FALSE);
2741 if (options.useXstack)
2743 /* Restore bank AFTER calling unsaveRBank,
2744 * since it can trash r0.
2746 emitcode ("pop", "psw");
2750 if (!inExcludeList ("dph"))
2751 emitcode ("pop", "dph");
2752 if (!inExcludeList ("dpl"))
2753 emitcode ("pop", "dpl");
2754 if (!inExcludeList ("b"))
2755 emitcode ("pop", "b");
2756 if (!inExcludeList ("acc"))
2757 emitcode ("pop", "acc");
2759 /* if debug then send end of function */
2760 if (options.debug && currFunc)
2763 emitcode ("", "C$%s$%d$%d$%d ==.",
2764 FileBaseName (ic->filename), currFunc->lastLine,
2765 ic->level, ic->block);
2766 if (IS_STATIC (currFunc->etype))
2767 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2769 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2773 emitcode ("reti", "");
2777 if (IFFUNC_CALLEESAVES(sym->type))
2781 /* if any registers used */
2784 /* save the registers used */
2785 for (i = sym->regsUsed->size; i >= 0; i--)
2787 if (bitVectBitValue (sym->regsUsed, i) ||
2788 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2789 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2795 /* if debug then send end of function */
2796 if (options.debug && currFunc)
2799 emitcode ("", "C$%s$%d$%d$%d ==.",
2800 FileBaseName (ic->filename), currFunc->lastLine,
2801 ic->level, ic->block);
2802 if (IS_STATIC (currFunc->etype))
2803 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2805 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2809 emitcode ("ret", "");
2814 /*-----------------------------------------------------------------*/
2815 /* genRet - generate code for return statement */
2816 /*-----------------------------------------------------------------*/
2820 int size, offset = 0, pushed = 0;
2822 D(emitcode ("; genRet",""));
2824 /* if we have no return value then
2825 just generate the "ret" */
2829 /* we have something to return then
2830 move the return value into place */
2831 aopOp (IC_LEFT (ic), ic, FALSE);
2832 size = AOP_SIZE (IC_LEFT (ic));
2837 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2840 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2842 emitcode ("push", "%s", l);
2847 l = aopGet (AOP (IC_LEFT (ic)), offset,
2849 if (strcmp (fReturn[offset], l))
2850 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2859 if (strcmp (fReturn[pushed], "a"))
2860 emitcode ("pop", fReturn[pushed]);
2862 emitcode ("pop", "acc");
2865 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2868 /* generate a jump to the return label
2869 if the next is not the return statement */
2870 if (!(ic->next && ic->next->op == LABEL &&
2871 IC_LABEL (ic->next) == returnLabel))
2873 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2877 /*-----------------------------------------------------------------*/
2878 /* genLabel - generates a label */
2879 /*-----------------------------------------------------------------*/
2881 genLabel (iCode * ic)
2883 /* special case never generate */
2884 if (IC_LABEL (ic) == entryLabel)
2887 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2890 /*-----------------------------------------------------------------*/
2891 /* genGoto - generates a ljmp */
2892 /*-----------------------------------------------------------------*/
2894 genGoto (iCode * ic)
2896 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2899 /*-----------------------------------------------------------------*/
2900 /* findLabelBackwards: walks back through the iCode chain looking */
2901 /* for the given label. Returns number of iCode instructions */
2902 /* between that label and given ic. */
2903 /* Returns zero if label not found. */
2904 /*-----------------------------------------------------------------*/
2906 findLabelBackwards (iCode * ic, int key)
2915 /* If we have any pushes or pops, we cannot predict the distance.
2916 I don't like this at all, this should be dealt with in the
2918 if (ic->op == IPUSH || ic->op == IPOP) {
2922 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2931 /*-----------------------------------------------------------------*/
2932 /* genPlusIncr :- does addition with increment if possible */
2933 /*-----------------------------------------------------------------*/
2935 genPlusIncr (iCode * ic)
2937 unsigned int icount;
2938 unsigned int size = getDataSize (IC_RESULT (ic));
2940 /* will try to generate an increment */
2941 /* if the right side is not a literal
2943 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2946 /* if the literal value of the right hand side
2947 is greater than 4 then it is not worth it */
2948 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2951 D(emitcode ("; genPlusIncr",""));
2953 /* if increment >=16 bits in register or direct space */
2954 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
2955 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2963 /* If the next instruction is a goto and the goto target
2964 * is < 10 instructions previous to this, we can generate
2965 * jumps straight to that target.
2967 if (ic->next && ic->next->op == GOTO
2968 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2969 && labelRange <= 10)
2971 emitcode (";", "tail increment optimized");
2972 tlbl = IC_LABEL (ic->next);
2977 tlbl = newiTempLabel (NULL);
2980 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2981 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2982 IS_AOP_PREG (IC_RESULT (ic)))
2983 emitcode ("cjne", "%s,#0x00,%05d$",
2984 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2988 emitcode ("clr", "a");
2989 emitcode ("cjne", "a,%s,%05d$",
2990 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
2994 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2997 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2998 IS_AOP_PREG (IC_RESULT (ic)))
2999 emitcode ("cjne", "%s,#0x00,%05d$",
3000 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3003 emitcode ("cjne", "a,%s,%05d$",
3004 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3007 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3011 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3012 IS_AOP_PREG (IC_RESULT (ic)))
3013 emitcode ("cjne", "%s,#0x00,%05d$",
3014 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3018 emitcode ("cjne", "a,%s,%05d$",
3019 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3022 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3027 emitcode ("", "%05d$:", tlbl->key + 100);
3032 /* if the sizes are greater than 1 then we cannot */
3033 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3034 AOP_SIZE (IC_LEFT (ic)) > 1)
3037 /* we can if the aops of the left & result match or
3038 if they are in registers and the registers are the
3040 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3045 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3046 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3047 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3053 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3062 /*-----------------------------------------------------------------*/
3063 /* outBitAcc - output a bit in acc */
3064 /*-----------------------------------------------------------------*/
3066 outBitAcc (operand * result)
3068 symbol *tlbl = newiTempLabel (NULL);
3069 /* if the result is a bit */
3070 if (AOP_TYPE (result) == AOP_CRY)
3072 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3076 emitcode ("jz", "%05d$", tlbl->key + 100);
3077 emitcode ("mov", "a,%s", one);
3078 emitcode ("", "%05d$:", tlbl->key + 100);
3083 /*-----------------------------------------------------------------*/
3084 /* genPlusBits - generates code for addition of two bits */
3085 /*-----------------------------------------------------------------*/
3087 genPlusBits (iCode * ic)
3089 D(emitcode ("; genPlusBits",""));
3091 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3093 symbol *lbl = newiTempLabel (NULL);
3094 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3095 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3096 emitcode ("cpl", "c");
3097 emitcode ("", "%05d$:", (lbl->key + 100));
3098 outBitC (IC_RESULT (ic));
3102 emitcode ("clr", "a");
3103 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3104 emitcode ("rlc", "a");
3105 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3106 emitcode ("addc", "a,#0x00");
3107 outAcc (IC_RESULT (ic));
3112 /* This is the original version of this code.
3114 * This is being kept around for reference,
3115 * because I am not entirely sure I got it right...
3118 adjustArithmeticResult (iCode * ic)
3120 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3121 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3122 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3123 aopPut (AOP (IC_RESULT (ic)),
3124 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3126 isOperandVolatile (IC_RESULT (ic), FALSE));
3128 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3129 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3130 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3131 aopPut (AOP (IC_RESULT (ic)),
3132 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3134 isOperandVolatile (IC_RESULT (ic), FALSE));
3136 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3137 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3138 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3139 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3140 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3143 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3144 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3148 /* This is the pure and virtuous version of this code.
3149 * I'm pretty certain it's right, but not enough to toss the old
3153 adjustArithmeticResult (iCode * ic)
3155 if (opIsGptr (IC_RESULT (ic)) &&
3156 opIsGptr (IC_LEFT (ic)) &&
3157 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3159 aopPut (AOP (IC_RESULT (ic)),
3160 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3162 isOperandVolatile (IC_RESULT (ic), FALSE));
3165 if (opIsGptr (IC_RESULT (ic)) &&
3166 opIsGptr (IC_RIGHT (ic)) &&
3167 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3169 aopPut (AOP (IC_RESULT (ic)),
3170 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3172 isOperandVolatile (IC_RESULT (ic), FALSE));
3175 if (opIsGptr (IC_RESULT (ic)) &&
3176 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3177 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3178 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3179 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3182 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3183 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3188 /*-----------------------------------------------------------------*/
3189 /* genPlus - generates code for addition */
3190 /*-----------------------------------------------------------------*/
3192 genPlus (iCode * ic)
3194 int size, offset = 0;
3196 asmop *leftOp, *rightOp;
3198 /* special cases :- */
3200 D(emitcode ("; genPlus",""));
3202 aopOp (IC_LEFT (ic), ic, FALSE);
3203 aopOp (IC_RIGHT (ic), ic, FALSE);
3204 aopOp (IC_RESULT (ic), ic, TRUE);
3206 /* if literal, literal on the right or
3207 if left requires ACC or right is already
3209 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3210 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3211 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3213 operand *t = IC_RIGHT (ic);
3214 IC_RIGHT (ic) = IC_LEFT (ic);
3218 /* if both left & right are in bit
3220 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3221 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3227 /* if left in bit space & right literal */
3228 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3229 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3231 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3232 /* if result in bit space */
3233 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3235 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3236 emitcode ("cpl", "c");
3237 outBitC (IC_RESULT (ic));
3241 size = getDataSize (IC_RESULT (ic));
3244 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3245 emitcode ("addc", "a,#00");
3246 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3252 /* if I can do an increment instead
3253 of add then GOOD for ME */
3254 if (genPlusIncr (ic) == TRUE)
3257 size = getDataSize (IC_RESULT (ic));
3259 leftOp = AOP(IC_LEFT(ic));
3260 rightOp = AOP(IC_RIGHT(ic));
3265 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3267 emitcode("mov", "b,a");
3268 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3269 emitcode("xch", "a,b");
3270 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3271 emitcode (add, "a,b");
3273 else if (aopGetUsesAcc (leftOp, offset))
3275 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3276 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3280 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3281 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3283 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3284 add = "addc"; /* further adds must propagate carry */
3287 adjustArithmeticResult (ic);
3290 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3291 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3292 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3295 /*-----------------------------------------------------------------*/
3296 /* genMinusDec :- does subtraction with deccrement if possible */
3297 /*-----------------------------------------------------------------*/
3299 genMinusDec (iCode * ic)
3301 unsigned int icount;
3302 unsigned int size = getDataSize (IC_RESULT (ic));
3304 /* will try to generate an increment */
3305 /* if the right side is not a literal
3307 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3310 /* if the literal value of the right hand side
3311 is greater than 4 then it is not worth it */
3312 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3315 D(emitcode ("; genMinusDec",""));
3317 /* if decrement >=16 bits in register or direct space */
3318 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3319 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3327 /* If the next instruction is a goto and the goto target
3328 * is <= 10 instructions previous to this, we can generate
3329 * jumps straight to that target.
3331 if (ic->next && ic->next->op == GOTO
3332 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3333 && labelRange <= 10)
3335 emitcode (";", "tail decrement optimized");
3336 tlbl = IC_LABEL (ic->next);
3341 tlbl = newiTempLabel (NULL);
3345 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3346 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3347 IS_AOP_PREG (IC_RESULT (ic)))
3348 emitcode ("cjne", "%s,#0xff,%05d$"
3349 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3353 emitcode ("mov", "a,#0xff");
3354 emitcode ("cjne", "a,%s,%05d$"
3355 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3358 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3361 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3362 IS_AOP_PREG (IC_RESULT (ic)))
3363 emitcode ("cjne", "%s,#0xff,%05d$"
3364 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3368 emitcode ("cjne", "a,%s,%05d$"
3369 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3372 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3376 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3377 IS_AOP_PREG (IC_RESULT (ic)))
3378 emitcode ("cjne", "%s,#0xff,%05d$"
3379 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3383 emitcode ("cjne", "a,%s,%05d$"
3384 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3387 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3391 emitcode ("", "%05d$:", tlbl->key + 100);
3396 /* if the sizes are greater than 1 then we cannot */
3397 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3398 AOP_SIZE (IC_LEFT (ic)) > 1)
3401 /* we can if the aops of the left & result match or
3402 if they are in registers and the registers are the
3404 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3408 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3416 /*-----------------------------------------------------------------*/
3417 /* addSign - complete with sign */
3418 /*-----------------------------------------------------------------*/
3420 addSign (operand * result, int offset, int sign)
3422 int size = (getDataSize (result) - offset);
3427 emitcode ("rlc", "a");
3428 emitcode ("subb", "a,acc");
3430 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3434 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3438 /*-----------------------------------------------------------------*/
3439 /* genMinusBits - generates code for subtraction of two bits */
3440 /*-----------------------------------------------------------------*/
3442 genMinusBits (iCode * ic)
3444 symbol *lbl = newiTempLabel (NULL);
3446 D(emitcode ("; genMinusBits",""));
3448 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3450 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3451 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3452 emitcode ("cpl", "c");
3453 emitcode ("", "%05d$:", (lbl->key + 100));
3454 outBitC (IC_RESULT (ic));
3458 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3459 emitcode ("subb", "a,acc");
3460 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3461 emitcode ("inc", "a");
3462 emitcode ("", "%05d$:", (lbl->key + 100));
3463 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3464 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3468 /*-----------------------------------------------------------------*/
3469 /* genMinus - generates code for subtraction */
3470 /*-----------------------------------------------------------------*/
3472 genMinus (iCode * ic)
3474 int size, offset = 0;
3476 D(emitcode ("; genMinus",""));
3478 aopOp (IC_LEFT (ic), ic, FALSE);
3479 aopOp (IC_RIGHT (ic), ic, FALSE);
3480 aopOp (IC_RESULT (ic), ic, TRUE);
3482 /* special cases :- */
3483 /* if both left & right are in bit space */
3484 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3485 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3491 /* if I can do an decrement instead
3492 of subtract then GOOD for ME */
3493 if (genMinusDec (ic) == TRUE)
3496 size = getDataSize (IC_RESULT (ic));
3498 /* if literal, add a,#-lit, else normal subb */
3499 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3501 unsigned long lit = 0L;
3503 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3508 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3509 /* first add without previous c */
3511 if (!size && lit== (unsigned long) -1) {
3512 emitcode ("dec", "a");
3514 emitcode ("add", "a,#0x%02x",
3515 (unsigned int) (lit & 0x0FFL));
3518 emitcode ("addc", "a,#0x%02x",
3519 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3521 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3526 asmop *leftOp, *rightOp;
3528 leftOp = AOP(IC_LEFT(ic));
3529 rightOp = AOP(IC_RIGHT(ic));
3533 if (aopGetUsesAcc(rightOp, offset)) {
3534 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
3535 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
3537 emitcode( "setb", "c");
3539 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
3540 emitcode("cpl", "a");
3542 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
3545 emitcode ("subb", "a,%s",
3546 aopGet(rightOp, offset, FALSE, TRUE));
3549 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3554 adjustArithmeticResult (ic);
3557 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3558 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3559 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3563 /*-----------------------------------------------------------------*/
3564 /* genMultbits :- multiplication of bits */
3565 /*-----------------------------------------------------------------*/
3567 genMultbits (operand * left,
3571 D(emitcode ("; genMultbits",""));
3573 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3574 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3579 /*-----------------------------------------------------------------*/
3580 /* genMultOneByte : 8*8=8/16 bit multiplication */
3581 /*-----------------------------------------------------------------*/
3583 genMultOneByte (operand * left,
3587 sym_link *opetype = operandType (result);
3589 int size=AOP_SIZE(result);
3591 D(emitcode ("; genMultOneByte",""));
3593 if (size<1 || size>2) {
3594 // this should never happen
3595 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3596 AOP_SIZE(result), __FILE__, lineno);
3600 /* (if two literals: the value is computed before) */
3601 /* if one literal, literal on the right */
3602 if (AOP_TYPE (left) == AOP_LIT)
3607 //emitcode (";", "swapped left and right");
3610 if (SPEC_USIGN(opetype)
3611 // ignore the sign of left and right, what else can we do?
3612 || (SPEC_USIGN(operandType(left)) &&
3613 SPEC_USIGN(operandType(right)))) {
3614 // just an unsigned 8*8=8/16 multiply
3615 //emitcode (";","unsigned");
3616 // TODO: check for accumulator clash between left & right aops?
3617 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3618 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3619 emitcode ("mul", "ab");
3620 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3622 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3627 // we have to do a signed multiply
3629 //emitcode (";", "signed");
3630 emitcode ("clr", "F0"); // reset sign flag
3631 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3633 lbl=newiTempLabel(NULL);
3634 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3635 // left side is negative, 8-bit two's complement, this fails for -128
3636 emitcode ("setb", "F0"); // set sign flag
3637 emitcode ("cpl", "a");
3638 emitcode ("inc", "a");
3640 emitcode ("", "%05d$:", lbl->key+100);
3643 if (AOP_TYPE(right)==AOP_LIT) {
3644 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3645 /* AND literal negative */
3647 emitcode ("cpl", "F0"); // complement sign flag
3648 emitcode ("mov", "b,#0x%02x", -val);
3650 emitcode ("mov", "b,#0x%02x", val);
3653 lbl=newiTempLabel(NULL);
3654 emitcode ("mov", "b,a");
3655 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3656 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3657 // right side is negative, 8-bit two's complement
3658 emitcode ("cpl", "F0"); // complement sign flag
3659 emitcode ("cpl", "a");
3660 emitcode ("inc", "a");
3661 emitcode ("", "%05d$:", lbl->key+100);
3663 emitcode ("mul", "ab");
3665 lbl=newiTempLabel(NULL);
3666 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3667 // only ONE op was negative, we have to do a 8/16-bit two's complement
3668 emitcode ("cpl", "a"); // lsb
3670 emitcode ("inc", "a");
3672 emitcode ("add", "a,#1");
3673 emitcode ("xch", "a,b");
3674 emitcode ("cpl", "a"); // msb
3675 emitcode ("addc", "a,#0");
3676 emitcode ("xch", "a,b");
3679 emitcode ("", "%05d$:", lbl->key+100);
3680 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3682 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
3686 /*-----------------------------------------------------------------*/
3687 /* genMult - generates code for multiplication */
3688 /*-----------------------------------------------------------------*/
3690 genMult (iCode * ic)
3692 operand *left = IC_LEFT (ic);
3693 operand *right = IC_RIGHT (ic);
3694 operand *result = IC_RESULT (ic);
3696 D(emitcode ("; genMult",""));
3698 /* assign the amsops */
3699 aopOp (left, ic, FALSE);
3700 aopOp (right, ic, FALSE);
3701 aopOp (result, ic, TRUE);
3703 /* special cases first */
3705 if (AOP_TYPE (left) == AOP_CRY &&
3706 AOP_TYPE (right) == AOP_CRY)
3708 genMultbits (left, right, result);
3712 /* if both are of size == 1 */
3713 #if 0 // one of them can be a sloc shared with the result
3714 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3716 if (getSize(operandType(left)) == 1 &&
3717 getSize(operandType(right)) == 1)
3720 genMultOneByte (left, right, result);
3724 /* should have been converted to function call */
3725 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3726 getSize(OP_SYMBOL(right)->type));
3730 freeAsmop (result, NULL, ic, TRUE);
3731 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3732 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3735 /*-----------------------------------------------------------------*/
3736 /* genDivbits :- division of bits */
3737 /*-----------------------------------------------------------------*/
3739 genDivbits (operand * left,
3746 D(emitcode ("; genDivbits",""));
3748 /* the result must be bit */
3749 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3750 l = aopGet (AOP (left), 0, FALSE, FALSE);
3754 emitcode ("div", "ab");
3755 emitcode ("rrc", "a");
3756 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3759 /*-----------------------------------------------------------------*/
3760 /* genDivOneByte : 8 bit division */
3761 /*-----------------------------------------------------------------*/
3763 genDivOneByte (operand * left,
3767 sym_link *opetype = operandType (result);
3772 D(emitcode ("; genDivOneByte",""));
3774 size = AOP_SIZE (result) - 1;
3776 /* signed or unsigned */
3777 if (SPEC_USIGN (opetype))
3779 /* unsigned is easy */
3780 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3781 l = aopGet (AOP (left), 0, FALSE, FALSE);
3783 emitcode ("div", "ab");
3784 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3786 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
3790 /* signed is a little bit more difficult */
3792 /* save the signs of the operands */
3793 l = aopGet (AOP (left), 0, FALSE, FALSE);
3795 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3796 emitcode ("push", "acc"); /* save it on the stack */
3798 /* now sign adjust for both left & right */
3799 l = aopGet (AOP (right), 0, FALSE, FALSE);
3801 lbl = newiTempLabel (NULL);
3802 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3803 emitcode ("cpl", "a");
3804 emitcode ("inc", "a");
3805 emitcode ("", "%05d$:", (lbl->key + 100));
3806 emitcode ("mov", "b,a");
3808 /* sign adjust left side */
3809 l = aopGet (AOP (left), 0, FALSE, FALSE);
3812 lbl = newiTempLabel (NULL);
3813 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3814 emitcode ("cpl", "a");
3815 emitcode ("inc", "a");
3816 emitcode ("", "%05d$:", (lbl->key + 100));
3818 /* now the division */
3819 emitcode ("div", "ab");
3820 /* we are interested in the lower order
3822 emitcode ("mov", "b,a");
3823 lbl = newiTempLabel (NULL);
3824 emitcode ("pop", "acc");
3825 /* if there was an over flow we don't
3826 adjust the sign of the result */
3827 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3828 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3830 emitcode ("clr", "a");
3831 emitcode ("subb", "a,b");
3832 emitcode ("mov", "b,a");
3833 emitcode ("", "%05d$:", (lbl->key + 100));
3835 /* now we are done */
3836 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3839 emitcode ("mov", "c,b.7");
3840 emitcode ("subb", "a,acc");
3843 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
3847 /*-----------------------------------------------------------------*/
3848 /* genDiv - generates code for division */
3849 /*-----------------------------------------------------------------*/
3853 operand *left = IC_LEFT (ic);
3854 operand *right = IC_RIGHT (ic);
3855 operand *result = IC_RESULT (ic);
3857 D(emitcode ("; genDiv",""));
3859 /* assign the amsops */
3860 aopOp (left, ic, FALSE);
3861 aopOp (right, ic, FALSE);
3862 aopOp (result, ic, TRUE);
3864 /* special cases first */
3866 if (AOP_TYPE (left) == AOP_CRY &&
3867 AOP_TYPE (right) == AOP_CRY)
3869 genDivbits (left, right, result);
3873 /* if both are of size == 1 */
3874 if (AOP_SIZE (left) == 1 &&
3875 AOP_SIZE (right) == 1)
3877 genDivOneByte (left, right, result);
3881 /* should have been converted to function call */
3884 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3885 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3886 freeAsmop (result, NULL, ic, TRUE);
3889 /*-----------------------------------------------------------------*/
3890 /* genModbits :- modulus of bits */
3891 /*-----------------------------------------------------------------*/
3893 genModbits (operand * left,
3900 D(emitcode ("; genModbits",""));
3902 /* the result must be bit */
3903 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3904 l = aopGet (AOP (left), 0, FALSE, FALSE);
3908 emitcode ("div", "ab");
3909 emitcode ("mov", "a,b");
3910 emitcode ("rrc", "a");
3911 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
3914 /*-----------------------------------------------------------------*/
3915 /* genModOneByte : 8 bit modulus */
3916 /*-----------------------------------------------------------------*/
3918 genModOneByte (operand * left,
3922 sym_link *opetype = operandType (result);
3926 D(emitcode ("; genModOneByte",""));
3928 /* signed or unsigned */
3929 if (SPEC_USIGN (opetype))
3931 /* unsigned is easy */
3932 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3933 l = aopGet (AOP (left), 0, FALSE, FALSE);
3935 emitcode ("div", "ab");
3936 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3940 /* signed is a little bit more difficult */
3942 /* save the signs of the operands */
3943 l = aopGet (AOP (left), 0, FALSE, FALSE);
3946 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3947 emitcode ("push", "acc"); /* save it on the stack */
3949 /* now sign adjust for both left & right */
3950 l = aopGet (AOP (right), 0, FALSE, FALSE);
3953 lbl = newiTempLabel (NULL);
3954 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3955 emitcode ("cpl", "a");
3956 emitcode ("inc", "a");
3957 emitcode ("", "%05d$:", (lbl->key + 100));
3958 emitcode ("mov", "b,a");
3960 /* sign adjust left side */
3961 l = aopGet (AOP (left), 0, FALSE, FALSE);
3964 lbl = newiTempLabel (NULL);
3965 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3966 emitcode ("cpl", "a");
3967 emitcode ("inc", "a");
3968 emitcode ("", "%05d$:", (lbl->key + 100));
3970 /* now the multiplication */
3971 emitcode ("div", "ab");
3972 /* we are interested in the lower order
3974 lbl = newiTempLabel (NULL);
3975 emitcode ("pop", "acc");
3976 /* if there was an over flow we don't
3977 adjust the sign of the result */
3978 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3979 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3981 emitcode ("clr", "a");
3982 emitcode ("subb", "a,b");
3983 emitcode ("mov", "b,a");
3984 emitcode ("", "%05d$:", (lbl->key + 100));
3986 /* now we are done */
3987 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
3991 /*-----------------------------------------------------------------*/
3992 /* genMod - generates code for division */
3993 /*-----------------------------------------------------------------*/
3997 operand *left = IC_LEFT (ic);
3998 operand *right = IC_RIGHT (ic);
3999 operand *result = IC_RESULT (ic);
4001 D(emitcode ("; genMod",""));
4003 /* assign the amsops */
4004 aopOp (left, ic, FALSE);
4005 aopOp (right, ic, FALSE);
4006 aopOp (result, ic, TRUE);
4008 /* special cases first */
4010 if (AOP_TYPE (left) == AOP_CRY &&
4011 AOP_TYPE (right) == AOP_CRY)
4013 genModbits (left, right, result);
4017 /* if both are of size == 1 */
4018 if (AOP_SIZE (left) == 1 &&
4019 AOP_SIZE (right) == 1)
4021 genModOneByte (left, right, result);
4025 /* should have been converted to function call */
4029 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4030 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4031 freeAsmop (result, NULL, ic, TRUE);
4034 /*-----------------------------------------------------------------*/
4035 /* genIfxJump :- will create a jump depending on the ifx */
4036 /*-----------------------------------------------------------------*/
4038 genIfxJump (iCode * ic, char *jval)
4041 symbol *tlbl = newiTempLabel (NULL);
4044 D(emitcode ("; genIfxJump",""));
4046 /* if true label then we jump if condition
4050 jlbl = IC_TRUE (ic);
4051 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4052 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4056 /* false label is present */
4057 jlbl = IC_FALSE (ic);
4058 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4059 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4061 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4062 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4064 emitcode (inst, "%05d$", tlbl->key + 100);
4065 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4066 emitcode ("", "%05d$:", tlbl->key + 100);
4068 /* mark the icode as generated */
4072 /*-----------------------------------------------------------------*/
4073 /* genCmp :- greater or less than comparison */
4074 /*-----------------------------------------------------------------*/
4076 genCmp (operand * left, operand * right,
4077 operand * result, iCode * ifx, int sign, iCode *ic)
4079 int size, offset = 0;
4080 unsigned long lit = 0L;
4083 D(emitcode ("; genCmp",""));
4085 /* if left & right are bit variables */
4086 if (AOP_TYPE (left) == AOP_CRY &&
4087 AOP_TYPE (right) == AOP_CRY)
4089 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4090 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4094 /* subtract right from left if at the
4095 end the carry flag is set then we know that
4096 left is greater than right */
4097 size = max (AOP_SIZE (left), AOP_SIZE (right));
4099 /* if unsigned char cmp with lit, do cjne left,#right,zz */
4100 if ((size == 1) && !sign &&
4101 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
4103 symbol *lbl = newiTempLabel (NULL);
4104 emitcode ("cjne", "%s,%s,%05d$",
4105 aopGet (AOP (left), offset, FALSE, FALSE),
4106 aopGet (AOP (right), offset, FALSE, FALSE),
4108 emitcode ("", "%05d$:", lbl->key + 100);
4112 if (AOP_TYPE (right) == AOP_LIT)
4114 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4115 /* optimize if(x < 0) or if(x >= 0) */
4124 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
4125 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
4127 genIfxJump (ifx, "acc.7");
4131 emitcode ("rlc", "a");
4139 rightInB = aopGetUsesAcc(AOP (right), offset);
4141 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4142 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4143 if (sign && size == 0)
4145 emitcode ("xrl", "a,#0x80");
4146 if (AOP_TYPE (right) == AOP_LIT)
4148 unsigned long lit = (unsigned long)
4149 floatFromVal (AOP (right)->aopu.aop_lit);
4150 emitcode ("subb", "a,#0x%02x",
4151 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4156 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4157 emitcode ("xrl", "b,#0x80");
4158 emitcode ("subb", "a,b");
4164 emitcode ("subb", "a,b");
4166 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4174 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4175 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4176 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4182 /* if the result is used in the next
4183 ifx conditional branch then generate
4184 code a little differently */
4186 genIfxJump (ifx, "c");
4189 /* leave the result in acc */
4193 /*-----------------------------------------------------------------*/
4194 /* genCmpGt :- greater than comparison */
4195 /*-----------------------------------------------------------------*/
4197 genCmpGt (iCode * ic, iCode * ifx)
4199 operand *left, *right, *result;
4200 sym_link *letype, *retype;
4203 D(emitcode ("; genCmpGt",""));
4205 left = IC_LEFT (ic);
4206 right = IC_RIGHT (ic);
4207 result = IC_RESULT (ic);
4209 letype = getSpec (operandType (left));
4210 retype = getSpec (operandType (right));
4211 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4212 /* assign the amsops */
4213 aopOp (left, ic, FALSE);
4214 aopOp (right, ic, FALSE);
4215 aopOp (result, ic, TRUE);
4217 genCmp (right, left, result, ifx, sign,ic);
4219 freeAsmop (result, NULL, ic, TRUE);
4222 /*-----------------------------------------------------------------*/
4223 /* genCmpLt - less than comparisons */
4224 /*-----------------------------------------------------------------*/
4226 genCmpLt (iCode * ic, iCode * ifx)
4228 operand *left, *right, *result;
4229 sym_link *letype, *retype;
4232 D(emitcode ("; genCmpLt",""));
4234 left = IC_LEFT (ic);
4235 right = IC_RIGHT (ic);
4236 result = IC_RESULT (ic);
4238 letype = getSpec (operandType (left));
4239 retype = getSpec (operandType (right));
4240 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4242 /* assign the amsops */
4243 aopOp (left, ic, FALSE);
4244 aopOp (right, ic, FALSE);
4245 aopOp (result, ic, TRUE);
4247 genCmp (left, right, result, ifx, sign,ic);
4249 freeAsmop (result, NULL, ic, TRUE);
4252 /*-----------------------------------------------------------------*/
4253 /* gencjneshort - compare and jump if not equal */
4254 /*-----------------------------------------------------------------*/
4256 gencjneshort (operand * left, operand * right, symbol * lbl)
4258 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4260 unsigned long lit = 0L;
4262 /* if the left side is a literal or
4263 if the right is in a pointer register and left
4265 if ((AOP_TYPE (left) == AOP_LIT) ||
4266 (AOP_TYPE (left) == AOP_IMMD) ||
4267 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4274 if (AOP_TYPE (right) == AOP_LIT)
4275 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4277 /* if the right side is a literal then anything goes */
4278 if (AOP_TYPE (right) == AOP_LIT &&
4279 AOP_TYPE (left) != AOP_DIR &&
4280 AOP_TYPE (left) != AOP_IMMD)
4284 emitcode ("cjne", "%s,%s,%05d$",
4285 aopGet (AOP (left), offset, FALSE, FALSE),
4286 aopGet (AOP (right), offset, FALSE, FALSE),
4292 /* if the right side is in a register or in direct space or
4293 if the left is a pointer register & right is not */
4294 else if (AOP_TYPE (right) == AOP_REG ||
4295 AOP_TYPE (right) == AOP_DIR ||
4296 AOP_TYPE (right) == AOP_LIT ||
4297 AOP_TYPE (right) == AOP_IMMD ||
4298 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4299 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4303 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4304 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4305 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4306 emitcode ("jnz", "%05d$", lbl->key + 100);
4308 emitcode ("cjne", "a,%s,%05d$",
4309 aopGet (AOP (right), offset, FALSE, TRUE),
4316 /* right is a pointer reg need both a & b */
4319 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4320 if (strcmp (l, "b"))
4321 emitcode ("mov", "b,%s", l);
4322 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4323 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4329 /*-----------------------------------------------------------------*/
4330 /* gencjne - compare and jump if not equal */
4331 /*-----------------------------------------------------------------*/
4333 gencjne (operand * left, operand * right, symbol * lbl)
4335 symbol *tlbl = newiTempLabel (NULL);
4337 gencjneshort (left, right, lbl);
4339 emitcode ("mov", "a,%s", one);
4340 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4341 emitcode ("", "%05d$:", lbl->key + 100);
4342 emitcode ("clr", "a");
4343 emitcode ("", "%05d$:", tlbl->key + 100);
4346 /*-----------------------------------------------------------------*/
4347 /* genCmpEq - generates code for equal to */
4348 /*-----------------------------------------------------------------*/
4350 genCmpEq (iCode * ic, iCode * ifx)
4352 operand *left, *right, *result;
4354 D(emitcode ("; genCmpEq",""));
4356 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4357 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4358 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4360 /* if literal, literal on the right or
4361 if the right is in a pointer register and left
4363 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4364 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4366 operand *t = IC_RIGHT (ic);
4367 IC_RIGHT (ic) = IC_LEFT (ic);
4371 if (ifx && !AOP_SIZE (result))
4374 /* if they are both bit variables */
4375 if (AOP_TYPE (left) == AOP_CRY &&
4376 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4378 if (AOP_TYPE (right) == AOP_LIT)
4380 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4383 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4384 emitcode ("cpl", "c");
4388 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4392 emitcode ("clr", "c");
4394 /* AOP_TYPE(right) == AOP_CRY */
4398 symbol *lbl = newiTempLabel (NULL);
4399 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4400 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4401 emitcode ("cpl", "c");
4402 emitcode ("", "%05d$:", (lbl->key + 100));
4404 /* if true label then we jump if condition
4406 tlbl = newiTempLabel (NULL);
4409 emitcode ("jnc", "%05d$", tlbl->key + 100);
4410 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4414 emitcode ("jc", "%05d$", tlbl->key + 100);
4415 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4417 emitcode ("", "%05d$:", tlbl->key + 100);
4421 tlbl = newiTempLabel (NULL);
4422 gencjneshort (left, right, tlbl);
4425 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4426 emitcode ("", "%05d$:", tlbl->key + 100);
4430 symbol *lbl = newiTempLabel (NULL);
4431 emitcode ("sjmp", "%05d$", lbl->key + 100);
4432 emitcode ("", "%05d$:", tlbl->key + 100);
4433 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4434 emitcode ("", "%05d$:", lbl->key + 100);
4437 /* mark the icode as generated */
4442 /* if they are both bit variables */
4443 if (AOP_TYPE (left) == AOP_CRY &&
4444 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4446 if (AOP_TYPE (right) == AOP_LIT)
4448 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4451 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4452 emitcode ("cpl", "c");
4456 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4460 emitcode ("clr", "c");
4462 /* AOP_TYPE(right) == AOP_CRY */
4466 symbol *lbl = newiTempLabel (NULL);
4467 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4468 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4469 emitcode ("cpl", "c");
4470 emitcode ("", "%05d$:", (lbl->key + 100));
4473 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4480 genIfxJump (ifx, "c");
4483 /* if the result is used in an arithmetic operation
4484 then put the result in place */
4489 gencjne (left, right, newiTempLabel (NULL));
4490 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4492 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4497 genIfxJump (ifx, "a");
4500 /* if the result is used in an arithmetic operation
4501 then put the result in place */
4502 if (AOP_TYPE (result) != AOP_CRY)
4504 /* leave the result in acc */
4508 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4509 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4510 freeAsmop (result, NULL, ic, TRUE);
4513 /*-----------------------------------------------------------------*/
4514 /* ifxForOp - returns the icode containing the ifx for operand */
4515 /*-----------------------------------------------------------------*/
4517 ifxForOp (operand * op, iCode * ic)
4519 /* if true symbol then needs to be assigned */
4520 if (IS_TRUE_SYMOP (op))
4523 /* if this has register type condition and
4524 the next instruction is ifx with the same operand
4525 and live to of the operand is upto the ifx only then */
4527 ic->next->op == IFX &&
4528 IC_COND (ic->next)->key == op->key &&
4529 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4535 /*-----------------------------------------------------------------*/
4536 /* hasInc - operand is incremented before any other use */
4537 /*-----------------------------------------------------------------*/
4539 hasInc (operand *op, iCode *ic,int osize)
4541 sym_link *type = operandType(op);
4542 sym_link *retype = getSpec (type);
4543 iCode *lic = ic->next;
4546 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4547 if (!IS_SYMOP(op)) return NULL;
4549 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4550 if (IS_AGGREGATE(type->next)) return NULL;
4551 if (osize != (isize = getSize(type->next))) return NULL;
4554 /* if operand of the form op = op + <sizeof *op> */
4555 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4556 isOperandEqual(IC_RESULT(lic),op) &&
4557 isOperandLiteral(IC_RIGHT(lic)) &&
4558 operandLitValue(IC_RIGHT(lic)) == isize) {
4561 /* if the operand used or deffed */
4562 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4565 /* if GOTO or IFX */
4566 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4572 /*-----------------------------------------------------------------*/
4573 /* genAndOp - for && operation */
4574 /*-----------------------------------------------------------------*/
4576 genAndOp (iCode * ic)
4578 operand *left, *right, *result;
4581 D(emitcode ("; genAndOp",""));
4583 /* note here that && operations that are in an
4584 if statement are taken away by backPatchLabels
4585 only those used in arthmetic operations remain */
4586 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4587 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4588 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4590 /* if both are bit variables */
4591 if (AOP_TYPE (left) == AOP_CRY &&
4592 AOP_TYPE (right) == AOP_CRY)
4594 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4595 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4600 tlbl = newiTempLabel (NULL);
4602 emitcode ("jz", "%05d$", tlbl->key + 100);
4604 emitcode ("", "%05d$:", tlbl->key + 100);
4608 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4609 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4610 freeAsmop (result, NULL, ic, TRUE);
4614 /*-----------------------------------------------------------------*/
4615 /* genOrOp - for || operation */
4616 /*-----------------------------------------------------------------*/
4618 genOrOp (iCode * ic)
4620 operand *left, *right, *result;
4623 D(emitcode ("; genOrOp",""));
4625 /* note here that || operations that are in an
4626 if statement are taken away by backPatchLabels
4627 only those used in arthmetic operations remain */
4628 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4629 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4630 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4632 /* if both are bit variables */
4633 if (AOP_TYPE (left) == AOP_CRY &&
4634 AOP_TYPE (right) == AOP_CRY)
4636 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4637 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4642 tlbl = newiTempLabel (NULL);
4644 emitcode ("jnz", "%05d$", tlbl->key + 100);
4646 emitcode ("", "%05d$:", tlbl->key + 100);
4650 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4651 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4652 freeAsmop (result, NULL, ic, TRUE);
4655 /*-----------------------------------------------------------------*/
4656 /* isLiteralBit - test if lit == 2^n */
4657 /*-----------------------------------------------------------------*/
4659 isLiteralBit (unsigned long lit)
4661 unsigned long pw[32] =
4662 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4663 0x100L, 0x200L, 0x400L, 0x800L,
4664 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4665 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4666 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4667 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4668 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4671 for (idx = 0; idx < 32; idx++)
4677 /*-----------------------------------------------------------------*/
4678 /* continueIfTrue - */
4679 /*-----------------------------------------------------------------*/
4681 continueIfTrue (iCode * ic)
4684 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4688 /*-----------------------------------------------------------------*/
4690 /*-----------------------------------------------------------------*/
4692 jumpIfTrue (iCode * ic)
4695 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4699 /*-----------------------------------------------------------------*/
4700 /* jmpTrueOrFalse - */
4701 /*-----------------------------------------------------------------*/
4703 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4705 // ugly but optimized by peephole
4708 symbol *nlbl = newiTempLabel (NULL);
4709 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4710 emitcode ("", "%05d$:", tlbl->key + 100);
4711 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4712 emitcode ("", "%05d$:", nlbl->key + 100);
4716 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4717 emitcode ("", "%05d$:", tlbl->key + 100);
4722 /*-----------------------------------------------------------------*/
4723 /* genAnd - code for and */
4724 /*-----------------------------------------------------------------*/
4726 genAnd (iCode * ic, iCode * ifx)
4728 operand *left, *right, *result;
4729 int size, offset = 0;
4730 unsigned long lit = 0L;
4734 D(emitcode ("; genAnd",""));
4736 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4737 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4738 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4741 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4743 AOP_TYPE (left), AOP_TYPE (right));
4744 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4746 AOP_SIZE (left), AOP_SIZE (right));
4749 /* if left is a literal & right is not then exchange them */
4750 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4751 AOP_NEEDSACC (left))
4753 operand *tmp = right;
4758 /* if result = right then exchange them */
4759 if (sameRegs (AOP (result), AOP (right)))
4761 operand *tmp = right;
4766 /* if right is bit then exchange them */
4767 if (AOP_TYPE (right) == AOP_CRY &&
4768 AOP_TYPE (left) != AOP_CRY)
4770 operand *tmp = right;
4774 if (AOP_TYPE (right) == AOP_LIT)
4775 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4777 size = AOP_SIZE (result);
4780 // result = bit & yy;
4781 if (AOP_TYPE (left) == AOP_CRY)
4783 // c = bit & literal;
4784 if (AOP_TYPE (right) == AOP_LIT)
4788 if (size && sameRegs (AOP (result), AOP (left)))
4791 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4796 if (size && (AOP_TYPE (result) == AOP_CRY))
4798 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4801 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4806 emitcode ("clr", "c");
4811 if (AOP_TYPE (right) == AOP_CRY)
4814 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4815 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4820 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4822 emitcode ("rrc", "a");
4823 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4831 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4832 genIfxJump (ifx, "c");
4836 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4837 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4838 if ((AOP_TYPE (right) == AOP_LIT) &&
4839 (AOP_TYPE (result) == AOP_CRY) &&
4840 (AOP_TYPE (left) != AOP_CRY))
4842 int posbit = isLiteralBit (lit);
4847 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4850 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4856 sprintf (buffer, "acc.%d", posbit & 0x07);
4857 genIfxJump (ifx, buffer);
4864 symbol *tlbl = newiTempLabel (NULL);
4865 int sizel = AOP_SIZE (left);
4867 emitcode ("setb", "c");
4870 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4872 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4874 if ((posbit = isLiteralBit (bytelit)) != 0)
4875 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4878 if (bytelit != 0x0FFL)
4879 emitcode ("anl", "a,%s",
4880 aopGet (AOP (right), offset, FALSE, TRUE));
4881 emitcode ("jnz", "%05d$", tlbl->key + 100);
4886 // bit = left & literal
4889 emitcode ("clr", "c");
4890 emitcode ("", "%05d$:", tlbl->key + 100);
4892 // if(left & literal)
4896 jmpTrueOrFalse (ifx, tlbl);
4904 /* if left is same as result */
4905 if (sameRegs (AOP (result), AOP (left)))
4907 for (; size--; offset++)
4909 if (AOP_TYPE (right) == AOP_LIT)
4911 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4913 else if (bytelit == 0)
4915 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
4917 else if (IS_AOP_PREG (result))
4919 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4920 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4921 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4924 emitcode ("anl", "%s,%s",
4925 aopGet (AOP (left), offset, FALSE, TRUE),
4926 aopGet (AOP (right), offset, FALSE, FALSE));
4930 if (AOP_TYPE (left) == AOP_ACC)
4931 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4934 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4935 if (IS_AOP_PREG (result))
4937 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4938 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
4942 emitcode ("anl", "%s,a",
4943 aopGet (AOP (left), offset, FALSE, TRUE));
4950 // left & result in different registers
4951 if (AOP_TYPE (result) == AOP_CRY)
4954 // if(size), result in bit
4955 // if(!size && ifx), conditional oper: if(left & right)
4956 symbol *tlbl = newiTempLabel (NULL);
4957 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4959 emitcode ("setb", "c");
4962 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4963 emitcode ("anl", "a,%s",
4964 aopGet (AOP (right), offset, FALSE, FALSE));
4966 if (AOP_TYPE(left)==AOP_ACC) {
4967 emitcode("mov", "b,a");
4968 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4969 emitcode("anl", "a,b");
4971 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4972 emitcode ("anl", "a,%s",
4973 aopGet (AOP (left), offset, FALSE, FALSE));
4976 emitcode ("jnz", "%05d$", tlbl->key + 100);
4982 emitcode ("", "%05d$:", tlbl->key + 100);
4986 jmpTrueOrFalse (ifx, tlbl);
4990 for (; (size--); offset++)
4993 // result = left & right
4994 if (AOP_TYPE (right) == AOP_LIT)
4996 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4998 aopPut (AOP (result),
4999 aopGet (AOP (left), offset, FALSE, FALSE),
5001 isOperandVolatile (result, FALSE));
5004 else if (bytelit == 0)
5006 /* dummy read of volatile operand */
5007 if (isOperandVolatile (left, FALSE))
5008 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5009 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5013 // faster than result <- left, anl result,right
5014 // and better if result is SFR
5015 if (AOP_TYPE (left) == AOP_ACC)
5016 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5019 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5020 emitcode ("anl", "a,%s",
5021 aopGet (AOP (left), offset, FALSE, FALSE));
5023 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5029 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5030 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5031 freeAsmop (result, NULL, ic, TRUE);
5034 /*-----------------------------------------------------------------*/
5035 /* genOr - code for or */
5036 /*-----------------------------------------------------------------*/
5038 genOr (iCode * ic, iCode * ifx)
5040 operand *left, *right, *result;
5041 int size, offset = 0;
5042 unsigned long lit = 0L;
5044 D(emitcode ("; genOr",""));
5046 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5047 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5048 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5051 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5053 AOP_TYPE (left), AOP_TYPE (right));
5054 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5056 AOP_SIZE (left), AOP_SIZE (right));
5059 /* if left is a literal & right is not then exchange them */
5060 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5061 AOP_NEEDSACC (left))
5063 operand *tmp = right;
5068 /* if result = right then exchange them */
5069 if (sameRegs (AOP (result), AOP (right)))
5071 operand *tmp = right;
5076 /* if right is bit then exchange them */
5077 if (AOP_TYPE (right) == AOP_CRY &&
5078 AOP_TYPE (left) != AOP_CRY)
5080 operand *tmp = right;
5084 if (AOP_TYPE (right) == AOP_LIT)
5085 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5087 size = AOP_SIZE (result);
5091 if (AOP_TYPE (left) == AOP_CRY)
5093 if (AOP_TYPE (right) == AOP_LIT)
5095 // c = bit | literal;
5098 // lit != 0 => result = 1
5099 if (AOP_TYPE (result) == AOP_CRY)
5102 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5104 continueIfTrue (ifx);
5107 emitcode ("setb", "c");
5111 // lit == 0 => result = left
5112 if (size && sameRegs (AOP (result), AOP (left)))
5114 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5119 if (AOP_TYPE (right) == AOP_CRY)
5122 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5123 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
5128 symbol *tlbl = newiTempLabel (NULL);
5129 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
5130 emitcode ("setb", "c");
5131 emitcode ("jb", "%s,%05d$",
5132 AOP (left)->aopu.aop_dir, tlbl->key + 100);
5134 emitcode ("jnz", "%05d$", tlbl->key + 100);
5135 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5137 jmpTrueOrFalse (ifx, tlbl);
5143 emitcode ("", "%05d$:", tlbl->key + 100);
5152 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5153 genIfxJump (ifx, "c");
5157 // if(val | 0xZZ) - size = 0, ifx != FALSE -
5158 // bit = val | 0xZZ - size = 1, ifx = FALSE -
5159 if ((AOP_TYPE (right) == AOP_LIT) &&
5160 (AOP_TYPE (result) == AOP_CRY) &&
5161 (AOP_TYPE (left) != AOP_CRY))
5167 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5169 continueIfTrue (ifx);
5174 // lit = 0, result = boolean(left)
5176 emitcode ("setb", "c");
5180 symbol *tlbl = newiTempLabel (NULL);
5181 emitcode ("jnz", "%05d$", tlbl->key + 100);
5183 emitcode ("", "%05d$:", tlbl->key + 100);
5187 genIfxJump (ifx, "a");
5195 /* if left is same as result */
5196 if (sameRegs (AOP (result), AOP (left)))
5198 for (; size--; offset++)
5200 if (AOP_TYPE (right) == AOP_LIT)
5202 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5204 /* dummy read of volatile operand */
5205 if (isOperandVolatile (left, FALSE))
5206 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5210 else if (IS_AOP_PREG (left))
5212 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5213 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5214 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5217 emitcode ("orl", "%s,%s",
5218 aopGet (AOP (left), offset, FALSE, TRUE),
5219 aopGet (AOP (right), offset, FALSE, FALSE));
5223 if (AOP_TYPE (left) == AOP_ACC)
5224 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5227 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5228 if (IS_AOP_PREG (left))
5230 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5231 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5234 emitcode ("orl", "%s,a",
5235 aopGet (AOP (left), offset, FALSE, TRUE));
5242 // left & result in different registers
5243 if (AOP_TYPE (result) == AOP_CRY)
5246 // if(size), result in bit
5247 // if(!size && ifx), conditional oper: if(left | right)
5248 symbol *tlbl = newiTempLabel (NULL);
5249 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5251 emitcode ("setb", "c");
5254 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5255 emitcode ("orl", "a,%s",
5256 aopGet (AOP (right), offset, FALSE, FALSE));
5258 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5259 emitcode ("orl", "a,%s",
5260 aopGet (AOP (left), offset, FALSE, FALSE));
5262 emitcode ("jnz", "%05d$", tlbl->key + 100);
5268 emitcode ("", "%05d$:", tlbl->key + 100);
5272 jmpTrueOrFalse (ifx, tlbl);
5275 for (; (size--); offset++)
5278 // result = left & right
5279 if (AOP_TYPE (right) == AOP_LIT)
5281 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5283 aopPut (AOP (result),
5284 aopGet (AOP (left), offset, FALSE, FALSE),
5286 isOperandVolatile (result, FALSE));
5290 // faster than result <- left, anl result,right
5291 // and better if result is SFR
5292 if (AOP_TYPE (left) == AOP_ACC)
5293 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5296 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5297 emitcode ("orl", "a,%s",
5298 aopGet (AOP (left), offset, FALSE, FALSE));
5300 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5305 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5306 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5307 freeAsmop (result, NULL, ic, TRUE);
5310 /*-----------------------------------------------------------------*/
5311 /* genXor - code for xclusive or */
5312 /*-----------------------------------------------------------------*/
5314 genXor (iCode * ic, iCode * ifx)
5316 operand *left, *right, *result;
5317 int size, offset = 0;
5318 unsigned long lit = 0L;
5320 D(emitcode ("; genXor",""));
5322 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5323 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5324 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5327 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5329 AOP_TYPE (left), AOP_TYPE (right));
5330 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5332 AOP_SIZE (left), AOP_SIZE (right));
5335 /* if left is a literal & right is not ||
5336 if left needs acc & right does not */
5337 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5338 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5340 operand *tmp = right;
5345 /* if result = right then exchange them */
5346 if (sameRegs (AOP (result), AOP (right)))
5348 operand *tmp = right;
5353 /* if right is bit then exchange them */
5354 if (AOP_TYPE (right) == AOP_CRY &&
5355 AOP_TYPE (left) != AOP_CRY)
5357 operand *tmp = right;
5361 if (AOP_TYPE (right) == AOP_LIT)
5362 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5364 size = AOP_SIZE (result);
5368 if (AOP_TYPE (left) == AOP_CRY)
5370 if (AOP_TYPE (right) == AOP_LIT)
5372 // c = bit & literal;
5375 // lit>>1 != 0 => result = 1
5376 if (AOP_TYPE (result) == AOP_CRY)
5379 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5381 continueIfTrue (ifx);
5384 emitcode ("setb", "c");
5391 // lit == 0, result = left
5392 if (size && sameRegs (AOP (result), AOP (left)))
5394 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5398 // lit == 1, result = not(left)
5399 if (size && sameRegs (AOP (result), AOP (left)))
5401 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5406 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5407 emitcode ("cpl", "c");
5416 symbol *tlbl = newiTempLabel (NULL);
5417 if (AOP_TYPE (right) == AOP_CRY)
5420 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5424 int sizer = AOP_SIZE (right);
5426 // if val>>1 != 0, result = 1
5427 emitcode ("setb", "c");
5430 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5432 // test the msb of the lsb
5433 emitcode ("anl", "a,#0xfe");
5434 emitcode ("jnz", "%05d$", tlbl->key + 100);
5438 emitcode ("rrc", "a");
5440 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5441 emitcode ("cpl", "c");
5442 emitcode ("", "%05d$:", (tlbl->key + 100));
5449 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5450 genIfxJump (ifx, "c");
5454 if (sameRegs (AOP (result), AOP (left)))
5456 /* if left is same as result */
5457 for (; size--; offset++)
5459 if (AOP_TYPE (right) == AOP_LIT)
5461 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5463 else if (IS_AOP_PREG (left))
5465 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5466 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5467 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5470 emitcode ("xrl", "%s,%s",
5471 aopGet (AOP (left), offset, FALSE, TRUE),
5472 aopGet (AOP (right), offset, FALSE, FALSE));
5476 if (AOP_TYPE (left) == AOP_ACC)
5477 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5480 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5481 if (IS_AOP_PREG (left))
5483 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5484 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5487 emitcode ("xrl", "%s,a",
5488 aopGet (AOP (left), offset, FALSE, TRUE));
5495 // left & result in different registers
5496 if (AOP_TYPE (result) == AOP_CRY)
5499 // if(size), result in bit
5500 // if(!size && ifx), conditional oper: if(left ^ right)
5501 symbol *tlbl = newiTempLabel (NULL);
5502 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5504 emitcode ("setb", "c");
5507 if ((AOP_TYPE (right) == AOP_LIT) &&
5508 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5510 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5514 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5515 emitcode ("xrl", "a,%s",
5516 aopGet (AOP (right), offset, FALSE, FALSE));
5518 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5519 emitcode ("xrl", "a,%s",
5520 aopGet (AOP (left), offset, FALSE, FALSE));
5523 emitcode ("jnz", "%05d$", tlbl->key + 100);
5529 emitcode ("", "%05d$:", tlbl->key + 100);
5533 jmpTrueOrFalse (ifx, tlbl);
5536 for (; (size--); offset++)
5539 // result = left & right
5540 if (AOP_TYPE (right) == AOP_LIT)
5542 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5544 aopPut (AOP (result),
5545 aopGet (AOP (left), offset, FALSE, FALSE),
5547 isOperandVolatile (result, FALSE));
5551 // faster than result <- left, anl result,right
5552 // and better if result is SFR
5553 if (AOP_TYPE (left) == AOP_ACC)
5554 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5557 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5558 emitcode ("xrl", "a,%s",
5559 aopGet (AOP (left), offset, FALSE, TRUE));
5561 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5566 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5567 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5568 freeAsmop (result, NULL, ic, TRUE);
5571 /*-----------------------------------------------------------------*/
5572 /* genInline - write the inline code out */
5573 /*-----------------------------------------------------------------*/
5575 genInline (iCode * ic)
5577 char *buffer, *bp, *bp1;
5579 D(emitcode ("; genInline",""));
5581 _G.inLine += (!options.asmpeep);
5583 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5584 strcpy (buffer, IC_INLINE (ic));
5586 /* emit each line as a code */
5611 /* emitcode("",buffer); */
5612 _G.inLine -= (!options.asmpeep);
5615 /*-----------------------------------------------------------------*/
5616 /* genRRC - rotate right with carry */
5617 /*-----------------------------------------------------------------*/
5621 operand *left, *result;
5622 int size, offset = 0;
5625 D(emitcode ("; genRRC",""));
5627 /* rotate right with carry */
5628 left = IC_LEFT (ic);
5629 result = IC_RESULT (ic);
5630 aopOp (left, ic, FALSE);
5631 aopOp (result, ic, FALSE);
5633 /* move it to the result */
5634 size = AOP_SIZE (result);
5636 if (size == 1) { /* special case for 1 byte */
5637 l = aopGet (AOP (left), offset, FALSE, FALSE);
5639 emitcode ("rr", "a");
5645 l = aopGet (AOP (left), offset, FALSE, FALSE);
5647 emitcode ("rrc", "a");
5648 if (AOP_SIZE (result) > 1)
5649 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
5651 /* now we need to put the carry into the
5652 highest order byte of the result */
5653 if (AOP_SIZE (result) > 1)
5655 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5658 emitcode ("mov", "acc.7,c");
5660 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
5661 freeAsmop (left, NULL, ic, TRUE);
5662 freeAsmop (result, NULL, ic, TRUE);
5665 /*-----------------------------------------------------------------*/
5666 /* genRLC - generate code for rotate left with carry */
5667 /*-----------------------------------------------------------------*/
5671 operand *left, *result;
5672 int size, offset = 0;
5675 D(emitcode ("; genRLC",""));
5677 /* rotate right with carry */
5678 left = IC_LEFT (ic);
5679 result = IC_RESULT (ic);
5680 aopOp (left, ic, FALSE);
5681 aopOp (result, ic, FALSE);
5683 /* move it to the result */
5684 size = AOP_SIZE (result);
5688 l = aopGet (AOP (left), offset, FALSE, FALSE);
5690 if (size == 0) { /* special case for 1 byte */
5694 emitcode ("add", "a,acc");
5695 if (AOP_SIZE (result) > 1)
5696 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5699 l = aopGet (AOP (left), offset, FALSE, FALSE);
5701 emitcode ("rlc", "a");
5702 if (AOP_SIZE (result) > 1)
5703 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
5706 /* now we need to put the carry into the
5707 highest order byte of the result */
5708 if (AOP_SIZE (result) > 1)
5710 l = aopGet (AOP (result), 0, FALSE, FALSE);
5713 emitcode ("mov", "acc.0,c");
5715 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5716 freeAsmop (left, NULL, ic, TRUE);
5717 freeAsmop (result, NULL, ic, TRUE);
5720 /*-----------------------------------------------------------------*/
5721 /* genGetHbit - generates code get highest order bit */
5722 /*-----------------------------------------------------------------*/
5724 genGetHbit (iCode * ic)
5726 operand *left, *result;
5728 D(emitcode ("; genGetHbit",""));
5730 left = IC_LEFT (ic);
5731 result = IC_RESULT (ic);
5732 aopOp (left, ic, FALSE);
5733 aopOp (result, ic, FALSE);
5735 /* get the highest order byte into a */
5736 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5737 if (AOP_TYPE (result) == AOP_CRY)
5739 emitcode ("rlc", "a");
5744 emitcode ("rl", "a");
5745 emitcode ("anl", "a,#0x01");
5750 freeAsmop (left, NULL, ic, TRUE);
5751 freeAsmop (result, NULL, ic, TRUE);
5754 /*-----------------------------------------------------------------*/
5755 /* genSwap - generates code to swap nibbles or bytes */
5756 /*-----------------------------------------------------------------*/
5758 genSwap (iCode * ic)
5760 operand *left, *result;
5762 D(emitcode ("; genSwap",""));
5764 left = IC_LEFT (ic);
5765 result = IC_RESULT (ic);
5766 aopOp (left, ic, FALSE);
5767 aopOp (result, ic, FALSE);
5769 switch (AOP_SIZE (left))
5771 case 1: /* swap nibbles in byte */
5772 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5773 emitcode ("swap", "a");
5774 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5776 case 2: /* swap bytes in word */
5777 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
5779 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5780 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5781 0, isOperandVolatile (result, FALSE));
5782 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
5784 else if (operandsEqu (left, result))
5787 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
5788 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
5790 emitcode ("mov", "b,a");
5793 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5794 0, isOperandVolatile (result, FALSE));
5795 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
5799 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
5800 0, isOperandVolatile (result, FALSE));
5801 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
5802 1, isOperandVolatile (result, FALSE));
5806 wassertl(FALSE, "unsupported SWAP operand size");
5809 freeAsmop (left, NULL, ic, TRUE);
5810 freeAsmop (result, NULL, ic, TRUE);
5814 /*-----------------------------------------------------------------*/
5815 /* AccRol - rotate left accumulator by known count */
5816 /*-----------------------------------------------------------------*/
5818 AccRol (int shCount)
5820 shCount &= 0x0007; // shCount : 0..7
5827 emitcode ("rl", "a");
5830 emitcode ("rl", "a");
5831 emitcode ("rl", "a");
5834 emitcode ("swap", "a");
5835 emitcode ("rr", "a");
5838 emitcode ("swap", "a");
5841 emitcode ("swap", "a");
5842 emitcode ("rl", "a");
5845 emitcode ("rr", "a");
5846 emitcode ("rr", "a");
5849 emitcode ("rr", "a");
5854 /*-----------------------------------------------------------------*/
5855 /* AccLsh - left shift accumulator by known count */
5856 /*-----------------------------------------------------------------*/
5858 AccLsh (int shCount)
5863 emitcode ("add", "a,acc");
5864 else if (shCount == 2)
5866 emitcode ("add", "a,acc");
5867 emitcode ("add", "a,acc");
5871 /* rotate left accumulator */
5873 /* and kill the lower order bits */
5874 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5879 /*-----------------------------------------------------------------*/
5880 /* AccRsh - right shift accumulator by known count */
5881 /*-----------------------------------------------------------------*/
5883 AccRsh (int shCount)
5890 emitcode ("rrc", "a");
5894 /* rotate right accumulator */
5895 AccRol (8 - shCount);
5896 /* and kill the higher order bits */
5897 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5902 /*-----------------------------------------------------------------*/
5903 /* AccSRsh - signed right shift accumulator by known count */
5904 /*-----------------------------------------------------------------*/
5906 AccSRsh (int shCount)
5913 emitcode ("mov", "c,acc.7");
5914 emitcode ("rrc", "a");
5916 else if (shCount == 2)
5918 emitcode ("mov", "c,acc.7");
5919 emitcode ("rrc", "a");
5920 emitcode ("mov", "c,acc.7");
5921 emitcode ("rrc", "a");
5925 tlbl = newiTempLabel (NULL);
5926 /* rotate right accumulator */
5927 AccRol (8 - shCount);
5928 /* and kill the higher order bits */
5929 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5930 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5931 emitcode ("orl", "a,#0x%02x",
5932 (unsigned char) ~SRMask[shCount]);
5933 emitcode ("", "%05d$:", tlbl->key + 100);
5938 /*-----------------------------------------------------------------*/
5939 /* shiftR1Left2Result - shift right one byte from left to result */
5940 /*-----------------------------------------------------------------*/
5942 shiftR1Left2Result (operand * left, int offl,
5943 operand * result, int offr,
5944 int shCount, int sign)
5946 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5947 /* shift right accumulator */
5952 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5955 /*-----------------------------------------------------------------*/
5956 /* shiftL1Left2Result - shift left one byte from left to result */
5957 /*-----------------------------------------------------------------*/
5959 shiftL1Left2Result (operand * left, int offl,
5960 operand * result, int offr, int shCount)
5963 l = aopGet (AOP (left), offl, FALSE, FALSE);
5965 /* shift left accumulator */
5967 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5970 /*-----------------------------------------------------------------*/
5971 /* movLeft2Result - move byte from left to result */
5972 /*-----------------------------------------------------------------*/
5974 movLeft2Result (operand * left, int offl,
5975 operand * result, int offr, int sign)
5978 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5980 l = aopGet (AOP (left), offl, FALSE, FALSE);
5982 if (*l == '@' && (IS_AOP_PREG (result)))
5984 emitcode ("mov", "a,%s", l);
5985 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
5990 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
5993 /* MSB sign in acc.7 ! */
5994 if (getDataSize (left) == offl + 1)
5996 emitcode ("mov", "a,%s", l);
5997 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6004 /*-----------------------------------------------------------------*/
6005 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
6006 /*-----------------------------------------------------------------*/
6010 emitcode ("rrc", "a");
6011 emitcode ("xch", "a,%s", x);
6012 emitcode ("rrc", "a");
6013 emitcode ("xch", "a,%s", x);
6016 /*-----------------------------------------------------------------*/
6017 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
6018 /*-----------------------------------------------------------------*/
6022 emitcode ("xch", "a,%s", x);
6023 emitcode ("rlc", "a");
6024 emitcode ("xch", "a,%s", x);
6025 emitcode ("rlc", "a");
6028 /*-----------------------------------------------------------------*/
6029 /* AccAXLsh1 - left shift a:x<-0 by 1 */
6030 /*-----------------------------------------------------------------*/
6034 emitcode ("xch", "a,%s", x);
6035 emitcode ("add", "a,acc");
6036 emitcode ("xch", "a,%s", x);
6037 emitcode ("rlc", "a");
6040 /*-----------------------------------------------------------------*/
6041 /* AccAXLsh - left shift a:x by known count (0..7) */
6042 /*-----------------------------------------------------------------*/
6044 AccAXLsh (char *x, int shCount)
6059 case 5: // AAAAABBB:CCCCCDDD
6061 AccRol (shCount); // BBBAAAAA:CCCCCDDD
6063 emitcode ("anl", "a,#0x%02x",
6064 SLMask[shCount]); // BBB00000:CCCCCDDD
6066 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
6068 AccRol (shCount); // DDDCCCCC:BBB00000
6070 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
6072 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
6074 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
6076 emitcode ("anl", "a,#0x%02x",
6077 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
6079 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
6081 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
6084 case 6: // AAAAAABB:CCCCCCDD
6085 emitcode ("anl", "a,#0x%02x",
6086 SRMask[shCount]); // 000000BB:CCCCCCDD
6087 emitcode ("mov", "c,acc.0"); // c = B
6088 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
6090 AccAXRrl1 (x); // BCCCCCCD:D000000B
6091 AccAXRrl1 (x); // BBCCCCCC:DD000000
6093 emitcode("rrc","a");
6094 emitcode("xch","a,%s", x);
6095 emitcode("rrc","a");
6096 emitcode("mov","c,acc.0"); //<< get correct bit
6097 emitcode("xch","a,%s", x);
6099 emitcode("rrc","a");
6100 emitcode("xch","a,%s", x);
6101 emitcode("rrc","a");
6102 emitcode("xch","a,%s", x);
6105 case 7: // a:x <<= 7
6107 emitcode ("anl", "a,#0x%02x",
6108 SRMask[shCount]); // 0000000B:CCCCCCCD
6110 emitcode ("mov", "c,acc.0"); // c = B
6112 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
6114 AccAXRrl1 (x); // BCCCCCCC:D0000000
6122 /*-----------------------------------------------------------------*/
6123 /* AccAXRsh - right shift a:x known count (0..7) */
6124 /*-----------------------------------------------------------------*/
6126 AccAXRsh (char *x, int shCount)
6134 AccAXRrl1 (x); // 0->a:x
6139 AccAXRrl1 (x); // 0->a:x
6142 AccAXRrl1 (x); // 0->a:x
6147 case 5: // AAAAABBB:CCCCCDDD = a:x
6149 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
6151 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6153 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6155 emitcode ("anl", "a,#0x%02x",
6156 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6158 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6160 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6162 emitcode ("anl", "a,#0x%02x",
6163 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6165 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6167 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6169 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
6172 case 6: // AABBBBBB:CCDDDDDD
6174 emitcode ("mov", "c,acc.7");
6175 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6177 emitcode ("mov", "c,acc.7");
6178 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6180 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6182 emitcode ("anl", "a,#0x%02x",
6183 SRMask[shCount]); // 000000AA:BBBBBBCC
6186 case 7: // ABBBBBBB:CDDDDDDD
6188 emitcode ("mov", "c,acc.7"); // c = A
6190 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6192 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6194 emitcode ("anl", "a,#0x%02x",
6195 SRMask[shCount]); // 0000000A:BBBBBBBC
6203 /*-----------------------------------------------------------------*/
6204 /* AccAXRshS - right shift signed a:x known count (0..7) */
6205 /*-----------------------------------------------------------------*/
6207 AccAXRshS (char *x, int shCount)
6215 emitcode ("mov", "c,acc.7");
6216 AccAXRrl1 (x); // s->a:x
6220 emitcode ("mov", "c,acc.7");
6221 AccAXRrl1 (x); // s->a:x
6223 emitcode ("mov", "c,acc.7");
6224 AccAXRrl1 (x); // s->a:x
6229 case 5: // AAAAABBB:CCCCCDDD = a:x
6231 tlbl = newiTempLabel (NULL);
6232 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
6234 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
6236 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
6238 emitcode ("anl", "a,#0x%02x",
6239 SRMask[shCount]); // 000CCCCC:BBBAAAAA
6241 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
6243 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
6245 emitcode ("anl", "a,#0x%02x",
6246 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
6248 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
6250 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
6252 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
6254 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6255 emitcode ("orl", "a,#0x%02x",
6256 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
6258 emitcode ("", "%05d$:", tlbl->key + 100);
6259 break; // SSSSAAAA:BBBCCCCC
6261 case 6: // AABBBBBB:CCDDDDDD
6263 tlbl = newiTempLabel (NULL);
6264 emitcode ("mov", "c,acc.7");
6265 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
6267 emitcode ("mov", "c,acc.7");
6268 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
6270 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
6272 emitcode ("anl", "a,#0x%02x",
6273 SRMask[shCount]); // 000000AA:BBBBBBCC
6275 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6276 emitcode ("orl", "a,#0x%02x",
6277 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
6279 emitcode ("", "%05d$:", tlbl->key + 100);
6281 case 7: // ABBBBBBB:CDDDDDDD
6283 tlbl = newiTempLabel (NULL);
6284 emitcode ("mov", "c,acc.7"); // c = A
6286 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
6288 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
6290 emitcode ("anl", "a,#0x%02x",
6291 SRMask[shCount]); // 0000000A:BBBBBBBC
6293 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6294 emitcode ("orl", "a,#0x%02x",
6295 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
6297 emitcode ("", "%05d$:", tlbl->key + 100);
6304 /*-----------------------------------------------------------------*/
6305 /* shiftL2Left2Result - shift left two bytes from left to result */
6306 /*-----------------------------------------------------------------*/
6308 shiftL2Left2Result (operand * left, int offl,
6309 operand * result, int offr, int shCount)
6311 if (sameRegs (AOP (result), AOP (left)) &&
6312 ((offl + MSB16) == offr))
6314 /* don't crash result[offr] */
6315 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6316 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6320 movLeft2Result (left, offl, result, offr, 0);
6321 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6323 /* ax << shCount (x = lsb(result)) */
6324 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6325 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6329 /*-----------------------------------------------------------------*/
6330 /* shiftR2Left2Result - shift right two bytes from left to result */
6331 /*-----------------------------------------------------------------*/
6333 shiftR2Left2Result (operand * left, int offl,
6334 operand * result, int offr,
6335 int shCount, int sign)
6337 if (sameRegs (AOP (result), AOP (left)) &&
6338 ((offl + MSB16) == offr))
6340 /* don't crash result[offr] */
6341 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6342 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6346 movLeft2Result (left, offl, result, offr, 0);
6347 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6349 /* a:x >> shCount (x = lsb(result)) */
6351 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6353 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6354 if (getDataSize (result) > 1)
6355 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
6358 /*-----------------------------------------------------------------*/
6359 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6360 /*-----------------------------------------------------------------*/
6362 shiftLLeftOrResult (operand * left, int offl,
6363 operand * result, int offr, int shCount)
6365 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6366 /* shift left accumulator */
6368 /* or with result */
6369 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6370 /* back to result */
6371 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6374 /*-----------------------------------------------------------------*/
6375 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6376 /*-----------------------------------------------------------------*/
6378 shiftRLeftOrResult (operand * left, int offl,
6379 operand * result, int offr, int shCount)
6381 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6382 /* shift right accumulator */
6384 /* or with result */
6385 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6386 /* back to result */
6387 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6390 /*-----------------------------------------------------------------*/
6391 /* genlshOne - left shift a one byte quantity by known count */
6392 /*-----------------------------------------------------------------*/
6394 genlshOne (operand * result, operand * left, int shCount)
6396 D(emitcode ("; genlshOne",""));
6398 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6401 /*-----------------------------------------------------------------*/
6402 /* genlshTwo - left shift two bytes by known amount != 0 */
6403 /*-----------------------------------------------------------------*/
6405 genlshTwo (operand * result, operand * left, int shCount)
6409 D(emitcode ("; genlshTwo",""));
6411 size = getDataSize (result);
6413 /* if shCount >= 8 */
6421 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6423 movLeft2Result (left, LSB, result, MSB16, 0);
6425 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6428 /* 1 <= shCount <= 7 */
6432 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6434 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6438 /*-----------------------------------------------------------------*/
6439 /* shiftLLong - shift left one long from left to result */
6440 /* offl = LSB or MSB16 */
6441 /*-----------------------------------------------------------------*/
6443 shiftLLong (operand * left, operand * result, int offr)
6446 int size = AOP_SIZE (result);
6448 if (size >= LSB + offr)
6450 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6452 emitcode ("add", "a,acc");
6453 if (sameRegs (AOP (left), AOP (result)) &&
6454 size >= MSB16 + offr && offr != LSB)
6455 emitcode ("xch", "a,%s",
6456 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6458 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
6461 if (size >= MSB16 + offr)
6463 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6465 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6468 emitcode ("rlc", "a");
6469 if (sameRegs (AOP (left), AOP (result)) &&
6470 size >= MSB24 + offr && offr != LSB)
6471 emitcode ("xch", "a,%s",
6472 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6474 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
6477 if (size >= MSB24 + offr)
6479 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6481 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6484 emitcode ("rlc", "a");
6485 if (sameRegs (AOP (left), AOP (result)) &&
6486 size >= MSB32 + offr && offr != LSB)
6487 emitcode ("xch", "a,%s",
6488 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6490 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
6493 if (size > MSB32 + offr)
6495 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6497 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6500 emitcode ("rlc", "a");
6501 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
6504 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6507 /*-----------------------------------------------------------------*/
6508 /* genlshFour - shift four byte by a known amount != 0 */
6509 /*-----------------------------------------------------------------*/
6511 genlshFour (operand * result, operand * left, int shCount)
6515 D(emitcode ("; genlshFour",""));
6517 size = AOP_SIZE (result);
6519 /* if shifting more that 3 bytes */
6524 /* lowest order of left goes to the highest
6525 order of the destination */
6526 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6528 movLeft2Result (left, LSB, result, MSB32, 0);
6529 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6530 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6531 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
6535 /* more than two bytes */
6536 else if (shCount >= 16)
6538 /* lower order two bytes goes to higher order two bytes */
6540 /* if some more remaining */
6542 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6545 movLeft2Result (left, MSB16, result, MSB32, 0);
6546 movLeft2Result (left, LSB, result, MSB24, 0);
6548 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
6549 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6553 /* if more than 1 byte */
6554 else if (shCount >= 8)
6556 /* lower order three bytes goes to higher order three bytes */
6561 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6563 movLeft2Result (left, LSB, result, MSB16, 0);
6569 movLeft2Result (left, MSB24, result, MSB32, 0);
6570 movLeft2Result (left, MSB16, result, MSB24, 0);
6571 movLeft2Result (left, LSB, result, MSB16, 0);
6572 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6574 else if (shCount == 1)
6575 shiftLLong (left, result, MSB16);
6578 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6579 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6580 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6581 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
6586 /* 1 <= shCount <= 7 */
6587 else if (shCount <= 2)
6589 shiftLLong (left, result, LSB);
6591 shiftLLong (result, result, LSB);
6593 /* 3 <= shCount <= 7, optimize */
6596 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6597 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6598 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6602 /*-----------------------------------------------------------------*/
6603 /* genLeftShiftLiteral - left shifting by known count */
6604 /*-----------------------------------------------------------------*/
6606 genLeftShiftLiteral (operand * left,
6611 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6614 D(emitcode ("; genLeftShiftLiteral",""));
6616 freeAsmop (right, NULL, ic, TRUE);
6618 aopOp (left, ic, FALSE);
6619 aopOp (result, ic, FALSE);
6621 size = getSize (operandType (result));
6624 emitcode ("; shift left ", "result %d, left %d", size,
6628 /* I suppose that the left size >= result size */
6633 movLeft2Result (left, size, result, size, 0);
6637 else if (shCount >= (size * 8))
6639 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
6645 genlshOne (result, left, shCount);
6649 genlshTwo (result, left, shCount);
6653 genlshFour (result, left, shCount);
6656 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6657 "*** ack! mystery literal shift!\n");
6661 freeAsmop (left, NULL, ic, TRUE);
6662 freeAsmop (result, NULL, ic, TRUE);
6665 /*-----------------------------------------------------------------*/
6666 /* genLeftShift - generates code for left shifting */
6667 /*-----------------------------------------------------------------*/
6669 genLeftShift (iCode * ic)
6671 operand *left, *right, *result;
6674 symbol *tlbl, *tlbl1;
6676 D(emitcode ("; genLeftShift",""));
6678 right = IC_RIGHT (ic);
6679 left = IC_LEFT (ic);
6680 result = IC_RESULT (ic);
6682 aopOp (right, ic, FALSE);
6684 /* if the shift count is known then do it
6685 as efficiently as possible */
6686 if (AOP_TYPE (right) == AOP_LIT)
6688 genLeftShiftLiteral (left, right, result, ic);
6692 /* shift count is unknown then we have to form
6693 a loop get the loop count in B : Note: we take
6694 only the lower order byte since shifting
6695 more that 32 bits make no sense anyway, ( the
6696 largest size of an object can be only 32 bits ) */
6698 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6699 emitcode ("inc", "b");
6700 freeAsmop (right, NULL, ic, TRUE);
6701 aopOp (left, ic, FALSE);
6702 aopOp (result, ic, FALSE);
6704 /* now move the left to the result if they are not the
6706 if (!sameRegs (AOP (left), AOP (result)) &&
6707 AOP_SIZE (result) > 1)
6710 size = AOP_SIZE (result);
6714 l = aopGet (AOP (left), offset, FALSE, TRUE);
6715 if (*l == '@' && (IS_AOP_PREG (result)))
6718 emitcode ("mov", "a,%s", l);
6719 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6722 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
6727 tlbl = newiTempLabel (NULL);
6728 size = AOP_SIZE (result);
6730 tlbl1 = newiTempLabel (NULL);
6732 /* if it is only one byte then */
6735 symbol *tlbl1 = newiTempLabel (NULL);
6737 l = aopGet (AOP (left), 0, FALSE, FALSE);
6739 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6740 emitcode ("", "%05d$:", tlbl->key + 100);
6741 emitcode ("add", "a,acc");
6742 emitcode ("", "%05d$:", tlbl1->key + 100);
6743 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6744 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6748 reAdjustPreg (AOP (result));
6750 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6751 emitcode ("", "%05d$:", tlbl->key + 100);
6752 l = aopGet (AOP (result), offset, FALSE, FALSE);
6754 emitcode ("add", "a,acc");
6755 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6758 l = aopGet (AOP (result), offset, FALSE, FALSE);
6760 emitcode ("rlc", "a");
6761 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6763 reAdjustPreg (AOP (result));
6765 emitcode ("", "%05d$:", tlbl1->key + 100);
6766 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6768 freeAsmop (left, NULL, ic, TRUE);
6769 freeAsmop (result, NULL, ic, TRUE);
6772 /*-----------------------------------------------------------------*/
6773 /* genrshOne - right shift a one byte quantity by known count */
6774 /*-----------------------------------------------------------------*/
6776 genrshOne (operand * result, operand * left,
6777 int shCount, int sign)
6779 D(emitcode ("; genrshOne",""));
6781 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6784 /*-----------------------------------------------------------------*/
6785 /* genrshTwo - right shift two bytes by known amount != 0 */
6786 /*-----------------------------------------------------------------*/
6788 genrshTwo (operand * result, operand * left,
6789 int shCount, int sign)
6791 D(emitcode ("; genrshTwo",""));
6793 /* if shCount >= 8 */
6798 shiftR1Left2Result (left, MSB16, result, LSB,
6801 movLeft2Result (left, MSB16, result, LSB, sign);
6802 addSign (result, MSB16, sign);
6805 /* 1 <= shCount <= 7 */
6807 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6810 /*-----------------------------------------------------------------*/
6811 /* shiftRLong - shift right one long from left to result */
6812 /* offl = LSB or MSB16 */
6813 /*-----------------------------------------------------------------*/
6815 shiftRLong (operand * left, int offl,
6816 operand * result, int sign)
6818 int isSameRegs=sameRegs(AOP(left),AOP(result));
6820 if (isSameRegs && offl>1) {
6821 // we are in big trouble, but this shouldn't happen
6822 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6825 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6830 emitcode ("rlc", "a");
6831 emitcode ("subb", "a,acc");
6833 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6835 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
6836 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6839 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
6844 emitcode ("clr", "c");
6846 emitcode ("mov", "c,acc.7");
6849 emitcode ("rrc", "a");
6851 if (isSameRegs && offl==MSB16) {
6852 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6854 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
6855 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6858 emitcode ("rrc", "a");
6859 if (isSameRegs && offl==1) {
6860 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6862 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
6863 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6865 emitcode ("rrc", "a");
6866 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
6870 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6871 emitcode ("rrc", "a");
6872 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
6876 /*-----------------------------------------------------------------*/
6877 /* genrshFour - shift four byte by a known amount != 0 */
6878 /*-----------------------------------------------------------------*/
6880 genrshFour (operand * result, operand * left,
6881 int shCount, int sign)
6883 D(emitcode ("; genrshFour",""));
6885 /* if shifting more that 3 bytes */
6890 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6892 movLeft2Result (left, MSB32, result, LSB, sign);
6893 addSign (result, MSB16, sign);
6895 else if (shCount >= 16)
6899 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6902 movLeft2Result (left, MSB24, result, LSB, 0);
6903 movLeft2Result (left, MSB32, result, MSB16, sign);
6905 addSign (result, MSB24, sign);
6907 else if (shCount >= 8)
6911 shiftRLong (left, MSB16, result, sign);
6912 else if (shCount == 0)
6914 movLeft2Result (left, MSB16, result, LSB, 0);
6915 movLeft2Result (left, MSB24, result, MSB16, 0);
6916 movLeft2Result (left, MSB32, result, MSB24, sign);
6917 addSign (result, MSB32, sign);
6921 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6922 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6923 /* the last shift is signed */
6924 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6925 addSign (result, MSB32, sign);
6929 { /* 1 <= shCount <= 7 */
6932 shiftRLong (left, LSB, result, sign);
6934 shiftRLong (result, LSB, result, sign);
6938 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6939 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6940 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6945 /*-----------------------------------------------------------------*/
6946 /* genRightShiftLiteral - right shifting by known count */
6947 /*-----------------------------------------------------------------*/
6949 genRightShiftLiteral (operand * left,
6955 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6958 D(emitcode ("; genRightShiftLiteral",""));
6960 freeAsmop (right, NULL, ic, TRUE);
6962 aopOp (left, ic, FALSE);
6963 aopOp (result, ic, FALSE);
6966 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6970 size = getDataSize (left);
6971 /* test the LEFT size !!! */
6973 /* I suppose that the left size >= result size */
6976 size = getDataSize (result);
6978 movLeft2Result (left, size, result, size, 0);
6981 else if (shCount >= (size * 8))
6984 /* get sign in acc.7 */
6985 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6987 addSign (result, LSB, sign);
6994 genrshOne (result, left, shCount, sign);
6998 genrshTwo (result, left, shCount, sign);
7002 genrshFour (result, left, shCount, sign);
7008 freeAsmop (left, NULL, ic, TRUE);
7009 freeAsmop (result, NULL, ic, TRUE);
7012 /*-----------------------------------------------------------------*/
7013 /* genSignedRightShift - right shift of signed number */
7014 /*-----------------------------------------------------------------*/
7016 genSignedRightShift (iCode * ic)
7018 operand *right, *left, *result;
7021 symbol *tlbl, *tlbl1;
7023 D(emitcode ("; genSignedRightShift",""));
7025 /* we do it the hard way put the shift count in b
7026 and loop thru preserving the sign */
7028 right = IC_RIGHT (ic);
7029 left = IC_LEFT (ic);
7030 result = IC_RESULT (ic);
7032 aopOp (right, ic, FALSE);
7035 if (AOP_TYPE (right) == AOP_LIT)
7037 genRightShiftLiteral (left, right, result, ic, 1);
7040 /* shift count is unknown then we have to form
7041 a loop get the loop count in B : Note: we take
7042 only the lower order byte since shifting
7043 more that 32 bits make no sense anyway, ( the
7044 largest size of an object can be only 32 bits ) */
7046 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7047 emitcode ("inc", "b");
7048 freeAsmop (right, NULL, ic, TRUE);
7049 aopOp (left, ic, FALSE);
7050 aopOp (result, ic, FALSE);
7052 /* now move the left to the result if they are not the
7054 if (!sameRegs (AOP (left), AOP (result)) &&
7055 AOP_SIZE (result) > 1)
7058 size = AOP_SIZE (result);
7062 l = aopGet (AOP (left), offset, FALSE, TRUE);
7063 if (*l == '@' && IS_AOP_PREG (result))
7066 emitcode ("mov", "a,%s", l);
7067 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7070 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7075 /* mov the highest order bit to OVR */
7076 tlbl = newiTempLabel (NULL);
7077 tlbl1 = newiTempLabel (NULL);
7079 size = AOP_SIZE (result);
7081 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
7082 emitcode ("rlc", "a");
7083 emitcode ("mov", "ov,c");
7084 /* if it is only one byte then */
7087 l = aopGet (AOP (left), 0, FALSE, FALSE);
7089 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7090 emitcode ("", "%05d$:", tlbl->key + 100);
7091 emitcode ("mov", "c,ov");
7092 emitcode ("rrc", "a");
7093 emitcode ("", "%05d$:", tlbl1->key + 100);
7094 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7095 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7099 reAdjustPreg (AOP (result));
7100 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7101 emitcode ("", "%05d$:", tlbl->key + 100);
7102 emitcode ("mov", "c,ov");
7105 l = aopGet (AOP (result), offset, FALSE, FALSE);
7107 emitcode ("rrc", "a");
7108 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7110 reAdjustPreg (AOP (result));
7111 emitcode ("", "%05d$:", tlbl1->key + 100);
7112 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7115 freeAsmop (left, NULL, ic, TRUE);
7116 freeAsmop (result, NULL, ic, TRUE);
7119 /*-----------------------------------------------------------------*/
7120 /* genRightShift - generate code for right shifting */
7121 /*-----------------------------------------------------------------*/
7123 genRightShift (iCode * ic)
7125 operand *right, *left, *result;
7129 symbol *tlbl, *tlbl1;
7131 D(emitcode ("; genRightShift",""));
7133 /* if signed then we do it the hard way preserve the
7134 sign bit moving it inwards */
7135 retype = getSpec (operandType (IC_RESULT (ic)));
7137 if (!SPEC_USIGN (retype))
7139 genSignedRightShift (ic);
7143 /* signed & unsigned types are treated the same : i.e. the
7144 signed is NOT propagated inwards : quoting from the
7145 ANSI - standard : "for E1 >> E2, is equivalent to division
7146 by 2**E2 if unsigned or if it has a non-negative value,
7147 otherwise the result is implementation defined ", MY definition
7148 is that the sign does not get propagated */
7150 right = IC_RIGHT (ic);
7151 left = IC_LEFT (ic);
7152 result = IC_RESULT (ic);
7154 aopOp (right, ic, FALSE);
7156 /* if the shift count is known then do it
7157 as efficiently as possible */
7158 if (AOP_TYPE (right) == AOP_LIT)
7160 genRightShiftLiteral (left, right, result, ic, 0);
7164 /* shift count is unknown then we have to form
7165 a loop get the loop count in B : Note: we take
7166 only the lower order byte since shifting
7167 more that 32 bits make no sense anyway, ( the
7168 largest size of an object can be only 32 bits ) */
7170 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7171 emitcode ("inc", "b");
7172 freeAsmop (right, NULL, ic, TRUE);
7173 aopOp (left, ic, FALSE);
7174 aopOp (result, ic, FALSE);
7176 /* now move the left to the result if they are not the
7178 if (!sameRegs (AOP (left), AOP (result)) &&
7179 AOP_SIZE (result) > 1)
7182 size = AOP_SIZE (result);
7186 l = aopGet (AOP (left), offset, FALSE, TRUE);
7187 if (*l == '@' && IS_AOP_PREG (result))
7190 emitcode ("mov", "a,%s", l);
7191 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7194 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7199 tlbl = newiTempLabel (NULL);
7200 tlbl1 = newiTempLabel (NULL);
7201 size = AOP_SIZE (result);
7204 /* if it is only one byte then */
7207 l = aopGet (AOP (left), 0, FALSE, FALSE);
7209 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7210 emitcode ("", "%05d$:", tlbl->key + 100);
7212 emitcode ("rrc", "a");
7213 emitcode ("", "%05d$:", tlbl1->key + 100);
7214 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7215 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7219 reAdjustPreg (AOP (result));
7220 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7221 emitcode ("", "%05d$:", tlbl->key + 100);
7225 l = aopGet (AOP (result), offset, FALSE, FALSE);
7227 emitcode ("rrc", "a");
7228 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
7230 reAdjustPreg (AOP (result));
7232 emitcode ("", "%05d$:", tlbl1->key + 100);
7233 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7236 freeAsmop (left, NULL, ic, TRUE);
7237 freeAsmop (result, NULL, ic, TRUE);
7240 /*-----------------------------------------------------------------*/
7241 /* emitPtrByteGet - emits code to get a byte into A through a */
7242 /* pointer register (R0, R1, or DPTR). The */
7243 /* original value of A can be preserved in B. */
7244 /*-----------------------------------------------------------------*/
7246 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
7253 emitcode ("mov", "b,a");
7254 emitcode ("mov", "a,@%s", rname);
7259 emitcode ("mov", "b,a");
7260 emitcode ("movx", "a,@%s", rname);
7265 emitcode ("mov", "b,a");
7266 emitcode ("movx", "a,@dptr");
7271 emitcode ("mov", "b,a");
7272 emitcode ("clr", "a");
7273 emitcode ("movc", "a,@a+dptr");
7279 emitcode ("push", "b");
7280 emitcode ("push", "acc");
7282 emitcode ("lcall", "__gptrget");
7284 emitcode ("pop", "b");
7289 /*-----------------------------------------------------------------*/
7290 /* emitPtrByteSet - emits code to set a byte from src through a */
7291 /* pointer register (R0, R1, or DPTR). */
7292 /*-----------------------------------------------------------------*/
7294 emitPtrByteSet (char *rname, int p_type, char *src)
7303 emitcode ("mov", "@%s,a", rname);
7306 emitcode ("mov", "@%s,%s", rname, src);
7311 emitcode ("movx", "@%s,a", rname);
7316 emitcode ("movx", "@dptr,a");
7321 emitcode ("lcall", "__gptrput");
7326 /*-----------------------------------------------------------------*/
7327 /* genUnpackBits - generates code for unpacking bits */
7328 /*-----------------------------------------------------------------*/
7330 genUnpackBits (operand * result, char *rname, int ptype)
7332 int offset = 0; /* result byte offset */
7333 int rsize; /* result size */
7334 int rlen = 0; /* remaining bitfield length */
7335 sym_link *etype; /* bitfield type information */
7336 int blen; /* bitfield length */
7337 int bstr; /* bitfield starting bit within byte */
7339 D(emitcode ("; genUnpackBits",""));
7341 etype = getSpec (operandType (result));
7342 rsize = getSize (operandType (result));
7343 blen = SPEC_BLEN (etype);
7344 bstr = SPEC_BSTR (etype);
7346 /* If the bitfield length is less than a byte */
7349 emitPtrByteGet (rname, ptype, FALSE);
7351 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
7352 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7356 /* Bit field did not fit in a byte. Copy all
7357 but the partial byte at the end. */
7358 for (rlen=blen;rlen>=8;rlen-=8)
7360 emitPtrByteGet (rname, ptype, FALSE);
7361 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7363 emitcode ("inc", "%s", rname);
7366 /* Handle the partial byte at the end */
7369 emitPtrByteGet (rname, ptype, FALSE);
7370 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
7371 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7379 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
7384 /*-----------------------------------------------------------------*/
7385 /* genDataPointerGet - generates code when ptr offset is known */
7386 /*-----------------------------------------------------------------*/
7388 genDataPointerGet (operand * left,
7394 int size, offset = 0;
7396 D(emitcode ("; genDataPointerGet",""));
7398 aopOp (result, ic, TRUE);
7400 /* get the string representation of the name */
7401 l = aopGet (AOP (left), 0, FALSE, TRUE);
7402 size = AOP_SIZE (result);
7406 sprintf (buffer, "(%s + %d)", l + 1, offset);
7408 sprintf (buffer, "%s", l + 1);
7409 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
7412 freeAsmop (left, NULL, ic, TRUE);
7413 freeAsmop (result, NULL, ic, TRUE);
7416 /*-----------------------------------------------------------------*/
7417 /* genNearPointerGet - emitcode for near pointer fetch */
7418 /*-----------------------------------------------------------------*/
7420 genNearPointerGet (operand * left,
7428 sym_link *rtype, *retype;
7429 sym_link *ltype = operandType (left);
7432 D(emitcode ("; genNearPointerGet",""));
7434 rtype = operandType (result);
7435 retype = getSpec (rtype);
7437 aopOp (left, ic, FALSE);
7439 /* if left is rematerialisable and
7440 result is not bit variable type and
7441 the left is pointer to data space i.e
7442 lower 128 bytes of space */
7443 if (AOP_TYPE (left) == AOP_IMMD &&
7444 !IS_BITVAR (retype) &&
7445 DCL_TYPE (ltype) == POINTER)
7447 genDataPointerGet (left, result, ic);
7451 /* if the value is already in a pointer register
7452 then don't need anything more */
7453 if (!AOP_INPREG (AOP (left)))
7455 if (IS_AOP_PREG (left))
7457 // Aha, it is a pointer, just in disguise.
7458 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7461 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7462 __FILE__, __LINE__);
7467 emitcode ("mov", "a%s,%s", rname + 1, rname);
7468 rname++; // skip the '@'.
7473 /* otherwise get a free pointer register */
7475 preg = getFreePtr (ic, &aop, FALSE);
7476 emitcode ("mov", "%s,%s",
7478 aopGet (AOP (left), 0, FALSE, TRUE));
7483 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7485 //aopOp (result, ic, FALSE);
7486 aopOp (result, ic, result?TRUE:FALSE);
7488 /* if bitfield then unpack the bits */
7489 if (IS_BITVAR (retype))
7490 genUnpackBits (result, rname, POINTER);
7493 /* we have can just get the values */
7494 int size = AOP_SIZE (result);
7499 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7502 emitcode ("mov", "a,@%s", rname);
7503 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7507 sprintf (buffer, "@%s", rname);
7508 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
7512 emitcode ("inc", "%s", rname);
7516 /* now some housekeeping stuff */
7517 if (aop) /* we had to allocate for this iCode */
7519 if (pi) { /* post increment present */
7520 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
7522 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7526 /* we did not allocate which means left
7527 already in a pointer register, then
7528 if size > 0 && this could be used again
7529 we have to point it back to where it
7531 if ((AOP_SIZE (result) > 1 &&
7532 !OP_SYMBOL (left)->remat &&
7533 (OP_SYMBOL (left)->liveTo > ic->seq ||
7537 int size = AOP_SIZE (result) - 1;
7539 emitcode ("dec", "%s", rname);
7544 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
7545 freeAsmop (left, NULL, ic, TRUE);
7546 if (pi) pi->generated = 1;
7549 /*-----------------------------------------------------------------*/
7550 /* genPagedPointerGet - emitcode for paged pointer fetch */
7551 /*-----------------------------------------------------------------*/
7553 genPagedPointerGet (operand * left,
7561 sym_link *rtype, *retype;
7563 D(emitcode ("; genPagedPointerGet",""));
7565 rtype = operandType (result);
7566 retype = getSpec (rtype);
7568 aopOp (left, ic, FALSE);
7570 /* if the value is already in a pointer register
7571 then don't need anything more */
7572 if (!AOP_INPREG (AOP (left)))
7574 /* otherwise get a free pointer register */
7576 preg = getFreePtr (ic, &aop, FALSE);
7577 emitcode ("mov", "%s,%s",
7579 aopGet (AOP (left), 0, FALSE, TRUE));
7583 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7585 aopOp (result, ic, FALSE);
7587 /* if bitfield then unpack the bits */
7588 if (IS_BITVAR (retype))
7589 genUnpackBits (result, rname, PPOINTER);
7592 /* we have can just get the values */
7593 int size = AOP_SIZE (result);
7599 emitcode ("movx", "a,@%s", rname);
7600 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7605 emitcode ("inc", "%s", rname);
7609 /* now some housekeeping stuff */
7610 if (aop) /* we had to allocate for this iCode */
7612 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
7613 freeAsmop (NULL, aop, ic, TRUE);
7617 /* we did not allocate which means left
7618 already in a pointer register, then
7619 if size > 0 && this could be used again
7620 we have to point it back to where it
7622 if ((AOP_SIZE (result) > 1 &&
7623 !OP_SYMBOL (left)->remat &&
7624 (OP_SYMBOL (left)->liveTo > ic->seq ||
7628 int size = AOP_SIZE (result) - 1;
7630 emitcode ("dec", "%s", rname);
7635 freeAsmop (left, NULL, ic, TRUE);
7636 freeAsmop (result, NULL, ic, TRUE);
7637 if (pi) pi->generated = 1;
7641 /*--------------------------------------------------------------------*/
7642 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
7643 /*--------------------------------------------------------------------*/
7645 loadDptrFromOperand (operand *op, bool loadBToo)
7647 if (AOP_TYPE (op) != AOP_STR)
7649 /* if this is remateriazable */
7650 if (AOP_TYPE (op) == AOP_IMMD)
7652 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
7655 if (AOP(op)->aopu.aop_immd.from_cast_remat)
7656 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
7659 wassertl(FALSE, "need pointerCode");
7660 emitcode ("", "; mov b,???");
7661 /* genPointerGet and genPointerSet originally did different
7662 ** things for this case. Both seem wrong.
7663 ** from genPointerGet:
7664 ** emitcode ("mov", "b,#%d", pointerCode (retype));
7665 ** from genPointerSet:
7666 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7671 else if (AOP_TYPE (op) == AOP_DPTR)
7675 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7676 emitcode ("push", "acc");
7677 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
7678 emitcode ("push", "acc");
7679 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7680 emitcode ("pop", "dph");
7681 emitcode ("pop", "dpl");
7685 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
7686 emitcode ("push", "acc");
7687 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7688 emitcode ("pop", "dpl");
7692 { /* we need to get it byte by byte */
7693 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
7694 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
7696 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
7701 /*-----------------------------------------------------------------*/
7702 /* genFarPointerGet - gget value from far space */
7703 /*-----------------------------------------------------------------*/
7705 genFarPointerGet (operand * left,
7706 operand * result, iCode * ic, iCode * pi)
7709 sym_link *retype = getSpec (operandType (result));
7711 D(emitcode ("; genFarPointerGet",""));
7713 aopOp (left, ic, FALSE);
7714 loadDptrFromOperand (left, FALSE);
7716 /* so dptr now contains the address */
7717 aopOp (result, ic, FALSE);
7719 /* if bit then unpack */
7720 if (IS_BITVAR (retype))
7721 genUnpackBits (result, "dptr", FPOINTER);
7724 size = AOP_SIZE (result);
7729 emitcode ("movx", "a,@dptr");
7730 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7732 emitcode ("inc", "dptr");
7736 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7737 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7738 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7741 freeAsmop (left, NULL, ic, TRUE);
7742 freeAsmop (result, NULL, ic, TRUE);
7745 /*-----------------------------------------------------------------*/
7746 /* genCodePointerGet - gget value from code space */
7747 /*-----------------------------------------------------------------*/
7749 genCodePointerGet (operand * left,
7750 operand * result, iCode * ic, iCode *pi)
7753 sym_link *retype = getSpec (operandType (result));
7755 D(emitcode ("; genCodePointerGet",""));
7757 aopOp (left, ic, FALSE);
7758 loadDptrFromOperand (left, FALSE);
7760 /* so dptr now contains the address */
7761 aopOp (result, ic, FALSE);
7763 /* if bit then unpack */
7764 if (IS_BITVAR (retype))
7765 genUnpackBits (result, "dptr", CPOINTER);
7768 size = AOP_SIZE (result);
7775 emitcode ("clr", "a");
7776 emitcode ("movc", "a,@a+dptr");
7777 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7778 emitcode ("inc", "dptr");
7782 emitcode ("mov", "a,#0x%02x", offset);
7783 emitcode ("movc", "a,@a+dptr");
7784 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7789 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7790 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7791 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7794 freeAsmop (left, NULL, ic, TRUE);
7795 freeAsmop (result, NULL, ic, TRUE);
7798 /*-----------------------------------------------------------------*/
7799 /* genGenPointerGet - gget value from generic pointer space */
7800 /*-----------------------------------------------------------------*/
7802 genGenPointerGet (operand * left,
7803 operand * result, iCode * ic, iCode *pi)
7806 sym_link *retype = getSpec (operandType (result));
7808 D(emitcode ("; genGenPointerGet",""));
7810 aopOp (left, ic, FALSE);
7811 loadDptrFromOperand (left, TRUE);
7813 /* so dptr know contains the address */
7814 aopOp (result, ic, FALSE);
7816 /* if bit then unpack */
7817 if (IS_BITVAR (retype))
7818 genUnpackBits (result, "dptr", GPOINTER);
7821 size = AOP_SIZE (result);
7826 emitcode ("lcall", "__gptrget");
7827 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7829 emitcode ("inc", "dptr");
7833 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7834 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
7835 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
7838 freeAsmop (left, NULL, ic, TRUE);
7839 freeAsmop (result, NULL, ic, TRUE);
7842 /*-----------------------------------------------------------------*/
7843 /* genPointerGet - generate code for pointer get */
7844 /*-----------------------------------------------------------------*/
7846 genPointerGet (iCode * ic, iCode *pi)
7848 operand *left, *result;
7849 sym_link *type, *etype;
7852 D(emitcode ("; genPointerGet",""));
7854 left = IC_LEFT (ic);
7855 result = IC_RESULT (ic);
7857 /* depending on the type of pointer we need to
7858 move it to the correct pointer register */
7859 type = operandType (left);
7860 etype = getSpec (type);
7861 /* if left is of type of pointer then it is simple */
7862 if (IS_PTR (type) && !IS_FUNC (type->next))
7863 p_type = DCL_TYPE (type);
7866 /* we have to go by the storage class */
7867 p_type = PTR_TYPE (SPEC_OCLS (etype));
7870 /* special case when cast remat */
7871 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7872 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7873 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7874 type = operandType (left);
7875 p_type = DCL_TYPE (type);
7877 /* now that we have the pointer type we assign
7878 the pointer values */
7884 genNearPointerGet (left, result, ic, pi);
7888 genPagedPointerGet (left, result, ic, pi);
7892 genFarPointerGet (left, result, ic, pi);
7896 genCodePointerGet (left, result, ic, pi);
7900 genGenPointerGet (left, result, ic, pi);
7908 /*-----------------------------------------------------------------*/
7909 /* genPackBits - generates code for packed bit storage */
7910 /*-----------------------------------------------------------------*/
7912 genPackBits (sym_link * etype,
7914 char *rname, int p_type)
7916 int offset = 0; /* source byte offset */
7917 int rlen = 0; /* remaining bitfield length */
7918 int blen; /* bitfield length */
7919 int bstr; /* bitfield starting bit within byte */
7920 int litval; /* source literal value (if AOP_LIT) */
7921 unsigned char mask; /* bitmask within current byte */
7923 D(emitcode ("; genPackBits",""));
7925 blen = SPEC_BLEN (etype);
7926 bstr = SPEC_BSTR (etype);
7928 /* If the bitfield length is less than a byte */
7931 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7932 (unsigned char) (0xFF >> (8 - bstr)));
7934 if (AOP_TYPE (right) == AOP_LIT)
7936 /* Case with a bitfield length <8 and literal source
7938 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7940 litval &= (~mask) & 0xff;
7941 emitPtrByteGet (rname, p_type, FALSE);
7942 if ((mask|litval)!=0xff)
7943 emitcode ("anl","a,#0x%02x", mask);
7945 emitcode ("orl","a,#0x%02x", litval);
7949 if ((blen==1) && (p_type!=GPOINTER))
7951 /* Case with a bitfield length == 1 and no generic pointer
7953 if (AOP_TYPE (right) == AOP_CRY)
7954 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
7957 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7958 emitcode ("rrc","a");
7960 emitPtrByteGet (rname, p_type, FALSE);
7961 emitcode ("mov","acc.%d,c",bstr);
7965 /* Case with a bitfield length < 8 and arbitrary source
7967 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
7968 /* shift and mask source value */
7970 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
7972 /* transfer A to B and get next byte */
7973 emitPtrByteGet (rname, p_type, TRUE);
7975 emitcode ("anl", "a,#0x%02x", mask);
7976 emitcode ("orl", "a,b");
7977 if (p_type == GPOINTER)
7978 emitcode ("pop", "b");
7982 emitPtrByteSet (rname, p_type, "a");
7986 /* Bit length is greater than 7 bits. In this case, copy */
7987 /* all except the partial byte at the end */
7988 for (rlen=blen;rlen>=8;rlen-=8)
7990 emitPtrByteSet (rname, p_type,
7991 aopGet (AOP (right), offset++, FALSE, TRUE) );
7993 emitcode ("inc", "%s", rname);
7996 /* If there was a partial byte at the end */
7999 mask = (((unsigned char) -1 << rlen) & 0xff);
8001 if (AOP_TYPE (right) == AOP_LIT)
8003 /* Case with partial byte and literal source
8005 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8006 litval >>= (blen-rlen);
8007 litval &= (~mask) & 0xff;
8008 emitPtrByteGet (rname, p_type, FALSE);
8009 if ((mask|litval)!=0xff)
8010 emitcode ("anl","a,#0x%02x", mask);
8012 emitcode ("orl","a,#0x%02x", litval);
8016 /* Case with partial byte and arbitrary source
8018 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
8019 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
8021 /* transfer A to B and get next byte */
8022 emitPtrByteGet (rname, p_type, TRUE);
8024 emitcode ("anl", "a,#0x%02x", mask);
8025 emitcode ("orl", "a,b");
8026 if (p_type == GPOINTER)
8027 emitcode ("pop", "b");
8029 emitPtrByteSet (rname, p_type, "a");
8035 /*-----------------------------------------------------------------*/
8036 /* genDataPointerSet - remat pointer to data space */
8037 /*-----------------------------------------------------------------*/
8039 genDataPointerSet (operand * right,
8043 int size, offset = 0;
8044 char *l, buffer[256];
8046 D(emitcode ("; genDataPointerSet",""));
8048 aopOp (right, ic, FALSE);
8050 l = aopGet (AOP (result), 0, FALSE, TRUE);
8051 size = AOP_SIZE (right);
8055 sprintf (buffer, "(%s + %d)", l + 1, offset);
8057 sprintf (buffer, "%s", l + 1);
8058 emitcode ("mov", "%s,%s", buffer,
8059 aopGet (AOP (right), offset++, FALSE, FALSE));
8062 freeAsmop (right, NULL, ic, TRUE);
8063 freeAsmop (result, NULL, ic, TRUE);
8066 /*-----------------------------------------------------------------*/
8067 /* genNearPointerSet - emitcode for near pointer put */
8068 /*-----------------------------------------------------------------*/
8070 genNearPointerSet (operand * right,
8078 sym_link *retype, *letype;
8079 sym_link *ptype = operandType (result);
8081 D(emitcode ("; genNearPointerSet",""));
8083 retype = getSpec (operandType (right));
8084 letype = getSpec (ptype);
8085 aopOp (result, ic, FALSE);
8087 /* if the result is rematerializable &
8088 in data space & not a bit variable */
8089 if (AOP_TYPE (result) == AOP_IMMD &&
8090 DCL_TYPE (ptype) == POINTER &&
8091 !IS_BITVAR (retype) &&
8092 !IS_BITVAR (letype))
8094 genDataPointerSet (right, result, ic);
8098 /* if the value is already in a pointer register
8099 then don't need anything more */
8100 if (!AOP_INPREG (AOP (result)))
8103 //AOP_TYPE (result) == AOP_STK
8107 // Aha, it is a pointer, just in disguise.
8108 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8111 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8112 __FILE__, __LINE__);
8117 emitcode ("mov", "a%s,%s", rname + 1, rname);
8118 rname++; // skip the '@'.
8123 /* otherwise get a free pointer register */
8125 preg = getFreePtr (ic, &aop, FALSE);
8126 emitcode ("mov", "%s,%s",
8128 aopGet (AOP (result), 0, FALSE, TRUE));
8134 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8137 aopOp (right, ic, FALSE);
8139 /* if bitfield then unpack the bits */
8140 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8141 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
8144 /* we have can just get the values */
8145 int size = AOP_SIZE (right);
8150 l = aopGet (AOP (right), offset, FALSE, TRUE);
8154 emitcode ("mov", "@%s,a", rname);
8157 emitcode ("mov", "@%s,%s", rname, l);
8159 emitcode ("inc", "%s", rname);
8164 /* now some housekeeping stuff */
8165 if (aop) /* we had to allocate for this iCode */
8168 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8169 freeAsmop (NULL, aop, ic, TRUE);
8173 /* we did not allocate which means left
8174 already in a pointer register, then
8175 if size > 0 && this could be used again
8176 we have to point it back to where it
8178 if ((AOP_SIZE (right) > 1 &&
8179 !OP_SYMBOL (result)->remat &&
8180 (OP_SYMBOL (result)->liveTo > ic->seq ||
8184 int size = AOP_SIZE (right) - 1;
8186 emitcode ("dec", "%s", rname);
8191 if (pi) pi->generated = 1;
8192 freeAsmop (result, NULL, ic, TRUE);
8193 freeAsmop (right, NULL, ic, TRUE);
8196 /*-----------------------------------------------------------------*/
8197 /* genPagedPointerSet - emitcode for Paged pointer put */
8198 /*-----------------------------------------------------------------*/
8200 genPagedPointerSet (operand * right,
8208 sym_link *retype, *letype;
8210 D(emitcode ("; genPagedPointerSet",""));
8212 retype = getSpec (operandType (right));
8213 letype = getSpec (operandType (result));
8215 aopOp (result, ic, FALSE);
8217 /* if the value is already in a pointer register
8218 then don't need anything more */
8219 if (!AOP_INPREG (AOP (result)))
8221 /* otherwise get a free pointer register */
8223 preg = getFreePtr (ic, &aop, FALSE);
8224 emitcode ("mov", "%s,%s",
8226 aopGet (AOP (result), 0, FALSE, TRUE));
8230 rname = aopGet (AOP (result), 0, FALSE, FALSE);
8232 aopOp (right, ic, FALSE);
8234 /* if bitfield then unpack the bits */
8235 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8236 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
8239 /* we have can just get the values */
8240 int size = AOP_SIZE (right);
8245 l = aopGet (AOP (right), offset, FALSE, TRUE);
8248 emitcode ("movx", "@%s,a", rname);
8251 emitcode ("inc", "%s", rname);
8257 /* now some housekeeping stuff */
8258 if (aop) /* we had to allocate for this iCode */
8261 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
8262 freeAsmop (NULL, aop, ic, TRUE);
8266 /* we did not allocate which means left
8267 already in a pointer register, then
8268 if size > 0 && this could be used again
8269 we have to point it back to where it
8271 if (AOP_SIZE (right) > 1 &&
8272 !OP_SYMBOL (result)->remat &&
8273 (OP_SYMBOL (result)->liveTo > ic->seq ||
8276 int size = AOP_SIZE (right) - 1;
8278 emitcode ("dec", "%s", rname);
8283 if (pi) pi->generated = 1;
8284 freeAsmop (result, NULL, ic, TRUE);
8285 freeAsmop (right, NULL, ic, TRUE);
8290 /*-----------------------------------------------------------------*/
8291 /* genFarPointerSet - set value from far space */
8292 /*-----------------------------------------------------------------*/
8294 genFarPointerSet (operand * right,
8295 operand * result, iCode * ic, iCode * pi)
8298 sym_link *retype = getSpec (operandType (right));
8299 sym_link *letype = getSpec (operandType (result));
8301 D(emitcode ("; genFarPointerSet",""));
8303 aopOp (result, ic, FALSE);
8304 loadDptrFromOperand (result, FALSE);
8306 /* so dptr know contains the address */
8307 aopOp (right, ic, FALSE);
8309 /* if bit then unpack */
8310 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8311 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
8314 size = AOP_SIZE (right);
8319 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8321 emitcode ("movx", "@dptr,a");
8323 emitcode ("inc", "dptr");
8326 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8327 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8328 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8331 freeAsmop (result, NULL, ic, TRUE);
8332 freeAsmop (right, NULL, ic, TRUE);
8335 /*-----------------------------------------------------------------*/
8336 /* genGenPointerSet - set value from generic pointer space */
8337 /*-----------------------------------------------------------------*/
8339 genGenPointerSet (operand * right,
8340 operand * result, iCode * ic, iCode * pi)
8343 sym_link *retype = getSpec (operandType (right));
8344 sym_link *letype = getSpec (operandType (result));
8346 D(emitcode ("; genGenPointerSet",""));
8348 aopOp (result, ic, FALSE);
8349 loadDptrFromOperand (result, TRUE);
8351 /* so dptr know contains the address */
8352 aopOp (right, ic, FALSE);
8354 /* if bit then unpack */
8355 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8356 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8359 size = AOP_SIZE (right);
8364 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8366 emitcode ("lcall", "__gptrput");
8368 emitcode ("inc", "dptr");
8372 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8373 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
8374 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
8377 freeAsmop (result, NULL, ic, TRUE);
8378 freeAsmop (right, NULL, ic, TRUE);
8381 /*-----------------------------------------------------------------*/
8382 /* genPointerSet - stores the value into a pointer location */
8383 /*-----------------------------------------------------------------*/
8385 genPointerSet (iCode * ic, iCode *pi)
8387 operand *right, *result;
8388 sym_link *type, *etype;
8391 D(emitcode ("; genPointerSet",""));
8393 right = IC_RIGHT (ic);
8394 result = IC_RESULT (ic);
8396 /* depending on the type of pointer we need to
8397 move it to the correct pointer register */
8398 type = operandType (result);
8399 etype = getSpec (type);
8400 /* if left is of type of pointer then it is simple */
8401 if (IS_PTR (type) && !IS_FUNC (type->next))
8403 p_type = DCL_TYPE (type);
8407 /* we have to go by the storage class */
8408 p_type = PTR_TYPE (SPEC_OCLS (etype));
8411 /* special case when cast remat */
8412 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8413 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8414 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8415 type = operandType (result);
8416 p_type = DCL_TYPE (type);
8418 /* now that we have the pointer type we assign
8419 the pointer values */
8425 genNearPointerSet (right, result, ic, pi);
8429 genPagedPointerSet (right, result, ic, pi);
8433 genFarPointerSet (right, result, ic, pi);
8437 genGenPointerSet (right, result, ic, pi);
8441 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8442 "genPointerSet: illegal pointer type");
8447 /*-----------------------------------------------------------------*/
8448 /* genIfx - generate code for Ifx statement */
8449 /*-----------------------------------------------------------------*/
8451 genIfx (iCode * ic, iCode * popIc)
8453 operand *cond = IC_COND (ic);
8456 D(emitcode ("; genIfx",""));
8458 aopOp (cond, ic, FALSE);
8460 /* get the value into acc */
8461 if (AOP_TYPE (cond) != AOP_CRY)
8465 /* the result is now in the accumulator */
8466 freeAsmop (cond, NULL, ic, TRUE);
8468 /* if there was something to be popped then do it */
8472 /* if the condition is a bit variable */
8473 if (isbit && IS_ITEMP (cond) &&
8475 genIfxJump (ic, SPIL_LOC (cond)->rname);
8476 else if (isbit && !IS_ITEMP (cond))
8477 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8479 genIfxJump (ic, "a");
8484 /*-----------------------------------------------------------------*/
8485 /* genAddrOf - generates code for address of */
8486 /*-----------------------------------------------------------------*/
8488 genAddrOf (iCode * ic)
8490 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8493 D(emitcode ("; genAddrOf",""));
8495 aopOp (IC_RESULT (ic), ic, FALSE);
8497 /* if the operand is on the stack then we
8498 need to get the stack offset of this
8502 /* if it has an offset then we need to compute
8506 emitcode ("mov", "a,_bp");
8507 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8508 ((char) (sym->stack - _G.nRegsSaved)) :
8509 ((char) sym->stack)) & 0xff);
8510 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8514 /* we can just move _bp */
8515 aopPut (AOP (IC_RESULT (ic)), "_bp", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8517 /* fill the result with zero */
8518 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8523 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8529 /* object not on stack then we need the name */
8530 size = AOP_SIZE (IC_RESULT (ic));
8535 char s[SDCC_NAME_MAX];
8537 sprintf (s, "#(%s >> %d)",
8541 sprintf (s, "#%s", sym->rname);
8542 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
8546 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8550 /*-----------------------------------------------------------------*/
8551 /* genFarFarAssign - assignment when both are in far space */
8552 /*-----------------------------------------------------------------*/
8554 genFarFarAssign (operand * result, operand * right, iCode * ic)
8556 int size = AOP_SIZE (right);
8560 D(emitcode ("; genFarFarAssign",""));
8562 /* first push the right side on to the stack */
8565 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8567 emitcode ("push", "acc");
8570 freeAsmop (right, NULL, ic, FALSE);
8571 /* now assign DPTR to result */
8572 aopOp (result, ic, FALSE);
8573 size = AOP_SIZE (result);
8576 emitcode ("pop", "acc");
8577 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
8579 freeAsmop (result, NULL, ic, FALSE);
8583 /*-----------------------------------------------------------------*/
8584 /* genAssign - generate code for assignment */
8585 /*-----------------------------------------------------------------*/
8587 genAssign (iCode * ic)
8589 operand *result, *right;
8591 unsigned long lit = 0L;
8593 D(emitcode("; genAssign",""));
8595 result = IC_RESULT (ic);
8596 right = IC_RIGHT (ic);
8598 /* if they are the same */
8599 if (operandsEqu (result, right) &&
8600 !isOperandVolatile (result, FALSE) &&
8601 !isOperandVolatile (right, FALSE))
8604 aopOp (right, ic, FALSE);
8606 /* special case both in far space */
8607 if (AOP_TYPE (right) == AOP_DPTR &&
8608 IS_TRUE_SYMOP (result) &&
8609 isOperandInFarSpace (result))
8612 genFarFarAssign (result, right, ic);
8616 aopOp (result, ic, TRUE);
8618 /* if they are the same registers */
8619 if (sameRegs (AOP (right), AOP (result)) &&
8620 !isOperandVolatile (result, FALSE) &&
8621 !isOperandVolatile (right, FALSE))
8624 /* if the result is a bit */
8625 if (AOP_TYPE (result) == AOP_CRY)
8628 /* if the right size is a literal then
8629 we know what the value is */
8630 if (AOP_TYPE (right) == AOP_LIT)
8632 if (((int) operandLitValue (right)))
8633 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8635 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8639 /* the right is also a bit variable */
8640 if (AOP_TYPE (right) == AOP_CRY)
8642 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8643 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8649 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8653 /* bit variables done */
8655 size = AOP_SIZE (result);
8657 if (AOP_TYPE (right) == AOP_LIT)
8658 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8660 (AOP_TYPE (result) != AOP_REG) &&
8661 (AOP_TYPE (right) == AOP_LIT) &&
8662 !IS_FLOAT (operandType (right)) &&
8665 emitcode ("clr", "a");
8668 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8669 aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
8671 aopPut (AOP (result),
8672 aopGet (AOP (right), size, FALSE, FALSE),
8674 isOperandVolatile (result, FALSE));
8681 aopPut (AOP (result),
8682 aopGet (AOP (right), offset, FALSE, FALSE),
8684 isOperandVolatile (result, FALSE));
8690 freeAsmop (right, NULL, ic, TRUE);
8691 freeAsmop (result, NULL, ic, TRUE);
8694 /*-----------------------------------------------------------------*/
8695 /* genJumpTab - genrates code for jump table */
8696 /*-----------------------------------------------------------------*/
8698 genJumpTab (iCode * ic)
8703 D(emitcode ("; genJumpTab",""));
8705 aopOp (IC_JTCOND (ic), ic, FALSE);
8706 /* get the condition into accumulator */
8707 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8709 /* multiply by three */
8710 emitcode ("add", "a,acc");
8711 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8712 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8714 jtab = newiTempLabel (NULL);
8715 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8716 emitcode ("jmp", "@a+dptr");
8717 emitcode ("", "%05d$:", jtab->key + 100);
8718 /* now generate the jump labels */
8719 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8720 jtab = setNextItem (IC_JTLABELS (ic)))
8721 emitcode ("ljmp", "%05d$", jtab->key + 100);
8725 /*-----------------------------------------------------------------*/
8726 /* genCast - gen code for casting */
8727 /*-----------------------------------------------------------------*/
8729 genCast (iCode * ic)
8731 operand *result = IC_RESULT (ic);
8732 sym_link *ctype = operandType (IC_LEFT (ic));
8733 sym_link *rtype = operandType (IC_RIGHT (ic));
8734 operand *right = IC_RIGHT (ic);
8737 D(emitcode("; genCast",""));
8739 /* if they are equivalent then do nothing */
8740 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8743 aopOp (right, ic, FALSE);
8744 aopOp (result, ic, FALSE);
8746 /* if the result is a bit (and not a bitfield) */
8747 // if (AOP_TYPE (result) == AOP_CRY)
8748 if (IS_BITVAR (OP_SYMBOL (result)->type)
8749 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
8751 /* if the right size is a literal then
8752 we know what the value is */
8753 if (AOP_TYPE (right) == AOP_LIT)
8755 if (((int) operandLitValue (right)))
8756 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
8758 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
8763 /* the right is also a bit variable */
8764 if (AOP_TYPE (right) == AOP_CRY)
8766 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8767 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
8773 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8778 /* if they are the same size : or less */
8779 if (AOP_SIZE (result) <= AOP_SIZE (right))
8782 /* if they are in the same place */
8783 if (sameRegs (AOP (right), AOP (result)))
8786 /* if they in different places then copy */
8787 size = AOP_SIZE (result);
8791 aopPut (AOP (result),
8792 aopGet (AOP (right), offset, FALSE, FALSE),
8794 isOperandVolatile (result, FALSE));
8801 /* if the result is of type pointer */
8806 sym_link *type = operandType (right);
8807 sym_link *etype = getSpec (type);
8809 /* pointer to generic pointer */
8810 if (IS_GENPTR (ctype))
8813 p_type = DCL_TYPE (type);
8816 if (SPEC_SCLS(etype)==S_REGISTER) {
8817 // let's assume it is a generic pointer
8820 /* we have to go by the storage class */
8821 p_type = PTR_TYPE (SPEC_OCLS (etype));
8825 /* the first two bytes are known */
8826 size = GPTRSIZE - 1;
8830 aopPut (AOP (result),
8831 aopGet (AOP (right), offset, FALSE, FALSE),
8833 isOperandVolatile (result, FALSE));
8836 /* the last byte depending on type */
8838 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8843 // pointerTypeToGPByte will have bitched.
8847 sprintf(gpValStr, "#0x%d", gpVal);
8848 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
8853 /* just copy the pointers */
8854 size = AOP_SIZE (result);
8858 aopPut (AOP (result),
8859 aopGet (AOP (right), offset, FALSE, FALSE),
8861 isOperandVolatile (result, FALSE));
8867 /* so we now know that the size of destination is greater
8868 than the size of the source */
8869 /* we move to result for the size of source */
8870 size = AOP_SIZE (right);
8874 aopPut (AOP (result),
8875 aopGet (AOP (right), offset, FALSE, FALSE),
8877 isOperandVolatile (result, FALSE));
8881 /* now depending on the sign of the source && destination */
8882 size = AOP_SIZE (result) - AOP_SIZE (right);
8883 /* if unsigned or not an integral type */
8884 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8887 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8891 /* we need to extend the sign :{ */
8892 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8895 emitcode ("rlc", "a");
8896 emitcode ("subb", "a,acc");
8898 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8901 /* we are done hurray !!!! */
8904 freeAsmop (right, NULL, ic, TRUE);
8905 freeAsmop (result, NULL, ic, TRUE);
8909 /*-----------------------------------------------------------------*/
8910 /* genDjnz - generate decrement & jump if not zero instrucion */
8911 /*-----------------------------------------------------------------*/
8913 genDjnz (iCode * ic, iCode * ifx)
8919 D(emitcode ("; genDjnz",""));
8921 /* if the if condition has a false label
8922 then we cannot save */
8926 /* if the minus is not of the form
8928 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8929 !IS_OP_LITERAL (IC_RIGHT (ic)))
8932 if (operandLitValue (IC_RIGHT (ic)) != 1)
8935 /* if the size of this greater than one then no
8937 if (getSize (operandType (IC_RESULT (ic))) > 1)
8940 /* otherwise we can save BIG */
8941 lbl = newiTempLabel (NULL);
8942 lbl1 = newiTempLabel (NULL);
8944 aopOp (IC_RESULT (ic), ic, FALSE);
8946 if (AOP_NEEDSACC(IC_RESULT(ic)))
8948 /* If the result is accessed indirectly via
8949 * the accumulator, we must explicitly write
8950 * it back after the decrement.
8952 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8954 if (strcmp(rByte, "a"))
8956 /* Something is hopelessly wrong */
8957 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8958 __FILE__, __LINE__);
8959 /* We can just give up; the generated code will be inefficient,
8962 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8965 emitcode ("dec", "%s", rByte);
8966 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
8967 emitcode ("jnz", "%05d$", lbl->key + 100);
8969 else if (IS_AOP_PREG (IC_RESULT (ic)))
8971 emitcode ("dec", "%s",
8972 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8973 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8974 emitcode ("jnz", "%05d$", lbl->key + 100);
8978 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8981 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8982 emitcode ("", "%05d$:", lbl->key + 100);
8983 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8984 emitcode ("", "%05d$:", lbl1->key + 100);
8986 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8991 /*-----------------------------------------------------------------*/
8992 /* genReceive - generate code for a receive iCode */
8993 /*-----------------------------------------------------------------*/
8995 genReceive (iCode * ic)
8997 int size = getSize (operandType (IC_RESULT (ic)));
8999 D(emitcode ("; genReceive",""));
9001 if (ic->argreg == 1) { /* first parameter */
9002 if (isOperandInFarSpace (IC_RESULT (ic)) &&
9003 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
9004 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
9006 offset = fReturnSizeMCS51 - size;
9008 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
9009 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
9012 aopOp (IC_RESULT (ic), ic, FALSE);
9013 size = AOP_SIZE (IC_RESULT (ic));
9016 emitcode ("pop", "acc");
9017 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9022 aopOp (IC_RESULT (ic), ic, FALSE);
9024 assignResultValue (IC_RESULT (ic));
9026 } else { /* second receive onwards */
9028 aopOp (IC_RESULT (ic), ic, FALSE);
9029 rb1off = ic->argreg;
9031 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9034 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9037 /*-----------------------------------------------------------------*/
9038 /* genDummyRead - generate code for dummy read of volatiles */
9039 /*-----------------------------------------------------------------*/
9041 genDummyRead (iCode * ic)
9046 D(emitcode("; genDummyRead",""));
9048 right = IC_RIGHT (ic);
9050 aopOp (right, ic, FALSE);
9052 /* if the result is a bit */
9053 if (AOP_TYPE (right) == AOP_CRY)
9055 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9059 /* bit variables done */
9061 size = AOP_SIZE (right);
9065 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
9070 freeAsmop (right, NULL, ic, TRUE);
9073 /*-----------------------------------------------------------------*/
9074 /* genCritical - generate code for start of a critical sequence */
9075 /*-----------------------------------------------------------------*/
9077 genCritical (iCode *ic)
9079 symbol *tlbl = newiTempLabel (NULL);
9081 D(emitcode("; genCritical",""));
9084 aopOp (IC_RESULT (ic), ic, TRUE);
9086 emitcode ("setb", "c");
9087 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
9088 emitcode ("clr", "c");
9089 emitcode ("", "%05d$:", (tlbl->key + 100));
9092 outBitC (IC_RESULT (ic)); /* save old ea in an operand */
9094 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
9097 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9100 /*-----------------------------------------------------------------*/
9101 /* genEndCritical - generate code for end of a critical sequence */
9102 /*-----------------------------------------------------------------*/
9104 genEndCritical (iCode *ic)
9106 D(emitcode("; genEndCritical",""));
9110 aopOp (IC_RIGHT (ic), ic, FALSE);
9111 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
9113 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
9114 emitcode ("mov", "ea,c");
9118 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
9119 emitcode ("rrc", "a");
9120 emitcode ("mov", "ea,c");
9122 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
9126 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
9127 emitcode ("mov", "ea,c");
9132 /*-----------------------------------------------------------------*/
9133 /* gen51Code - generate code for 8051 based controllers */
9134 /*-----------------------------------------------------------------*/
9136 gen51Code (iCode * lic)
9141 lineHead = lineCurr = NULL;
9143 /* print the allocation information */
9144 if (allocInfo && currFunc)
9145 printAllocInfo (currFunc, codeOutFile);
9146 /* if debug information required */
9147 if (options.debug && currFunc)
9149 debugFile->writeFunction(currFunc);
9151 if (IS_STATIC (currFunc->etype))
9152 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
9154 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
9157 /* stack pointer name */
9158 if (options.useXstack)
9164 for (ic = lic; ic; ic = ic->next)
9166 _G.current_iCode = ic;
9168 if (ic->lineno && cln != ic->lineno)
9173 emitcode ("", "C$%s$%d$%d$%d ==.",
9174 FileBaseName (ic->filename), ic->lineno,
9175 ic->level, ic->block);
9178 if (!options.noCcodeInAsm) {
9179 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
9180 printCLine(ic->filename, ic->lineno));
9184 if (options.iCodeInAsm) {
9188 for (i=0; i<8; i++) {
9189 sprintf (®sInUse[i],
9190 "%c", ic->riu & (1<<i) ? i+'0' : '-');
9193 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
9195 /* if the result is marked as
9196 spilt and rematerializable or code for
9197 this has already been generated then
9199 if (resultRemat (ic) || ic->generated)
9202 /* depending on the operation */
9222 /* IPOP happens only when trying to restore a
9223 spilt live range, if there is an ifx statement
9224 following this pop then the if statement might
9225 be using some of the registers being popped which
9226 would destory the contents of the register so
9227 we need to check for this condition and handle it */
9229 ic->next->op == IFX &&
9230 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
9231 genIfx (ic->next, ic);
9249 genEndFunction (ic);
9269 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
9286 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
9290 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
9297 /* note these two are xlated by algebraic equivalence
9298 during parsing SDCC.y */
9299 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9300 "got '>=' or '<=' shouldn't have come here");
9304 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
9316 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
9320 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
9324 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
9351 case GET_VALUE_AT_ADDRESS:
9352 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
9356 if (POINTER_SET (ic))
9357 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
9383 addSet (&_G.sendSet, ic);
9386 case DUMMY_READ_VOLATILE:
9395 genEndCritical (ic);
9407 _G.current_iCode = NULL;
9409 /* now we are ready to call the
9410 peep hole optimizer */
9411 if (!options.nopeep)
9412 peepHole (&lineHead);
9414 /* now do the actual printing */
9415 printLine (lineHead, codeOutFile);