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;
67 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
69 #define R0INB _G.bu.bs.r0InB
70 #define R1INB _G.bu.bs.r1InB
71 #define OPINB _G.bu.bs.OpInB
72 #define BINUSE _G.bu.BInUse
82 short r0InB : 2;//2 so we can see it overflow
83 short r1InB : 2;//2 so we can see it overflow
84 short OpInB : 2;//2 so we can see it overflow
98 static char *rb1regs[] = {
99 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
102 extern int mcs51_ptrRegReq;
103 extern int mcs51_nRegs;
104 extern FILE *codeOutFile;
105 static void saveRBank (int, iCode *, bool);
107 #define RESULTONSTACK(x) \
108 (IC_RESULT(x) && IC_RESULT(x)->aop && \
109 IC_RESULT(x)->aop->type == AOP_STK )
111 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
112 #define CLRC emitcode("clr","c")
113 #define SETC emitcode("setb","c")
115 static lineNode *lineHead = NULL;
116 static lineNode *lineCurr = NULL;
118 static unsigned char SLMask[] =
119 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
120 0xE0, 0xC0, 0x80, 0x00};
121 static unsigned char SRMask[] =
122 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
123 0x07, 0x03, 0x01, 0x00};
130 /*-----------------------------------------------------------------*/
131 /* emitcode - writes the code into a file : for now it is simple */
132 /*-----------------------------------------------------------------*/
134 emitcode (char *inst, const char *fmt,...)
137 char lb[INITIAL_INLINEASM];
145 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
147 SNPRINTF (lb, sizeof(lb), "%s", inst);
148 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
151 tvsprintf (lb, sizeof(lb), fmt, ap);
153 while (isspace (*lbp))
157 lineCurr = (lineCurr ?
158 connectLine (lineCurr, newLineNode (lb)) :
159 (lineHead = newLineNode (lb)));
160 lineCurr->isInline = _G.inLine;
161 lineCurr->isDebug = _G.debugLine;
162 lineCurr->ic = _G.current_iCode;
163 lineCurr->isComment = (*lbp==';');
167 /*-----------------------------------------------------------------*/
168 /* mcs51_emitDebuggerSymbol - associate the current code location */
169 /* with a debugger symbol */
170 /*-----------------------------------------------------------------*/
172 mcs51_emitDebuggerSymbol (char * debugSym)
175 emitcode ("", "%s ==.", debugSym);
179 /*-----------------------------------------------------------------*/
180 /* mova - moves specified value into accumulator */
181 /*-----------------------------------------------------------------*/
185 /* do some early peephole optimization */
186 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
189 emitcode("mov","a,%s", x);
192 /*-----------------------------------------------------------------*/
193 /* pushB - saves register B if necessary */
194 /*-----------------------------------------------------------------*/
198 bool pushedB = FALSE;
202 emitcode ("push", "b");
203 // printf("B was in use !\n");
213 /*-----------------------------------------------------------------*/
214 /* popB - restores value of register B if necessary */
215 /*-----------------------------------------------------------------*/
221 emitcode ("pop", "b");
229 /*-----------------------------------------------------------------*/
230 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
231 /*-----------------------------------------------------------------*/
233 getFreePtr (iCode * ic, asmop ** aopp, bool result)
238 /* the logic: if r0 & r1 used in the instruction
239 then we are in trouble otherwise */
241 /* first check if r0 & r1 are used by this
242 instruction, in which case we are in trouble */
243 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
244 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
249 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
250 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
252 /* if no usage of r0 then return it */
255 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
256 (*aopp)->type = AOP_R0;
258 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
261 /* if no usage of r1 then return it */
264 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
265 (*aopp)->type = AOP_R1;
267 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
270 /* now we know they both have usage */
271 /* if r0 not used in this instruction */
274 /* push it if not already pushed */
277 emitcode ("mov", "b,%s",
278 mcs51_regWithIdx (R0_IDX)->dname);
281 else if (!_G.r0Pushed)
283 emitcode ("push", "%s",
284 mcs51_regWithIdx (R0_IDX)->dname);
288 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
289 (*aopp)->type = AOP_R0;
291 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
294 /* if r1 not used then */
298 /* push it if not already pushed */
301 emitcode ("mov", "b,%s",
302 mcs51_regWithIdx (R1_IDX)->dname);
305 else if (!_G.r1Pushed)
307 emitcode ("push", "%s",
308 mcs51_regWithIdx (R1_IDX)->dname);
312 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
313 (*aopp)->type = AOP_R1;
314 return mcs51_regWithIdx (R1_IDX);
317 /* I said end of world, but not quite end of world yet */
319 /* we can push it on the stack */
320 (*aopp)->type = AOP_STK;
323 /* in the case that result AND left AND right needs a pointer reg
324 we can safely use the result's */
325 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
326 (*aopp)->type = AOP_R0;
327 return mcs51_regWithIdx (R0_IDX);
329 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
330 (*aopp)->type = AOP_R1;
331 return mcs51_regWithIdx (R1_IDX);
335 /* now this is REALLY the end of the world */
336 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
337 "getFreePtr should never reach here");
342 /*-----------------------------------------------------------------*/
343 /* getTempRegs - initialize an array of pointers to GPR registers */
344 /* that are not in use. Returns 1 if the requested */
345 /* number of registers were available, 0 otherwise. */
346 /*-----------------------------------------------------------------*/
348 getTempRegs(regs **tempRegs, int size, iCode *ic)
355 ic = _G.current_iCode;
361 freeRegs = newBitVect(8);
362 bitVectSetBit (freeRegs, R2_IDX);
363 bitVectSetBit (freeRegs, R3_IDX);
364 bitVectSetBit (freeRegs, R4_IDX);
365 bitVectSetBit (freeRegs, R5_IDX);
366 bitVectSetBit (freeRegs, R6_IDX);
367 bitVectSetBit (freeRegs, R7_IDX);
369 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
371 bitVect * newfreeRegs;
372 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
373 freeBitVect(freeRegs);
374 freeRegs = newfreeRegs;
376 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
379 for (i=0; i<freeRegs->size; i++)
381 if (bitVectBitValue(freeRegs,i))
382 tempRegs[offset++] = mcs51_regWithIdx(i);
385 freeBitVect(freeRegs);
390 freeBitVect(freeRegs);
395 /*-----------------------------------------------------------------*/
396 /* newAsmop - creates a new asmOp */
397 /*-----------------------------------------------------------------*/
399 newAsmop (short type)
403 aop = Safe_calloc (1, sizeof (asmop));
408 /*-----------------------------------------------------------------*/
409 /* pointerCode - returns the code for a pointer type */
410 /*-----------------------------------------------------------------*/
412 pointerCode (sym_link * etype)
415 return PTR_TYPE (SPEC_OCLS (etype));
419 /*-----------------------------------------------------------------*/
420 /* leftRightUseAcc - returns size of accumulator use by operands */
421 /*-----------------------------------------------------------------*/
423 leftRightUseAcc(iCode *ic)
432 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
433 "null iCode pointer");
440 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
443 size = getSize (OP_SYMBOL (op)->type);
448 else if (ic->op == JUMPTABLE)
451 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
454 size = getSize (OP_SYMBOL (op)->type);
462 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
465 size = getSize (OP_SYMBOL (op)->type);
470 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
473 size = getSize (OP_SYMBOL (op)->type);
485 /*-----------------------------------------------------------------*/
486 /* aopForSym - for a true symbol */
487 /*-----------------------------------------------------------------*/
489 aopForSym (iCode * ic, symbol * sym, bool result)
494 wassertl (ic != NULL, "Got a null iCode");
495 wassertl (sym != NULL, "Got a null symbol");
497 space = SPEC_OCLS (sym->etype);
499 /* if already has one */
503 /* assign depending on the storage class */
504 /* if it is on the stack or indirectly addressable */
505 /* space we need to assign either r0 or r1 to it */
506 if (sym->onStack || sym->iaccess)
508 sym->aop = aop = newAsmop (0);
509 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
510 aop->size = getSize (sym->type);
512 /* now assign the address of the variable to
513 the pointer register */
514 if (aop->type != AOP_STK)
519 char offset = ((sym->stack < 0) ?
520 ((char) (sym->stack - _G.nRegsSaved)) :
521 ((char) sym->stack)) & 0xff;
522 if (_G.accInUse || leftRightUseAcc (ic))
523 emitcode ("push", "acc");
525 if ((offset >= -3) && (offset <= 3))
527 emitcode ("mov", "%s,%s",
528 aop->aopu.aop_ptr->name, SYM_BP (sym));
531 emitcode ("dec", aop->aopu.aop_ptr->name);
536 emitcode ("inc", aop->aopu.aop_ptr->name);
542 emitcode ("mov", "a,%s", SYM_BP (sym));
543 emitcode ("add", "a,#0x%02x", offset);
544 emitcode ("mov", "%s,a",
545 aop->aopu.aop_ptr->name);
547 if (_G.accInUse || leftRightUseAcc (ic))
548 emitcode ("pop", "acc");
551 emitcode ("mov", "%s,#%s",
552 aop->aopu.aop_ptr->name,
554 aop->paged = space->paged;
557 aop->aopu.aop_stk = sym->stack;
561 /* if in bit space */
562 if (IN_BITSPACE (space))
564 sym->aop = aop = newAsmop (AOP_CRY);
565 aop->aopu.aop_dir = sym->rname;
566 aop->size = getSize (sym->type);
569 /* if it is in direct space */
570 if (IN_DIRSPACE (space))
572 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
573 //printTypeChainRaw(sym->type, NULL);
574 //printf("space = %s\n", space ? space->sname : "NULL");
575 sym->aop = aop = newAsmop (AOP_DIR);
576 aop->aopu.aop_dir = sym->rname;
577 aop->size = getSize (sym->type);
581 /* special case for a function */
582 if (IS_FUNC (sym->type))
584 sym->aop = aop = newAsmop (AOP_IMMD);
585 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
586 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
587 aop->size = FPTRSIZE;
591 /* only remaining is far space */
592 /* in which case DPTR gets the address */
593 sym->aop = aop = newAsmop (AOP_DPTR);
594 emitcode ("mov", "dptr,#%s", sym->rname);
595 aop->size = getSize (sym->type);
597 /* if it is in code space */
598 if (IN_CODESPACE (space))
604 /*-----------------------------------------------------------------*/
605 /* aopForRemat - rematerialzes an object */
606 /*-----------------------------------------------------------------*/
608 aopForRemat (symbol * sym)
610 iCode *ic = sym->rematiCode;
611 asmop *aop = newAsmop (AOP_IMMD);
618 val += (int) operandLitValue (IC_RIGHT (ic));
619 else if (ic->op == '-')
620 val -= (int) operandLitValue (IC_RIGHT (ic));
621 else if (IS_CAST_ICODE(ic)) {
622 sym_link *from_type = operandType(IC_RIGHT(ic));
623 aop->aopu.aop_immd.from_cast_remat = 1;
624 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
625 ptr_type = DCL_TYPE(from_type);
626 if (ptr_type == IPOINTER) {
633 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
637 sprintf (buffer, "(%s %c 0x%04x)",
638 OP_SYMBOL (IC_LEFT (ic))->rname,
639 val >= 0 ? '+' : '-',
642 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
644 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
645 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
646 /* set immd2 field if required */
647 if (aop->aopu.aop_immd.from_cast_remat) {
648 sprintf(buffer,"#0x%02x",ptr_type);
649 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
650 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
656 /*-----------------------------------------------------------------*/
657 /* regsInCommon - two operands have some registers in common */
658 /*-----------------------------------------------------------------*/
660 regsInCommon (operand * op1, operand * op2)
665 /* if they have registers in common */
666 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
669 sym1 = OP_SYMBOL (op1);
670 sym2 = OP_SYMBOL (op2);
672 if (sym1->nRegs == 0 || sym2->nRegs == 0)
675 for (i = 0; i < sym1->nRegs; i++)
681 for (j = 0; j < sym2->nRegs; j++)
686 if (sym2->regs[j] == sym1->regs[i])
694 /*-----------------------------------------------------------------*/
695 /* operandsEqu - equivalent */
696 /*-----------------------------------------------------------------*/
698 operandsEqu (operand * op1, operand * op2)
702 /* if they're not symbols */
703 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
706 sym1 = OP_SYMBOL (op1);
707 sym2 = OP_SYMBOL (op2);
709 /* if both are itemps & one is spilt
710 and the other is not then false */
711 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
712 sym1->isspilt != sym2->isspilt)
715 /* if they are the same */
719 /* if they have the same rname */
720 if (sym1->rname[0] && sym2->rname[0]
721 && strcmp (sym1->rname, sym2->rname) == 0)
724 /* if left is a tmp & right is not */
725 if (IS_ITEMP (op1) &&
728 (sym1->usl.spillLoc == sym2))
731 if (IS_ITEMP (op2) &&
735 (sym2->usl.spillLoc == sym1))
741 /*-----------------------------------------------------------------*/
742 /* sameRegs - two asmops have the same registers */
743 /*-----------------------------------------------------------------*/
745 sameRegs (asmop * aop1, asmop * aop2)
752 if (aop1->type != AOP_REG ||
753 aop2->type != AOP_REG)
756 if (aop1->size != aop2->size)
759 for (i = 0; i < aop1->size; i++)
760 if (aop1->aopu.aop_reg[i] !=
761 aop2->aopu.aop_reg[i])
767 /*-----------------------------------------------------------------*/
768 /* aopOp - allocates an asmop for an operand : */
769 /*-----------------------------------------------------------------*/
771 aopOp (operand * op, iCode * ic, bool result)
780 /* if this a literal */
781 if (IS_OP_LITERAL (op))
783 op->aop = aop = newAsmop (AOP_LIT);
784 aop->aopu.aop_lit = op->operand.valOperand;
785 aop->size = getSize (operandType (op));
789 /* if already has a asmop then continue */
793 /* if the underlying symbol has a aop */
794 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
796 op->aop = OP_SYMBOL (op)->aop;
800 /* if this is a true symbol */
801 if (IS_TRUE_SYMOP (op))
803 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
807 /* this is a temporary : this has
813 e) can be a return use only */
815 sym = OP_SYMBOL (op);
817 /* if the type is a conditional */
818 if (sym->regType == REG_CND)
820 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
825 /* if it is spilt then two situations
827 b) has a spill location */
828 if (sym->isspilt || sym->nRegs == 0)
831 /* rematerialize it NOW */
834 sym->aop = op->aop = aop =
836 aop->size = getSize (sym->type);
843 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
844 aop->size = getSize (sym->type);
845 for (i = 0; i < 2; i++)
846 aop->aopu.aop_str[i] = accUse[i];
854 aop = op->aop = sym->aop = newAsmop (AOP_STR);
855 aop->size = getSize (sym->type);
856 for (i = 0; i < fReturnSizeMCS51; i++)
857 aop->aopu.aop_str[i] = fReturn[i];
861 if (sym->usl.spillLoc)
863 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
865 /* force a new aop if sizes differ */
866 sym->usl.spillLoc->aop = NULL;
868 sym->aop = op->aop = aop =
869 aopForSym (ic, sym->usl.spillLoc, result);
870 aop->size = getSize (sym->type);
874 /* else must be a dummy iTemp */
875 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
876 aop->size = getSize (sym->type);
880 /* must be in a register */
881 sym->aop = op->aop = aop = newAsmop (AOP_REG);
882 aop->size = sym->nRegs;
883 for (i = 0; i < sym->nRegs; i++)
884 aop->aopu.aop_reg[i] = sym->regs[i];
887 /*-----------------------------------------------------------------*/
888 /* freeAsmop - free up the asmop given to an operand */
889 /*----------------------------------------------------------------*/
891 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
908 /* depending on the asmop type only three cases need work AOP_RO
909 , AOP_R1 && AOP_STK */
915 emitcode ("mov", "r0,b");
918 else if (_G.r0Pushed)
922 emitcode ("pop", "ar0");
926 bitVectUnSetBit (ic->rUsed, R0_IDX);
932 emitcode ("mov", "r1,b");
939 emitcode ("pop", "ar1");
943 bitVectUnSetBit (ic->rUsed, R1_IDX);
949 int stk = aop->aopu.aop_stk + aop->size - 1;
950 bitVectUnSetBit (ic->rUsed, R0_IDX);
951 bitVectUnSetBit (ic->rUsed, R1_IDX);
953 getFreePtr (ic, &aop, FALSE);
957 emitcode ("mov", "a,_bp");
958 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
959 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
963 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
968 emitcode ("pop", "acc");
969 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
972 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
975 freeAsmop (op, NULL, ic, TRUE);
978 emitcode ("pop", "ar1");
984 emitcode ("pop", "ar0");
991 /* all other cases just dealloc */
997 OP_SYMBOL (op)->aop = NULL;
998 /* if the symbol has a spill */
1000 SPIL_LOC (op)->aop = NULL;
1005 /*------------------------------------------------------------------*/
1006 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1007 /* pop r0 or r1 off stack if pushed */
1008 /*------------------------------------------------------------------*/
1010 freeForBranchAsmop (operand * op)
1030 emitcode ("mov", "r0,b");
1032 else if (_G.r0Pushed)
1034 emitcode ("pop", "ar0");
1041 emitcode ("mov", "r1,b");
1043 else if (_G.r1Pushed)
1045 emitcode ("pop", "ar1");
1052 int stk = aop->aopu.aop_stk + aop->size - 1;
1054 emitcode ("mov", "b,r0");
1057 emitcode ("mov", "a,_bp");
1058 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1059 emitcode ("mov", "r0,a");
1063 emitcode ("mov", "r0,_bp");
1068 emitcode ("pop", "acc");
1069 emitcode ("mov", "@r0,a");
1072 emitcode ("dec", "r0");
1074 emitcode ("mov", "r0,b");
1080 /*-----------------------------------------------------------------*/
1081 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1082 /* clobber the accumulator */
1083 /*-----------------------------------------------------------------*/
1085 aopGetUsesAcc (asmop *aop, int offset)
1087 if (offset > (aop->size - 1))
1105 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1116 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1122 /* Error case --- will have been caught already */
1128 /*-----------------------------------------------------------------*/
1129 /* aopGet - for fetching value of the aop */
1130 /*-----------------------------------------------------------------*/
1132 aopGet (asmop * aop, int offset, bool bit16, bool dname)
1137 /* offset is greater than
1139 if (offset > (aop->size - 1) &&
1140 aop->type != AOP_LIT)
1143 /* depending on type */
1151 /* if we need to increment it */
1152 while (offset > aop->coff)
1154 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1158 while (offset < aop->coff)
1160 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1167 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1168 return (dname ? "acc" : "a");
1170 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1171 rs = Safe_calloc (1, strlen (s) + 1);
1176 if (aop->code && aop->coff==0 && offset>=1) {
1177 emitcode ("mov", "a,#0x%02x", offset);
1178 emitcode ("movc", "a,@a+dptr");
1179 return (dname ? "acc" : "a");
1182 while (offset > aop->coff)
1184 emitcode ("inc", "dptr");
1188 while (offset < aop->coff)
1190 emitcode ("lcall", "__decdptr");
1197 emitcode ("clr", "a");
1198 emitcode ("movc", "a,@a+dptr");
1202 emitcode ("movx", "a,@dptr");
1204 return (dname ? "acc" : "a");
1208 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1209 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1211 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1213 sprintf (s, "#(%s >> %d)",
1214 aop->aopu.aop_immd.aop_immd1,
1218 aop->aopu.aop_immd.aop_immd1);
1219 rs = Safe_calloc (1, strlen (s) + 1);
1225 sprintf (s, "(%s + %d)",
1229 sprintf (s, "%s", aop->aopu.aop_dir);
1230 rs = Safe_calloc (1, strlen (s) + 1);
1236 return aop->aopu.aop_reg[offset]->dname;
1238 return aop->aopu.aop_reg[offset]->name;
1241 emitcode ("clr", "a");
1242 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1243 emitcode ("rlc", "a");
1244 return (dname ? "acc" : "a");
1247 if (!offset && dname)
1249 return aop->aopu.aop_str[offset];
1252 return aopLiteral (aop->aopu.aop_lit, offset);
1256 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1260 return aop->aopu.aop_str[offset];
1264 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1265 "aopget got unsupported aop->type");
1268 /*-----------------------------------------------------------------*/
1269 /* aopPut - puts a string for a aop and indicates if acc is in use */
1270 /*-----------------------------------------------------------------*/
1272 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1275 bool accuse = FALSE;
1277 if (aop->size && offset > (aop->size - 1))
1279 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1280 "aopPut got offset > aop->size");
1284 /* will assign value to value */
1285 /* depending on where it is ofcourse */
1289 MOVA (s); /* read s in case it was volatile */
1295 sprintf (d, "(%s + %d)",
1296 aop->aopu.aop_dir, offset);
1298 sprintf (d, "%s", aop->aopu.aop_dir);
1300 if (strcmp (d, s) ||
1302 emitcode ("mov", "%s,%s", d, s);
1303 if (!strcmp (d, "acc"))
1309 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1310 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1313 strcmp (s, "r0") == 0 ||
1314 strcmp (s, "r1") == 0 ||
1315 strcmp (s, "r2") == 0 ||
1316 strcmp (s, "r3") == 0 ||
1317 strcmp (s, "r4") == 0 ||
1318 strcmp (s, "r5") == 0 ||
1319 strcmp (s, "r6") == 0 ||
1320 strcmp (s, "r7") == 0)
1321 emitcode ("mov", "%s,%s",
1322 aop->aopu.aop_reg[offset]->dname, s);
1324 emitcode ("mov", "%s,%s",
1325 aop->aopu.aop_reg[offset]->name, s);
1332 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1333 "aopPut writing to code space");
1337 while (offset > aop->coff)
1340 emitcode ("inc", "dptr");
1343 while (offset < aop->coff)
1346 emitcode ("lcall", "__decdptr");
1351 /* if not in accumulator */
1354 emitcode ("movx", "@dptr,a");
1359 while (offset > aop->coff)
1362 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1364 while (offset < aop->coff)
1367 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1374 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1380 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1382 else if (strcmp (s, "r0") == 0 ||
1383 strcmp (s, "r1") == 0 ||
1384 strcmp (s, "r2") == 0 ||
1385 strcmp (s, "r3") == 0 ||
1386 strcmp (s, "r4") == 0 ||
1387 strcmp (s, "r5") == 0 ||
1388 strcmp (s, "r6") == 0 ||
1389 strcmp (s, "r7") == 0)
1392 sprintf (buffer, "a%s", s);
1393 emitcode ("mov", "@%s,%s",
1394 aop->aopu.aop_ptr->name, buffer);
1397 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1402 if (strcmp (s, "a") == 0)
1403 emitcode ("push", "acc");
1407 emitcode ("push", "acc");
1409 emitcode ("push", s);
1415 /* if not bit variable */
1416 if (!aop->aopu.aop_dir)
1418 /* inefficient: move carry into A and use jz/jnz */
1419 emitcode ("clr", "a");
1420 emitcode ("rlc", "a");
1426 emitcode ("clr", "%s", aop->aopu.aop_dir);
1428 emitcode ("setb", "%s", aop->aopu.aop_dir);
1429 else if (!strcmp (s, "c"))
1430 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1434 /* set C, if a >= 1 */
1435 emitcode ("add", "a,#0xff");
1436 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1443 if (strcmp (aop->aopu.aop_str[offset], s) ||
1445 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1451 if (!offset && (strcmp (s, "acc") == 0) &&
1455 if (strcmp (aop->aopu.aop_str[offset], s) &&
1457 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1461 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1462 "aopPut got unsupported aop->type");
1471 /*-----------------------------------------------------------------*/
1472 /* pointToEnd :- points to the last byte of the operand */
1473 /*-----------------------------------------------------------------*/
1475 pointToEnd (asmop * aop)
1481 aop->coff = count = (aop->size - 1);
1487 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1491 emitcode ("inc", "dptr");
1498 /*-----------------------------------------------------------------*/
1499 /* reAdjustPreg - points a register back to where it should */
1500 /*-----------------------------------------------------------------*/
1502 reAdjustPreg (asmop * aop)
1504 if ((aop->coff==0) || aop->size <= 1)
1512 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1517 emitcode ("lcall", "__decdptr");
1524 #define AOP(op) op->aop
1525 #define AOP_TYPE(op) AOP(op)->type
1526 #define AOP_SIZE(op) AOP(op)->size
1527 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1528 AOP_TYPE(x) == AOP_R0))
1530 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1531 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1533 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1534 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1535 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1538 /*-----------------------------------------------------------------*/
1539 /* opIsGptr: returns non-zero if the passed operand is */
1540 /* a generic pointer type. */
1541 /*-----------------------------------------------------------------*/
1543 opIsGptr (operand * op)
1545 sym_link *type = operandType (op);
1547 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1554 /*-----------------------------------------------------------------*/
1555 /* getDataSize - get the operand data size */
1556 /*-----------------------------------------------------------------*/
1558 getDataSize (operand * op)
1561 size = AOP_SIZE (op);
1562 if (size == GPTRSIZE)
1564 sym_link *type = operandType (op);
1565 if (IS_GENPTR (type))
1567 /* generic pointer; arithmetic operations
1568 * should ignore the high byte (pointer type).
1576 /*-----------------------------------------------------------------*/
1577 /* outAcc - output Acc */
1578 /*-----------------------------------------------------------------*/
1580 outAcc (operand * result)
1583 size = getDataSize (result);
1586 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1589 /* unsigned or positive */
1592 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1597 /*-----------------------------------------------------------------*/
1598 /* outBitC - output a bit C */
1599 /*-----------------------------------------------------------------*/
1601 outBitC (operand * result)
1603 /* if the result is bit */
1604 if (AOP_TYPE (result) == AOP_CRY)
1605 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1608 emitcode ("clr", "a");
1609 emitcode ("rlc", "a");
1614 /*-----------------------------------------------------------------*/
1615 /* toBoolean - emit code for orl a,operator(sizeop) */
1616 /*-----------------------------------------------------------------*/
1618 toBoolean (operand * oper)
1620 int size = AOP_SIZE (oper) - 1;
1622 bool AccUsed = FALSE;
1625 while (!AccUsed && size--)
1627 AccUsed |= aopGetUsesAcc(AOP (oper), offset++);
1630 size = AOP_SIZE (oper) - 1;
1632 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1633 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1636 emitcode("mov", "b,a");
1639 MOVA (aopGet (AOP (oper), offset++, FALSE, FALSE));
1640 emitcode ("orl", "b,a");
1642 MOVA (aopGet (AOP (oper), offset++, FALSE, FALSE));
1643 emitcode ("orl", "a,b");
1650 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1656 /*-----------------------------------------------------------------*/
1657 /* genNot - generate code for ! operation */
1658 /*-----------------------------------------------------------------*/
1664 D(emitcode ("; genNot",""));
1666 /* assign asmOps to operand & result */
1667 aopOp (IC_LEFT (ic), ic, FALSE);
1668 aopOp (IC_RESULT (ic), ic, TRUE);
1670 /* if in bit space then a special case */
1671 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1673 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1674 emitcode ("cpl", "c");
1675 outBitC (IC_RESULT (ic));
1679 toBoolean (IC_LEFT (ic));
1681 tlbl = newiTempLabel (NULL);
1682 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1683 emitcode ("", "%05d$:", tlbl->key + 100);
1684 outBitC (IC_RESULT (ic));
1687 /* release the aops */
1688 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1689 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1693 /*-----------------------------------------------------------------*/
1694 /* genCpl - generate code for complement */
1695 /*-----------------------------------------------------------------*/
1702 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1704 D(emitcode (";", "genCpl"));
1706 /* assign asmOps to operand & result */
1707 aopOp (IC_LEFT (ic), ic, FALSE);
1708 aopOp (IC_RESULT (ic), ic, TRUE);
1710 /* special case if in bit space */
1711 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1715 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1716 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1718 /* promotion rules are responsible for this strange result:
1719 bit -> int -> ~int -> bit
1720 uchar -> int -> ~int -> bit
1722 werror(W_COMPLEMENT);
1723 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1727 tlbl=newiTempLabel(NULL);
1728 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE);
1729 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1730 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1731 IS_AOP_PREG (IC_LEFT (ic)))
1733 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1738 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1740 emitcode ("", "%05d$:", tlbl->key + 100);
1741 outBitC (IC_RESULT(ic));
1745 size = AOP_SIZE (IC_RESULT (ic));
1748 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1750 emitcode ("cpl", "a");
1751 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1756 /* release the aops */
1757 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1758 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1761 /*-----------------------------------------------------------------*/
1762 /* genUminusFloat - unary minus for floating points */
1763 /*-----------------------------------------------------------------*/
1765 genUminusFloat (operand * op, operand * result)
1767 int size, offset = 0;
1770 D(emitcode ("; genUminusFloat",""));
1772 /* for this we just copy and then flip the bit */
1774 size = AOP_SIZE (op) - 1;
1778 aopPut (AOP (result),
1779 aopGet (AOP (op), offset, FALSE, FALSE),
1781 isOperandVolatile (result, FALSE));
1785 l = aopGet (AOP (op), offset, FALSE, FALSE);
1789 emitcode ("cpl", "acc.7");
1790 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1793 /*-----------------------------------------------------------------*/
1794 /* genUminus - unary minus code generation */
1795 /*-----------------------------------------------------------------*/
1797 genUminus (iCode * ic)
1800 sym_link *optype, *rtype;
1803 D(emitcode ("; genUminus",""));
1806 aopOp (IC_LEFT (ic), ic, FALSE);
1807 aopOp (IC_RESULT (ic), ic, TRUE);
1809 /* if both in bit space then special
1811 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1812 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1815 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1816 emitcode ("cpl", "c");
1817 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1821 optype = operandType (IC_LEFT (ic));
1822 rtype = operandType (IC_RESULT (ic));
1824 /* if float then do float stuff */
1825 if (IS_FLOAT (optype))
1827 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1831 /* otherwise subtract from zero */
1832 size = AOP_SIZE (IC_LEFT (ic));
1837 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1838 if (!strcmp (l, "a"))
1842 emitcode ("cpl", "a");
1843 emitcode ("addc", "a,#0");
1849 emitcode ("clr", "a");
1850 emitcode ("subb", "a,%s", l);
1852 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1855 /* if any remaining bytes in the result */
1856 /* we just need to propagate the sign */
1857 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1859 emitcode ("rlc", "a");
1860 emitcode ("subb", "a,acc");
1862 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1866 /* release the aops */
1867 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1868 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1871 /*-----------------------------------------------------------------*/
1872 /* saveRegisters - will look for a call and save the registers */
1873 /*-----------------------------------------------------------------*/
1875 saveRegisters (iCode * lic)
1882 for (ic = lic; ic; ic = ic->next)
1883 if (ic->op == CALL || ic->op == PCALL)
1888 fprintf (stderr, "found parameter push with no function call\n");
1892 /* if the registers have been saved already or don't need to be then
1896 if (IS_SYMOP(IC_LEFT(ic)) &&
1897 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1898 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1901 /* save the registers in use at this time but skip the
1902 ones for the result */
1903 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1904 mcs51_rUmaskForOp (IC_RESULT(ic)));
1907 if (options.useXstack)
1909 int count = bitVectnBitsOn (rsave);
1913 i = bitVectFirstBit (rsave);
1914 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1915 emitcode ("mov", "r0,%s", spname);
1916 emitcode ("inc", "%s", spname);// allocate before use
1917 emitcode ("movx", "@r0,a");
1918 if (bitVectBitValue (rsave, R0_IDX))
1919 emitcode ("mov", "r0,a");
1921 else if (count != 0)
1923 if (bitVectBitValue (rsave, R0_IDX))
1925 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1927 emitcode ("mov", "r0,%s", spname);
1929 emitcode ("add", "a,#%d", count);
1930 emitcode ("mov", "%s,a", spname);
1931 for (i = 0; i < mcs51_nRegs; i++)
1933 if (bitVectBitValue (rsave, i))
1937 emitcode ("pop", "acc");
1938 emitcode ("push", "acc");
1942 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1944 emitcode ("movx", "@r0,a");
1947 emitcode ("inc", "r0");
1951 if (bitVectBitValue (rsave, R0_IDX))
1953 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1958 for (i = 0; i < mcs51_nRegs; i++)
1960 if (bitVectBitValue (rsave, i))
1961 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1965 /*-----------------------------------------------------------------*/
1966 /* unsaveRegisters - pop the pushed registers */
1967 /*-----------------------------------------------------------------*/
1969 unsaveRegisters (iCode * ic)
1974 /* restore the registers in use at this time but skip the
1975 ones for the result */
1976 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1977 mcs51_rUmaskForOp (IC_RESULT(ic)));
1979 if (options.useXstack)
1981 int count = bitVectnBitsOn (rsave);
1985 emitcode ("mov", "r0,%s", spname);
1986 emitcode ("dec", "r0");
1987 emitcode ("movx", "a,@r0");
1988 i = bitVectFirstBit (rsave);
1989 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1990 emitcode ("dec", "%s", spname);
1992 else if (count != 0)
1994 emitcode ("mov", "r0,%s", spname);
1995 for (i = mcs51_nRegs; i >= 0; i--)
1997 if (bitVectBitValue (rsave, i))
1999 emitcode ("dec", "r0");
2000 emitcode ("movx", "a,@r0");
2002 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
2004 emitcode ("push", "acc");
2007 emitcode ("mov", "%s,r0", spname);
2008 if (bitVectBitValue (rsave, R0_IDX))
2010 emitcode ("pop", "ar0");
2015 for (i = mcs51_nRegs; i >= 0; i--)
2017 if (bitVectBitValue (rsave, i))
2018 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2023 /*-----------------------------------------------------------------*/
2025 /*-----------------------------------------------------------------*/
2027 pushSide (operand * oper, int size)
2032 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
2033 if (AOP_TYPE (oper) != AOP_REG &&
2034 AOP_TYPE (oper) != AOP_DIR &&
2038 emitcode ("push", "acc");
2041 emitcode ("push", "%s", l);
2045 /*-----------------------------------------------------------------*/
2046 /* assignResultValue - also indicates if acc is in use afterwards */
2047 /*-----------------------------------------------------------------*/
2049 assignResultValue (operand * oper)
2052 int size = AOP_SIZE (oper);
2053 bool accuse = FALSE;
2057 accuse |= aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2064 /*-----------------------------------------------------------------*/
2065 /* genXpush - pushes onto the external stack */
2066 /*-----------------------------------------------------------------*/
2068 genXpush (iCode * ic)
2070 asmop *aop = newAsmop (0);
2072 int size, offset = 0;
2074 D(emitcode ("; genXpush",""));
2076 aopOp (IC_LEFT (ic), ic, FALSE);
2077 r = getFreePtr (ic, &aop, FALSE);
2079 size = AOP_SIZE (IC_LEFT (ic));
2083 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2084 emitcode ("mov", "%s,%s", r->name, spname);
2085 emitcode ("inc", "%s", spname); // allocate space first
2086 emitcode ("movx", "@%s,a", r->name);
2090 // allocate space first
2091 emitcode ("mov", "%s,%s", r->name, spname);
2093 emitcode ("add", "a,#%d", size);
2094 emitcode ("mov", "%s,a", spname);
2098 MOVA (aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE));
2099 emitcode ("movx", "@%s,a", r->name);
2100 emitcode ("inc", "%s", r->name);
2104 freeAsmop (NULL, aop, ic, TRUE);
2105 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2108 /*-----------------------------------------------------------------*/
2109 /* genIpush - generate code for pushing this gets a little complex */
2110 /*-----------------------------------------------------------------*/
2112 genIpush (iCode * ic)
2114 int size, offset = 0;
2117 D(emitcode ("; genIpush",""));
2119 /* if this is not a parm push : ie. it is spill push
2120 and spill push is always done on the local stack */
2124 /* and the item is spilt then do nothing */
2125 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2128 aopOp (IC_LEFT (ic), ic, FALSE);
2129 size = AOP_SIZE (IC_LEFT (ic));
2130 /* push it on the stack */
2133 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2139 emitcode ("push", "%s", l);
2144 /* this is a paramter push: in this case we call
2145 the routine to find the call and save those
2146 registers that need to be saved */
2149 /* if use external stack then call the external
2150 stack pushing routine */
2151 if (options.useXstack)
2157 /* then do the push */
2158 aopOp (IC_LEFT (ic), ic, FALSE);
2160 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2161 size = AOP_SIZE (IC_LEFT (ic));
2165 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2166 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2167 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2171 emitcode ("push", "acc");
2174 emitcode ("push", "%s", l);
2177 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2180 /*-----------------------------------------------------------------*/
2181 /* genIpop - recover the registers: can happen only for spilling */
2182 /*-----------------------------------------------------------------*/
2184 genIpop (iCode * ic)
2188 D(emitcode ("; genIpop",""));
2190 /* if the temp was not pushed then */
2191 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2194 aopOp (IC_LEFT (ic), ic, FALSE);
2195 size = AOP_SIZE (IC_LEFT (ic));
2196 offset = (size - 1);
2198 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2201 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2204 /*-----------------------------------------------------------------*/
2205 /* saveRBank - saves an entire register bank on the stack */
2206 /*-----------------------------------------------------------------*/
2208 saveRBank (int bank, iCode * ic, bool pushPsw)
2211 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2215 if (options.useXstack)
2219 /* Assume r0 is available for use. */
2220 r = mcs51_regWithIdx (R0_IDX);;
2225 r = getFreePtr (ic, &aop, FALSE);
2227 // allocate space first
2228 emitcode ("mov", "%s,%s", r->name, spname);
2230 emitcode ("add", "a,#%d", count);
2231 emitcode ("mov", "%s,a", spname);
2234 for (i = 0; i < mcs51_nRegs; i++)
2236 if (options.useXstack)
2238 emitcode ("mov", "a,(%s+%d)",
2239 regs8051[i].base, 8 * bank + regs8051[i].offset);
2240 emitcode ("movx", "@%s,a", r->name);
2242 emitcode ("inc", "%s", r->name);
2245 emitcode ("push", "(%s+%d)",
2246 regs8051[i].base, 8 * bank + regs8051[i].offset);
2251 if (options.useXstack)
2253 emitcode ("mov", "a,psw");
2254 emitcode ("movx", "@%s,a", r->name);
2259 emitcode ("push", "psw");
2262 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2267 freeAsmop (NULL, aop, ic, TRUE);
2276 /*-----------------------------------------------------------------*/
2277 /* unsaveRBank - restores the register bank from stack */
2278 /*-----------------------------------------------------------------*/
2280 unsaveRBank (int bank, iCode * ic, bool popPsw)
2286 if (options.useXstack)
2290 /* Assume r0 is available for use. */
2291 r = mcs51_regWithIdx (R0_IDX);;
2296 r = getFreePtr (ic, &aop, FALSE);
2298 emitcode ("mov", "%s,%s", r->name, spname);
2303 if (options.useXstack)
2305 emitcode ("dec", "%s", r->name);
2306 emitcode ("movx", "a,@%s", r->name);
2307 emitcode ("mov", "psw,a");
2311 emitcode ("pop", "psw");
2315 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2317 if (options.useXstack)
2319 emitcode ("dec", "%s", r->name);
2320 emitcode ("movx", "a,@%s", r->name);
2321 emitcode ("mov", "(%s+%d),a",
2322 regs8051[i].base, 8 * bank + regs8051[i].offset);
2326 emitcode ("pop", "(%s+%d)",
2327 regs8051[i].base, 8 * bank + regs8051[i].offset);
2331 if (options.useXstack)
2333 emitcode ("mov", "%s,%s", spname, r->name);
2338 freeAsmop (NULL, aop, ic, TRUE);
2342 /*-----------------------------------------------------------------*/
2343 /* genSend - gen code for SEND */
2344 /*-----------------------------------------------------------------*/
2345 static void genSend(set *sendSet)
2350 for (sic = setFirstItem (sendSet); sic;
2351 sic = setNextItem (sendSet)) {
2352 int size, offset = 0;
2353 aopOp (IC_LEFT (sic), sic, FALSE);
2354 size = AOP_SIZE (IC_LEFT (sic));
2356 if (sic->argreg == 1) {
2358 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2360 if (strcmp (l, fReturn[offset]))
2361 emitcode ("mov", "%s,%s", fReturn[offset], l);
2367 emitcode ("mov","b1_%d,%s",rb1_count++,
2368 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2371 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2375 /*-----------------------------------------------------------------*/
2376 /* genCall - generates a call statement */
2377 /*-----------------------------------------------------------------*/
2379 genCall (iCode * ic)
2382 // bool restoreBank = FALSE;
2383 bool swapBanks = FALSE;
2384 bool accuse = FALSE;
2385 bool accPushed = FALSE;
2387 D(emitcode("; genCall",""));
2389 dtype = operandType (IC_LEFT (ic));
2390 /* if send set is not empty then assign */
2393 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2394 genSend(reverseSet(_G.sendSet));
2396 genSend(_G.sendSet);
2402 /* if we are calling a not _naked function that is not using
2403 the same register bank then we need to save the
2404 destination registers on the stack */
2405 dtype = operandType (IC_LEFT (ic));
2406 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2407 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2408 !IFFUNC_ISISR (dtype))
2413 /* if caller saves & we have not saved then */
2419 emitcode ("mov", "psw,#0x%02x",
2420 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2424 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2425 OP_SYMBOL (IC_LEFT (ic))->rname :
2426 OP_SYMBOL (IC_LEFT (ic))->name));
2430 emitcode ("mov", "psw,#0x%02x",
2431 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2434 /* if we need assign a result value */
2435 if ((IS_ITEMP (IC_RESULT (ic)) &&
2436 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2437 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2438 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2439 IS_TRUE_SYMOP (IC_RESULT (ic)))
2443 aopOp (IC_RESULT (ic), ic, FALSE);
2446 accuse = assignResultValue (IC_RESULT (ic));
2448 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2451 /* adjust the stack for parameters if required */
2455 if (ic->parmBytes > 3)
2459 emitcode ("push", "acc");
2463 emitcode ("mov", "a,%s", spname);
2464 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2465 emitcode ("mov", "%s,a", spname);
2467 /* unsaveRegisters from xstack needs acc, but */
2468 /* unsaveRegisters from stack needs this popped */
2469 if (accPushed && !options.useXstack)
2471 emitcode ("pop", "acc");
2476 for (i = 0; i < ic->parmBytes; i++)
2477 emitcode ("dec", "%s", spname);
2480 /* if we hade saved some registers then unsave them */
2481 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2483 if (accuse && !accPushed && options.useXstack)
2485 /* xstack needs acc, but doesn't touch normal stack */
2486 emitcode ("push", "acc");
2489 unsaveRegisters (ic);
2492 // /* if register bank was saved then pop them */
2494 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2497 emitcode ("pop", "acc");
2500 /*-----------------------------------------------------------------*/
2501 /* -10l - generates a call by pointer statement */
2502 /*-----------------------------------------------------------------*/
2504 genPcall (iCode * ic)
2507 symbol *rlbl = newiTempLabel (NULL);
2508 // bool restoreBank=FALSE;
2509 bool swapBanks = FALSE;
2511 D(emitcode("; genPCall",""));
2513 /* if caller saves & we have not saved then */
2517 /* if we are calling a not _naked function that is not using
2518 the same register bank then we need to save the
2519 destination registers on the stack */
2520 dtype = operandType (IC_LEFT (ic))->next;
2521 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2522 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2523 !IFFUNC_ISISR (dtype))
2525 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2526 // restoreBank=TRUE;
2528 // need caution message to user here
2531 /* push the return address on to the stack */
2532 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2533 emitcode ("push", "acc");
2534 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2535 emitcode ("push", "acc");
2537 /* now push the calling address */
2538 aopOp (IC_LEFT (ic), ic, FALSE);
2540 pushSide (IC_LEFT (ic), FPTRSIZE);
2542 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2544 /* if send set is not empty the assign */
2547 genSend(reverseSet(_G.sendSet));
2553 emitcode ("mov", "psw,#0x%02x",
2554 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2558 emitcode ("ret", "");
2559 emitcode ("", "%05d$:", (rlbl->key + 100));
2564 emitcode ("mov", "psw,#0x%02x",
2565 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2568 /* if we need assign a result value */
2569 if ((IS_ITEMP (IC_RESULT (ic)) &&
2570 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2571 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2572 IS_TRUE_SYMOP (IC_RESULT (ic)))
2576 aopOp (IC_RESULT (ic), ic, FALSE);
2579 assignResultValue (IC_RESULT (ic));
2581 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2584 /* adjust the stack for parameters if
2589 if (ic->parmBytes > 3)
2591 emitcode ("mov", "a,%s", spname);
2592 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2593 emitcode ("mov", "%s,a", spname);
2596 for (i = 0; i < ic->parmBytes; i++)
2597 emitcode ("dec", "%s", spname);
2601 // /* if register bank was saved then unsave them */
2603 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2605 /* if we hade saved some registers then
2607 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2608 unsaveRegisters (ic);
2611 /*-----------------------------------------------------------------*/
2612 /* resultRemat - result is rematerializable */
2613 /*-----------------------------------------------------------------*/
2615 resultRemat (iCode * ic)
2617 if (SKIP_IC (ic) || ic->op == IFX)
2620 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2622 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2623 if (sym->remat && !POINTER_SET (ic))
2630 #if defined(__BORLANDC__) || defined(_MSC_VER)
2631 #define STRCASECMP stricmp
2633 #define STRCASECMP strcasecmp
2636 /*-----------------------------------------------------------------*/
2637 /* inExcludeList - return 1 if the string is in exclude Reg list */
2638 /*-----------------------------------------------------------------*/
2640 regsCmp(void *p1, void *p2)
2642 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2646 inExcludeList (char *s)
2648 const char *p = setFirstItem(options.excludeRegsSet);
2650 if (p == NULL || STRCASECMP(p, "none") == 0)
2654 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2657 /*-----------------------------------------------------------------*/
2658 /* genFunction - generated code for function entry */
2659 /*-----------------------------------------------------------------*/
2661 genFunction (iCode * ic)
2663 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2665 bool switchedPSW = FALSE;
2666 int calleesaves_saved_register = -1;
2667 int stackAdjust = sym->stack;
2668 int accIsFree = sym->recvSize < 4;
2669 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2670 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
2673 /* create the function header */
2674 emitcode (";", "-----------------------------------------");
2675 emitcode (";", " function %s", sym->name);
2676 emitcode (";", "-----------------------------------------");
2678 emitcode ("", "%s:", sym->rname);
2679 ftype = operandType (IC_LEFT (ic));
2680 _G.currentFunc = sym;
2682 if (IFFUNC_ISNAKED(ftype))
2684 emitcode(";", "naked function: no prologue.");
2688 /* here we need to generate the equates for the
2689 register bank if required */
2690 if (FUNC_REGBANK (ftype) != rbank)
2694 rbank = FUNC_REGBANK (ftype);
2695 for (i = 0; i < mcs51_nRegs; i++)
2697 if (strcmp (regs8051[i].base, "0") == 0)
2698 emitcode ("", "%s = 0x%02x",
2700 8 * rbank + regs8051[i].offset);
2702 emitcode ("", "%s = %s + 0x%02x",
2705 8 * rbank + regs8051[i].offset);
2709 /* if this is an interrupt service routine then
2710 save acc, b, dpl, dph */
2711 if (IFFUNC_ISISR (sym->type))
2714 if (!inExcludeList ("acc"))
2715 emitcode ("push", "acc");
2716 if (!inExcludeList ("b"))
2717 emitcode ("push", "b");
2718 if (!inExcludeList ("dpl"))
2719 emitcode ("push", "dpl");
2720 if (!inExcludeList ("dph"))
2721 emitcode ("push", "dph");
2722 /* if this isr has no bank i.e. is going to
2723 run with bank 0 , then we need to save more
2725 if (!FUNC_REGBANK (sym->type))
2728 /* if this function does not call any other
2729 function then we can be economical and
2730 save only those registers that are used */
2731 if (!IFFUNC_HASFCALL(sym->type))
2735 /* if any registers used */
2738 /* save the registers used */
2739 for (i = 0; i < sym->regsUsed->size; i++)
2741 if (bitVectBitValue (sym->regsUsed, i))
2742 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2749 /* this function has a function call. We cannot
2750 determines register usage so we will have to push the
2752 saveRBank (0, ic, FALSE);
2753 if (options.parms_in_bank1) {
2755 for (i=0; i < 8 ; i++ ) {
2756 emitcode ("push","%s",rb1regs[i]);
2763 /* This ISR uses a non-zero bank.
2765 * We assume that the bank is available for our
2768 * However, if this ISR calls a function which uses some
2769 * other bank, we must save that bank entirely.
2771 unsigned long banksToSave = 0;
2773 if (IFFUNC_HASFCALL(sym->type))
2776 #define MAX_REGISTER_BANKS 4
2781 for (i = ic; i; i = i->next)
2783 if (i->op == ENDFUNCTION)
2785 /* we got to the end OK. */
2793 dtype = operandType (IC_LEFT(i));
2795 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2797 /* Mark this bank for saving. */
2798 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2800 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2804 banksToSave |= (1 << FUNC_REGBANK(dtype));
2807 /* And note that we don't need to do it in
2815 /* This is a mess; we have no idea what
2816 * register bank the called function might
2819 * The only thing I can think of to do is
2820 * throw a warning and hope.
2822 werror(W_FUNCPTR_IN_USING_ISR);
2826 if (banksToSave && options.useXstack)
2828 /* Since we aren't passing it an ic,
2829 * saveRBank will assume r0 is available to abuse.
2831 * So switch to our (trashable) bank now, so
2832 * the caller's R0 isn't trashed.
2834 emitcode ("push", "psw");
2835 emitcode ("mov", "psw,#0x%02x",
2836 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2840 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2842 if (banksToSave & (1 << ix))
2844 saveRBank(ix, NULL, FALSE);
2848 // TODO: this needs a closer look
2849 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2852 /* Set the register bank to the desired value if nothing else */
2853 /* has done so yet. */
2856 emitcode ("push", "psw");
2857 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2862 /* This is a non-ISR function. The caller has already switched register */
2863 /* banks, if necessary, so just handle the callee-saves option. */
2865 /* if callee-save to be used for this function
2866 then save the registers being used in this function */
2867 if (IFFUNC_CALLEESAVES(sym->type))
2871 /* if any registers used */
2874 /* save the registers used */
2875 for (i = 0; i < sym->regsUsed->size; i++)
2877 if (bitVectBitValue (sym->regsUsed, i))
2879 /* remember one saved register for later usage */
2880 if (calleesaves_saved_register < 0)
2881 calleesaves_saved_register = i;
2882 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2893 if (options.useXstack)
2895 emitcode ("mov", "r0,%s", spname);
2896 emitcode ("inc", "%s", spname);
2897 emitcode ("xch", "a,_bpx");
2898 emitcode ("movx", "@r0,a");
2899 emitcode ("inc", "r0");
2900 emitcode ("mov", "a,r0");
2901 emitcode ("xch", "a,_bpx");
2902 emitcode ("push", "_bp"); /* save the callers stack */
2903 emitcode ("mov", "_bp,sp");
2907 /* set up the stack */
2908 emitcode ("push", "_bp"); /* save the callers stack */
2909 emitcode ("mov", "_bp,sp");
2913 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2914 /* before setting up the stack frame completely. */
2915 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2917 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2921 if (rsym && rsym->regType == REG_CND)
2923 if (rsym && (rsym->accuse || rsym->ruonly))
2925 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2926 rsym = rsym->usl.spillLoc;
2929 /* If the RECEIVE operand immediately spills to the first entry on the */
2930 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2931 /* rather than the usual @r0/r1 machinations. */
2932 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2936 _G.current_iCode = ric;
2937 D(emitcode ("; genReceive",""));
2938 for (ofs=0; ofs < sym->recvSize; ofs++)
2940 if (!strcmp (fReturn[ofs], "a"))
2941 emitcode ("push", "acc");
2943 emitcode ("push", fReturn[ofs]);
2945 stackAdjust -= sym->recvSize;
2948 assert (stackAdjust>=0);
2951 _G.current_iCode = ic;
2955 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2956 /* to free up the accumulator. */
2957 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2961 _G.current_iCode = ric;
2962 D(emitcode ("; genReceive",""));
2963 for (ofs=0; ofs < sym->recvSize; ofs++)
2965 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2967 _G.current_iCode = ic;
2973 /* adjust the stack for the function */
2976 int i = stackAdjust;
2978 werror (W_STACK_OVERFLOW, sym->name);
2980 if (i > 3 && accIsFree)
2982 emitcode ("mov", "a,sp");
2983 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2984 emitcode ("mov", "sp,a");
2988 /* The accumulator is not free, so we will need another register */
2989 /* to clobber. No need to worry about a possible conflict with */
2990 /* the above early RECEIVE optimizations since they would have */
2991 /* freed the accumulator if they were generated. */
2993 if (IFFUNC_CALLEESAVES(sym->type))
2995 /* if it's a callee-saves function we need a saved register */
2996 if (calleesaves_saved_register >= 0)
2998 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2999 emitcode ("mov", "a,sp");
3000 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3001 emitcode ("mov", "sp,a");
3002 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3005 /* do it the hard way */
3007 emitcode ("inc", "sp");
3011 /* not callee-saves, we can clobber r0 */
3012 emitcode ("mov", "r0,a");
3013 emitcode ("mov", "a,sp");
3014 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3015 emitcode ("mov", "sp,a");
3016 emitcode ("mov", "a,r0");
3021 emitcode ("inc", "sp");
3026 char i = ((char) sym->xstack & 0xff);
3028 if (i > 3 && accIsFree)
3030 emitcode ("mov", "a,_spx");
3031 emitcode ("add", "a,#0x%02x", i);
3032 emitcode ("mov", "_spx,a");
3036 emitcode ("push", "acc");
3037 emitcode ("mov", "a,_spx");
3038 emitcode ("add", "a,#0x%02x", i);
3039 emitcode ("mov", "_spx,a");
3040 emitcode ("pop", "acc");
3045 emitcode ("inc", "_spx");
3049 /* if critical function then turn interrupts off */
3050 if (IFFUNC_ISCRITICAL (ftype))
3052 symbol *tlbl = newiTempLabel (NULL);
3053 emitcode ("setb", "c");
3054 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3055 emitcode ("clr", "c");
3056 emitcode ("", "%05d$:", (tlbl->key + 100));
3057 emitcode ("push", "psw"); /* save old ea via c in psw */
3061 /*-----------------------------------------------------------------*/
3062 /* genEndFunction - generates epilogue for functions */
3063 /*-----------------------------------------------------------------*/
3065 genEndFunction (iCode * ic)
3067 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3068 lineNode *lnp = lineCurr;
3070 bitVect *regsUsedPrologue;
3071 bitVect *regsUnneeded;
3074 _G.currentFunc = NULL;
3075 if (IFFUNC_ISNAKED(sym->type))
3077 emitcode(";", "naked function: no epilogue.");
3078 if (options.debug && currFunc)
3079 debugFile->writeEndFunction (currFunc, ic, 0);
3083 if (IFFUNC_ISCRITICAL (sym->type))
3085 emitcode ("pop", "psw"); /* restore ea via c in psw */
3086 emitcode ("mov", "ea,c");
3089 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3091 emitcode ("mov", "sp,_bp");
3092 emitcode ("pop", "_bp");
3094 if (options.useXstack)
3096 emitcode ("xch", "a,_bpx");
3097 emitcode ("mov", "r0,a");
3098 emitcode ("dec", "r0");
3099 emitcode ("movx", "a,@r0");
3100 emitcode ("xch", "a,_bpx");
3101 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3105 /* restore the register bank */
3106 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3108 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3109 || !options.useXstack)
3111 /* Special case of ISR using non-zero bank with useXstack
3114 emitcode ("pop", "psw");
3118 if (IFFUNC_ISISR (sym->type))
3121 /* now we need to restore the registers */
3122 /* if this isr has no bank i.e. is going to
3123 run with bank 0 , then we need to save more
3125 if (!FUNC_REGBANK (sym->type))
3127 /* if this function does not call any other
3128 function then we can be economical and
3129 save only those registers that are used */
3130 if (!IFFUNC_HASFCALL(sym->type))
3134 /* if any registers used */
3137 /* save the registers used */
3138 for (i = sym->regsUsed->size; i >= 0; i--)
3140 if (bitVectBitValue (sym->regsUsed, i))
3141 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3147 if (options.parms_in_bank1) {
3149 for (i = 7 ; i >= 0 ; i-- ) {
3150 emitcode ("pop","%s",rb1regs[i]);
3153 /* this function has a function call cannot
3154 determines register usage so we will have to pop the
3156 unsaveRBank (0, ic, FALSE);
3161 /* This ISR uses a non-zero bank.
3163 * Restore any register banks saved by genFunction
3166 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3169 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3171 if (savedBanks & (1 << ix))
3173 unsaveRBank(ix, NULL, FALSE);
3177 if (options.useXstack)
3179 /* Restore bank AFTER calling unsaveRBank,
3180 * since it can trash r0.
3182 emitcode ("pop", "psw");
3186 if (!inExcludeList ("dph"))
3187 emitcode ("pop", "dph");
3188 if (!inExcludeList ("dpl"))
3189 emitcode ("pop", "dpl");
3190 if (!inExcludeList ("b"))
3191 emitcode ("pop", "b");
3192 if (!inExcludeList ("acc"))
3193 emitcode ("pop", "acc");
3195 /* if debug then send end of function */
3196 if (options.debug && currFunc)
3198 debugFile->writeEndFunction (currFunc, ic, 1);
3201 emitcode ("reti", "");
3205 if (IFFUNC_CALLEESAVES(sym->type))
3209 /* if any registers used */
3212 /* save the registers used */
3213 for (i = sym->regsUsed->size; i >= 0; i--)
3215 if (bitVectBitValue (sym->regsUsed, i) ||
3216 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3217 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3220 else if (mcs51_ptrRegReq)
3222 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3223 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3228 /* if debug then send end of function */
3229 if (options.debug && currFunc)
3231 debugFile->writeEndFunction (currFunc, ic, 1);
3234 emitcode ("ret", "");
3237 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3240 /* If this was an interrupt handler using bank 0 that called another */
3241 /* function, then all registers must be saved; nothing to optimized. */
3242 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3243 && !FUNC_REGBANK(sym->type))
3246 /* There are no push/pops to optimize if not callee-saves or ISR */
3247 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3250 /* If there were stack parameters, we cannot optimize without also */
3251 /* fixing all of the stack offsets; this is too dificult to consider. */
3252 if (FUNC_HASSTACKPARM(sym->type))
3255 /* Compute the registers actually used */
3256 regsUsed = newBitVect (mcs51_nRegs);
3257 regsUsedPrologue = newBitVect (mcs51_nRegs);
3260 if (lnp->ic && lnp->ic->op == FUNCTION)
3261 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3263 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3265 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3266 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3273 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3274 && !bitVectBitValue (regsUsed, CND_IDX))
3276 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3277 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3278 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3279 bitVectUnSetBit (regsUsed, CND_IDX);
3282 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3284 /* If this was an interrupt handler that called another function */
3285 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3286 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3288 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3289 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3290 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3291 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3292 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3295 /* Remove the unneeded push/pops */
3296 regsUnneeded = newBitVect (mcs51_nRegs);
3299 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3301 if (!strncmp(lnp->line, "push", 4))
3303 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3304 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3306 connectLine (lnp->prev, lnp->next);
3307 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3310 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3312 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3313 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3315 connectLine (lnp->prev, lnp->next);
3316 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3323 for (idx = 0; idx < regsUnneeded->size; idx++)
3324 if (bitVectBitValue (regsUnneeded, idx))
3325 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3327 freeBitVect (regsUnneeded);
3328 freeBitVect (regsUsed);
3329 freeBitVect (regsUsedPrologue);
3332 /*-----------------------------------------------------------------*/
3333 /* genRet - generate code for return statement */
3334 /*-----------------------------------------------------------------*/
3338 int size, offset = 0, pushed = 0;
3340 D(emitcode ("; genRet",""));
3342 /* if we have no return value then
3343 just generate the "ret" */
3347 /* we have something to return then
3348 move the return value into place */
3349 aopOp (IC_LEFT (ic), ic, FALSE);
3350 size = AOP_SIZE (IC_LEFT (ic));
3355 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3358 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3360 emitcode ("push", "%s", l);
3365 l = aopGet (AOP (IC_LEFT (ic)), offset,
3367 if (strcmp (fReturn[offset], l))
3368 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3377 if (strcmp (fReturn[pushed], "a"))
3378 emitcode ("pop", fReturn[pushed]);
3380 emitcode ("pop", "acc");
3383 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3386 /* generate a jump to the return label
3387 if the next is not the return statement */
3388 if (!(ic->next && ic->next->op == LABEL &&
3389 IC_LABEL (ic->next) == returnLabel))
3391 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3395 /*-----------------------------------------------------------------*/
3396 /* genLabel - generates a label */
3397 /*-----------------------------------------------------------------*/
3399 genLabel (iCode * ic)
3401 /* special case never generate */
3402 if (IC_LABEL (ic) == entryLabel)
3405 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3408 /*-----------------------------------------------------------------*/
3409 /* genGoto - generates a ljmp */
3410 /*-----------------------------------------------------------------*/
3412 genGoto (iCode * ic)
3414 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3417 /*-----------------------------------------------------------------*/
3418 /* findLabelBackwards: walks back through the iCode chain looking */
3419 /* for the given label. Returns number of iCode instructions */
3420 /* between that label and given ic. */
3421 /* Returns zero if label not found. */
3422 /*-----------------------------------------------------------------*/
3424 findLabelBackwards (iCode * ic, int key)
3433 /* If we have any pushes or pops, we cannot predict the distance.
3434 I don't like this at all, this should be dealt with in the
3436 if (ic->op == IPUSH || ic->op == IPOP) {
3440 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3449 /*-----------------------------------------------------------------*/
3450 /* genPlusIncr :- does addition with increment if possible */
3451 /*-----------------------------------------------------------------*/
3453 genPlusIncr (iCode * ic)
3455 unsigned int icount;
3456 unsigned int size = getDataSize (IC_RESULT (ic));
3458 /* will try to generate an increment */
3459 /* if the right side is not a literal
3461 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3464 /* if the literal value of the right hand side
3465 is greater than 4 then it is not worth it */
3466 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3469 D(emitcode ("; genPlusIncr",""));
3471 /* if increment >=16 bits in register or direct space */
3472 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3473 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3481 /* If the next instruction is a goto and the goto target
3482 * is < 10 instructions previous to this, we can generate
3483 * jumps straight to that target.
3485 if (ic->next && ic->next->op == GOTO
3486 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3487 && labelRange <= 10)
3489 emitcode (";", "tail increment optimized");
3490 tlbl = IC_LABEL (ic->next);
3495 tlbl = newiTempLabel (NULL);
3498 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3499 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3500 IS_AOP_PREG (IC_RESULT (ic)))
3501 emitcode ("cjne", "%s,#0x00,%05d$",
3502 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3506 emitcode ("clr", "a");
3507 emitcode ("cjne", "a,%s,%05d$",
3508 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3512 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3515 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3516 IS_AOP_PREG (IC_RESULT (ic)))
3517 emitcode ("cjne", "%s,#0x00,%05d$",
3518 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3521 emitcode ("cjne", "a,%s,%05d$",
3522 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3525 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3529 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3530 IS_AOP_PREG (IC_RESULT (ic)))
3531 emitcode ("cjne", "%s,#0x00,%05d$",
3532 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3536 emitcode ("cjne", "a,%s,%05d$",
3537 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3540 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3545 emitcode ("", "%05d$:", tlbl->key + 100);
3550 /* if the sizes are greater than 1 then we cannot */
3551 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3552 AOP_SIZE (IC_LEFT (ic)) > 1)
3555 /* we can if the aops of the left & result match or
3556 if they are in registers and the registers are the
3558 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3563 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3564 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3565 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3571 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3580 /*-----------------------------------------------------------------*/
3581 /* outBitAcc - output a bit in acc */
3582 /*-----------------------------------------------------------------*/
3584 outBitAcc (operand * result)
3586 symbol *tlbl = newiTempLabel (NULL);
3587 /* if the result is a bit */
3588 if (AOP_TYPE (result) == AOP_CRY)
3590 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3594 emitcode ("jz", "%05d$", tlbl->key + 100);
3595 emitcode ("mov", "a,%s", one);
3596 emitcode ("", "%05d$:", tlbl->key + 100);
3601 /*-----------------------------------------------------------------*/
3602 /* genPlusBits - generates code for addition of two bits */
3603 /*-----------------------------------------------------------------*/
3605 genPlusBits (iCode * ic)
3607 D(emitcode ("; genPlusBits",""));
3609 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3611 symbol *lbl = newiTempLabel (NULL);
3612 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3613 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3614 emitcode ("cpl", "c");
3615 emitcode ("", "%05d$:", (lbl->key + 100));
3616 outBitC (IC_RESULT (ic));
3620 emitcode ("clr", "a");
3621 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3622 emitcode ("rlc", "a");
3623 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3624 emitcode ("addc", "a,#0x00");
3625 outAcc (IC_RESULT (ic));
3630 /* This is the original version of this code.
3632 * This is being kept around for reference,
3633 * because I am not entirely sure I got it right...
3636 adjustArithmeticResult (iCode * ic)
3638 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3639 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3640 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3641 aopPut (AOP (IC_RESULT (ic)),
3642 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3644 isOperandVolatile (IC_RESULT (ic), FALSE));
3646 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3647 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3648 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3649 aopPut (AOP (IC_RESULT (ic)),
3650 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3652 isOperandVolatile (IC_RESULT (ic), FALSE));
3654 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3655 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3656 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3657 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3658 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3661 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3662 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3666 /* This is the pure and virtuous version of this code.
3667 * I'm pretty certain it's right, but not enough to toss the old
3671 adjustArithmeticResult (iCode * ic)
3673 if (opIsGptr (IC_RESULT (ic)) &&
3674 opIsGptr (IC_LEFT (ic)) &&
3675 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3677 aopPut (AOP (IC_RESULT (ic)),
3678 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3680 isOperandVolatile (IC_RESULT (ic), FALSE));
3683 if (opIsGptr (IC_RESULT (ic)) &&
3684 opIsGptr (IC_RIGHT (ic)) &&
3685 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3687 aopPut (AOP (IC_RESULT (ic)),
3688 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3690 isOperandVolatile (IC_RESULT (ic), FALSE));
3693 if (opIsGptr (IC_RESULT (ic)) &&
3694 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3695 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3696 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3697 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3700 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3701 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3706 /*-----------------------------------------------------------------*/
3707 /* genPlus - generates code for addition */
3708 /*-----------------------------------------------------------------*/
3710 genPlus (iCode * ic)
3712 int size, offset = 0;
3715 asmop *leftOp, *rightOp;
3718 /* special cases :- */
3720 D(emitcode ("; genPlus",""));
3722 aopOp (IC_LEFT (ic), ic, FALSE);
3723 aopOp (IC_RIGHT (ic), ic, FALSE);
3724 aopOp (IC_RESULT (ic), ic, TRUE);
3726 /* if literal, literal on the right or
3727 if left requires ACC or right is already
3729 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3730 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3731 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3733 operand *t = IC_RIGHT (ic);
3734 IC_RIGHT (ic) = IC_LEFT (ic);
3738 /* if both left & right are in bit
3740 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3741 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3747 /* if left in bit space & right literal */
3748 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3749 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3751 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3752 /* if result in bit space */
3753 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3755 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3756 emitcode ("cpl", "c");
3757 outBitC (IC_RESULT (ic));
3761 size = getDataSize (IC_RESULT (ic));
3764 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3765 emitcode ("addc", "a,#00");
3766 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3772 /* if I can do an increment instead
3773 of add then GOOD for ME */
3774 if (genPlusIncr (ic) == TRUE)
3777 size = getDataSize (IC_RESULT (ic));
3778 leftOp = AOP(IC_LEFT(ic));
3779 rightOp = AOP(IC_RIGHT(ic));
3782 /* if this is an add for an array access
3783 at a 256 byte boundary */
3785 && AOP_TYPE (op) == AOP_IMMD
3787 && IS_SPEC (OP_SYM_ETYPE (op))
3788 && SPEC_ABSA (OP_SYM_ETYPE (op))
3789 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3792 D(emitcode ("; genPlus aligned array",""));
3793 aopPut (AOP (IC_RESULT (ic)),
3794 aopGet (rightOp, 0, FALSE, FALSE),
3796 isOperandVolatile (IC_RESULT (ic), FALSE));
3798 if( 1 == getDataSize (IC_RIGHT (ic)) )
3800 aopPut (AOP (IC_RESULT (ic)),
3801 aopGet (leftOp, 1, FALSE, FALSE),
3803 isOperandVolatile (IC_RESULT (ic), FALSE));
3807 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3808 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3809 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3814 /* if the lower bytes of a literal are zero skip the addition */
3815 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3817 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3818 (skip_bytes+1 < size))
3823 D(emitcode ("; genPlus shortcut",""));
3828 if( offset >= skip_bytes )
3830 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3833 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3835 emitcode("xch", "a,b");
3836 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3837 emitcode (add, "a,b");
3840 else if (aopGetUsesAcc (leftOp, offset))
3842 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3843 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3847 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3848 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3850 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3851 add = "addc"; /* further adds must propagate carry */
3855 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3856 isOperandVolatile (IC_RESULT (ic), FALSE))
3859 aopPut (AOP (IC_RESULT (ic)),
3860 aopGet (leftOp, offset, FALSE, FALSE),
3862 isOperandVolatile (IC_RESULT (ic), FALSE));
3868 adjustArithmeticResult (ic);
3871 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3872 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3873 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3876 /*-----------------------------------------------------------------*/
3877 /* genMinusDec :- does subtraction with deccrement if possible */
3878 /*-----------------------------------------------------------------*/
3880 genMinusDec (iCode * ic)
3882 unsigned int icount;
3883 unsigned int size = getDataSize (IC_RESULT (ic));
3885 /* will try to generate an increment */
3886 /* if the right side is not a literal
3888 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3891 /* if the literal value of the right hand side
3892 is greater than 4 then it is not worth it */
3893 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3896 D(emitcode ("; genMinusDec",""));
3898 /* if decrement >=16 bits in register or direct space */
3899 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3900 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3908 /* If the next instruction is a goto and the goto target
3909 * is <= 10 instructions previous to this, we can generate
3910 * jumps straight to that target.
3912 if (ic->next && ic->next->op == GOTO
3913 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3914 && labelRange <= 10)
3916 emitcode (";", "tail decrement optimized");
3917 tlbl = IC_LABEL (ic->next);
3922 tlbl = newiTempLabel (NULL);
3926 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3927 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3928 IS_AOP_PREG (IC_RESULT (ic)))
3929 emitcode ("cjne", "%s,#0xff,%05d$"
3930 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3934 emitcode ("mov", "a,#0xff");
3935 emitcode ("cjne", "a,%s,%05d$"
3936 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3939 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3942 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3943 IS_AOP_PREG (IC_RESULT (ic)))
3944 emitcode ("cjne", "%s,#0xff,%05d$"
3945 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3949 emitcode ("cjne", "a,%s,%05d$"
3950 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3953 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3957 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3958 IS_AOP_PREG (IC_RESULT (ic)))
3959 emitcode ("cjne", "%s,#0xff,%05d$"
3960 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3964 emitcode ("cjne", "a,%s,%05d$"
3965 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3968 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3972 emitcode ("", "%05d$:", tlbl->key + 100);
3977 /* if the sizes are greater than 1 then we cannot */
3978 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3979 AOP_SIZE (IC_LEFT (ic)) > 1)
3982 /* we can if the aops of the left & result match or
3983 if they are in registers and the registers are the
3985 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3989 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3997 /*-----------------------------------------------------------------*/
3998 /* addSign - complete with sign */
3999 /*-----------------------------------------------------------------*/
4001 addSign (operand * result, int offset, int sign)
4003 int size = (getDataSize (result) - offset);
4008 emitcode ("rlc", "a");
4009 emitcode ("subb", "a,acc");
4011 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4015 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4019 /*-----------------------------------------------------------------*/
4020 /* genMinusBits - generates code for subtraction of two bits */
4021 /*-----------------------------------------------------------------*/
4023 genMinusBits (iCode * ic)
4025 symbol *lbl = newiTempLabel (NULL);
4027 D(emitcode ("; genMinusBits",""));
4029 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4031 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4032 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4033 emitcode ("cpl", "c");
4034 emitcode ("", "%05d$:", (lbl->key + 100));
4035 outBitC (IC_RESULT (ic));
4039 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4040 emitcode ("subb", "a,acc");
4041 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4042 emitcode ("inc", "a");
4043 emitcode ("", "%05d$:", (lbl->key + 100));
4044 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4045 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4049 /*-----------------------------------------------------------------*/
4050 /* genMinus - generates code for subtraction */
4051 /*-----------------------------------------------------------------*/
4053 genMinus (iCode * ic)
4055 int size, offset = 0;
4057 D(emitcode ("; genMinus",""));
4059 aopOp (IC_LEFT (ic), ic, FALSE);
4060 aopOp (IC_RIGHT (ic), ic, FALSE);
4061 aopOp (IC_RESULT (ic), ic, TRUE);
4063 /* special cases :- */
4064 /* if both left & right are in bit space */
4065 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4066 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4072 /* if I can do an decrement instead
4073 of subtract then GOOD for ME */
4074 if (genMinusDec (ic) == TRUE)
4077 size = getDataSize (IC_RESULT (ic));
4079 /* if literal, add a,#-lit, else normal subb */
4080 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4082 unsigned long lit = 0L;
4084 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4089 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
4090 /* first add without previous c */
4092 if (!size && lit== (unsigned long) -1) {
4093 emitcode ("dec", "a");
4095 emitcode ("add", "a,#0x%02x",
4096 (unsigned int) (lit & 0x0FFL));
4099 emitcode ("addc", "a,#0x%02x",
4100 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4102 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4107 asmop *leftOp, *rightOp;
4109 leftOp = AOP(IC_LEFT(ic));
4110 rightOp = AOP(IC_RIGHT(ic));
4114 if (aopGetUsesAcc(rightOp, offset)) {
4115 if (aopGetUsesAcc(leftOp, offset)) {
4118 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4120 emitcode ("mov", "b,a");
4123 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4124 emitcode ("subb", "a,b");
4127 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4128 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4130 emitcode( "setb", "c");
4132 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4133 emitcode("cpl", "a");
4136 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4139 emitcode ("subb", "a,%s",
4140 aopGet(rightOp, offset, FALSE, TRUE));
4143 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4148 adjustArithmeticResult (ic);
4151 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4152 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4153 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4157 /*-----------------------------------------------------------------*/
4158 /* genMultbits :- multiplication of bits */
4159 /*-----------------------------------------------------------------*/
4161 genMultbits (operand * left,
4165 D(emitcode ("; genMultbits",""));
4167 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4168 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4172 /*-----------------------------------------------------------------*/
4173 /* genMultOneByte : 8*8=8/16 bit multiplication */
4174 /*-----------------------------------------------------------------*/
4176 genMultOneByte (operand * left,
4181 int size = AOP_SIZE (result);
4182 bool runtimeSign, compiletimeSign;
4183 bool lUnsigned, rUnsigned, pushedB;
4185 D(emitcode ("; genMultOneByte",""));
4187 if (size < 1 || size > 2)
4189 /* this should never happen */
4190 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4191 AOP_SIZE(result), __FILE__, lineno);
4195 /* (if two literals: the value is computed before) */
4196 /* if one literal, literal on the right */
4197 if (AOP_TYPE (left) == AOP_LIT)
4202 /* emitcode (";", "swapped left and right"); */
4204 /* if no literal, unsigned on the right: shorter code */
4205 if ( AOP_TYPE (right) != AOP_LIT
4206 && SPEC_USIGN (getSpec (operandType (left))))
4213 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4214 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4218 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4219 no need to take care about the signedness! */
4220 || (lUnsigned && rUnsigned))
4222 /* just an unsigned 8 * 8 = 8 multiply
4224 /* emitcode (";","unsigned"); */
4225 /* TODO: check for accumulator clash between left & right aops? */
4227 if (AOP_TYPE (right) == AOP_LIT)
4229 /* moving to accumulator first helps peepholes */
4230 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4231 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4235 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4236 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4239 emitcode ("mul", "ab");
4240 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4242 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4248 /* we have to do a signed multiply */
4249 /* emitcode (";", "signed"); */
4251 /* now sign adjust for both left & right */
4253 /* let's see what's needed: */
4254 /* apply negative sign during runtime */
4255 runtimeSign = FALSE;
4256 /* negative sign from literals */
4257 compiletimeSign = FALSE;
4261 if (AOP_TYPE(left) == AOP_LIT)
4263 /* signed literal */
4264 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4266 compiletimeSign = TRUE;
4269 /* signed but not literal */
4275 if (AOP_TYPE(right) == AOP_LIT)
4277 /* signed literal */
4278 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4280 compiletimeSign ^= TRUE;
4283 /* signed but not literal */
4287 /* initialize F0, which stores the runtime sign */
4290 if (compiletimeSign)
4291 emitcode ("setb", "F0"); /* set sign flag */
4293 emitcode ("clr", "F0"); /* reset sign flag */
4296 /* save the signs of the operands */
4297 if (AOP_TYPE(right) == AOP_LIT)
4299 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4301 if (!rUnsigned && val < 0)
4302 emitcode ("mov", "b,#0x%02x", -val);
4304 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4306 else /* ! literal */
4308 if (rUnsigned) /* emitcode (";", "signed"); */
4310 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4313 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4314 lbl = newiTempLabel (NULL);
4315 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4316 emitcode ("cpl", "F0"); /* complement sign flag */
4317 emitcode ("cpl", "a"); /* 2's complement */
4318 emitcode ("inc", "a");
4319 emitcode ("", "%05d$:", (lbl->key + 100));
4320 emitcode ("mov", "b,a");
4324 if (AOP_TYPE(left) == AOP_LIT)
4326 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4328 if (!lUnsigned && val < 0)
4329 emitcode ("mov", "a,#0x%02x", -val);
4331 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4333 else /* ! literal */
4335 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4339 lbl = newiTempLabel (NULL);
4340 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4341 emitcode ("cpl", "F0"); /* complement sign flag */
4342 emitcode ("cpl", "a"); /* 2's complement */
4343 emitcode ("inc", "a");
4344 emitcode ("", "%05d$:", (lbl->key + 100));
4348 /* now the multiplication */
4349 emitcode ("mul", "ab");
4350 if (runtimeSign || compiletimeSign)
4352 lbl = newiTempLabel (NULL);
4354 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4355 emitcode ("cpl", "a"); /* lsb 2's complement */
4357 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4360 emitcode ("add", "a,#1"); /* this sets carry flag */
4361 emitcode ("xch", "a,b");
4362 emitcode ("cpl", "a"); /* msb 2's complement */
4363 emitcode ("addc", "a,#0");
4364 emitcode ("xch", "a,b");
4366 emitcode ("", "%05d$:", (lbl->key + 100));
4368 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4370 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4375 /*-----------------------------------------------------------------*/
4376 /* genMult - generates code for multiplication */
4377 /*-----------------------------------------------------------------*/
4379 genMult (iCode * ic)
4381 operand *left = IC_LEFT (ic);
4382 operand *right = IC_RIGHT (ic);
4383 operand *result = IC_RESULT (ic);
4385 D(emitcode ("; genMult",""));
4387 /* assign the amsops */
4388 aopOp (left, ic, FALSE);
4389 aopOp (right, ic, FALSE);
4390 aopOp (result, ic, TRUE);
4392 /* special cases first */
4394 if (AOP_TYPE (left) == AOP_CRY &&
4395 AOP_TYPE (right) == AOP_CRY)
4397 genMultbits (left, right, result);
4401 /* if both are of size == 1 */
4402 #if 0 // one of them can be a sloc shared with the result
4403 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4405 if (getSize(operandType(left)) == 1 &&
4406 getSize(operandType(right)) == 1)
4409 genMultOneByte (left, right, result);
4413 /* should have been converted to function call */
4414 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4415 getSize(OP_SYMBOL(right)->type));
4419 freeAsmop (result, NULL, ic, TRUE);
4420 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4421 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4424 /*-----------------------------------------------------------------*/
4425 /* genDivbits :- division of bits */
4426 /*-----------------------------------------------------------------*/
4428 genDivbits (operand * left,
4435 D(emitcode ("; genDivbits",""));
4439 /* the result must be bit */
4440 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4441 l = aopGet (AOP (left), 0, FALSE, FALSE);
4445 emitcode ("div", "ab");
4446 emitcode ("rrc", "a");
4450 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4453 /*-----------------------------------------------------------------*/
4454 /* genDivOneByte : 8 bit division */
4455 /*-----------------------------------------------------------------*/
4457 genDivOneByte (operand * left,
4461 bool lUnsigned, rUnsigned, pushedB;
4462 bool runtimeSign, compiletimeSign;
4466 D(emitcode ("; genDivOneByte",""));
4468 /* Why is it necessary that genDivOneByte() can return an int result?
4471 volatile unsigned char uc;
4472 volatile signed char sc1, sc2;
4485 In all cases a one byte result would overflow, the following cast to int
4486 would return the wrong result.
4488 Two possible solution:
4489 a) cast operands to int, if ((unsigned) / (signed)) or
4490 ((signed) / (signed))
4491 b) return an 16 bit signed int; this is what we're doing here!
4494 size = AOP_SIZE (result) - 1;
4496 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4497 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4501 /* signed or unsigned */
4502 if (lUnsigned && rUnsigned)
4504 /* unsigned is easy */
4505 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4506 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4507 emitcode ("div", "ab");
4508 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4510 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4516 /* signed is a little bit more difficult */
4518 /* now sign adjust for both left & right */
4520 /* let's see what's needed: */
4521 /* apply negative sign during runtime */
4522 runtimeSign = FALSE;
4523 /* negative sign from literals */
4524 compiletimeSign = FALSE;
4528 if (AOP_TYPE(left) == AOP_LIT)
4530 /* signed literal */
4531 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4533 compiletimeSign = TRUE;
4536 /* signed but not literal */
4542 if (AOP_TYPE(right) == AOP_LIT)
4544 /* signed literal */
4545 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4547 compiletimeSign ^= TRUE;
4550 /* signed but not literal */
4554 /* initialize F0, which stores the runtime sign */
4557 if (compiletimeSign)
4558 emitcode ("setb", "F0"); /* set sign flag */
4560 emitcode ("clr", "F0"); /* reset sign flag */
4563 /* save the signs of the operands */
4564 if (AOP_TYPE(right) == AOP_LIT)
4566 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4568 if (!rUnsigned && val < 0)
4569 emitcode ("mov", "b,#0x%02x", -val);
4571 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4573 else /* ! literal */
4576 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4579 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4580 lbl = newiTempLabel (NULL);
4581 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4582 emitcode ("cpl", "F0"); /* complement sign flag */
4583 emitcode ("cpl", "a"); /* 2's complement */
4584 emitcode ("inc", "a");
4585 emitcode ("", "%05d$:", (lbl->key + 100));
4586 emitcode ("mov", "b,a");
4590 if (AOP_TYPE(left) == AOP_LIT)
4592 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4594 if (!lUnsigned && val < 0)
4595 emitcode ("mov", "a,#0x%02x", -val);
4597 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4599 else /* ! literal */
4601 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4605 lbl = newiTempLabel (NULL);
4606 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4607 emitcode ("cpl", "F0"); /* complement sign flag */
4608 emitcode ("cpl", "a"); /* 2's complement */
4609 emitcode ("inc", "a");
4610 emitcode ("", "%05d$:", (lbl->key + 100));
4614 /* now the division */
4615 emitcode ("div", "ab");
4617 if (runtimeSign || compiletimeSign)
4619 lbl = newiTempLabel (NULL);
4621 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4622 emitcode ("cpl", "a"); /* lsb 2's complement */
4623 emitcode ("inc", "a");
4624 emitcode ("", "%05d$:", (lbl->key + 100));
4626 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4629 /* msb is 0x00 or 0xff depending on the sign */
4632 emitcode ("mov", "c,F0");
4633 emitcode ("subb", "a,acc");
4635 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4637 else /* compiletimeSign */
4639 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4644 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4646 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4652 /*-----------------------------------------------------------------*/
4653 /* genDiv - generates code for division */
4654 /*-----------------------------------------------------------------*/
4658 operand *left = IC_LEFT (ic);
4659 operand *right = IC_RIGHT (ic);
4660 operand *result = IC_RESULT (ic);
4662 D(emitcode ("; genDiv",""));
4664 /* assign the amsops */
4665 aopOp (left, ic, FALSE);
4666 aopOp (right, ic, FALSE);
4667 aopOp (result, ic, TRUE);
4669 /* special cases first */
4671 if (AOP_TYPE (left) == AOP_CRY &&
4672 AOP_TYPE (right) == AOP_CRY)
4674 genDivbits (left, right, result);
4678 /* if both are of size == 1 */
4679 if (AOP_SIZE (left) == 1 &&
4680 AOP_SIZE (right) == 1)
4682 genDivOneByte (left, right, result);
4686 /* should have been converted to function call */
4689 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4690 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4691 freeAsmop (result, NULL, ic, TRUE);
4694 /*-----------------------------------------------------------------*/
4695 /* genModbits :- modulus of bits */
4696 /*-----------------------------------------------------------------*/
4698 genModbits (operand * left,
4705 D(emitcode ("; genModbits",""));
4709 /* the result must be bit */
4710 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4711 l = aopGet (AOP (left), 0, FALSE, FALSE);
4715 emitcode ("div", "ab");
4716 emitcode ("mov", "a,b");
4717 emitcode ("rrc", "a");
4721 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4724 /*-----------------------------------------------------------------*/
4725 /* genModOneByte : 8 bit modulus */
4726 /*-----------------------------------------------------------------*/
4728 genModOneByte (operand * left,
4732 bool lUnsigned, rUnsigned, pushedB;
4733 bool runtimeSign, compiletimeSign;
4737 D(emitcode ("; genModOneByte",""));
4739 size = AOP_SIZE (result) - 1;
4741 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4742 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4744 /* if right is a literal, check it for 2^n */
4745 if (AOP_TYPE(right) == AOP_LIT)
4747 unsigned char val = abs((int) operandLitValue(right));
4748 symbol *lbl2 = NULL;
4752 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
4761 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4762 "modulus of unsigned char by 2^n literal shouldn't be processed here");
4763 /* because iCode should have been changed to genAnd */
4764 /* see file "SDCCopt.c", function "convertToFcall()" */
4766 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4767 emitcode ("mov", "c,acc.7");
4768 emitcode ("anl", "a,#0x%02x", val - 1);
4769 lbl = newiTempLabel (NULL);
4770 emitcode ("jz", "%05d$", (lbl->key + 100));
4771 emitcode ("jnc", "%05d$", (lbl->key + 100));
4772 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
4778 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4780 aopPut (AOP (result), "#0xff", offs2++, isOperandVolatile (result, FALSE));
4781 lbl2 = newiTempLabel (NULL);
4782 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
4784 emitcode ("", "%05d$:", (lbl->key + 100));
4785 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4787 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4790 emitcode ("", "%05d$:", (lbl2->key + 100));
4801 /* signed or unsigned */
4802 if (lUnsigned && rUnsigned)
4804 /* unsigned is easy */
4805 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4806 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4807 emitcode ("div", "ab");
4808 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4810 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4816 /* signed is a little bit more difficult */
4818 /* now sign adjust for both left & right */
4820 /* modulus: sign of the right operand has no influence on the result! */
4821 if (AOP_TYPE(right) == AOP_LIT)
4823 signed char val = (char) operandLitValue(right);
4825 if (!rUnsigned && val < 0)
4826 emitcode ("mov", "b,#0x%02x", -val);
4828 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4830 else /* not literal */
4833 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4836 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4837 lbl = newiTempLabel (NULL);
4838 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4839 emitcode ("cpl", "a"); /* 2's complement */
4840 emitcode ("inc", "a");
4841 emitcode ("", "%05d$:", (lbl->key + 100));
4842 emitcode ("mov", "b,a");
4846 /* let's see what's needed: */
4847 /* apply negative sign during runtime */
4848 runtimeSign = FALSE;
4849 /* negative sign from literals */
4850 compiletimeSign = FALSE;
4852 /* sign adjust left side */
4853 if (AOP_TYPE(left) == AOP_LIT)
4855 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4857 if (!lUnsigned && val < 0)
4859 compiletimeSign = TRUE; /* set sign flag */
4860 emitcode ("mov", "a,#0x%02x", -val);
4863 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4865 else /* ! literal */
4867 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4872 emitcode ("clr", "F0"); /* clear sign flag */
4874 lbl = newiTempLabel (NULL);
4875 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4876 emitcode ("setb", "F0"); /* set sign flag */
4877 emitcode ("cpl", "a"); /* 2's complement */
4878 emitcode ("inc", "a");
4879 emitcode ("", "%05d$:", (lbl->key + 100));
4883 /* now the modulus */
4884 emitcode ("div", "ab");
4886 if (runtimeSign || compiletimeSign)
4888 emitcode ("mov", "a,b");
4889 lbl = newiTempLabel (NULL);
4891 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4892 emitcode ("cpl", "a"); /* 2's complement */
4893 emitcode ("inc", "a");
4894 emitcode ("", "%05d$:", (lbl->key + 100));
4896 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4899 /* msb is 0x00 or 0xff depending on the sign */
4902 emitcode ("mov", "c,F0");
4903 emitcode ("subb", "a,acc");
4905 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4907 else /* compiletimeSign */
4909 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4914 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4916 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4922 /*-----------------------------------------------------------------*/
4923 /* genMod - generates code for division */
4924 /*-----------------------------------------------------------------*/
4928 operand *left = IC_LEFT (ic);
4929 operand *right = IC_RIGHT (ic);
4930 operand *result = IC_RESULT (ic);
4932 D(emitcode ("; genMod",""));
4934 /* assign the asmops */
4935 aopOp (left, ic, FALSE);
4936 aopOp (right, ic, FALSE);
4937 aopOp (result, ic, TRUE);
4939 /* special cases first */
4941 if (AOP_TYPE (left) == AOP_CRY &&
4942 AOP_TYPE (right) == AOP_CRY)
4944 genModbits (left, right, result);
4948 /* if both are of size == 1 */
4949 if (AOP_SIZE (left) == 1 &&
4950 AOP_SIZE (right) == 1)
4952 genModOneByte (left, right, result);
4956 /* should have been converted to function call */
4960 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4961 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4962 freeAsmop (result, NULL, ic, TRUE);
4965 /*-----------------------------------------------------------------*/
4966 /* genIfxJump :- will create a jump depending on the ifx */
4967 /*-----------------------------------------------------------------*/
4969 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4972 symbol *tlbl = newiTempLabel (NULL);
4975 D(emitcode ("; genIfxJump",""));
4977 /* if true label then we jump if condition
4981 jlbl = IC_TRUE (ic);
4982 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4983 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4987 /* false label is present */
4988 jlbl = IC_FALSE (ic);
4989 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4990 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4992 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4993 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4995 emitcode (inst, "%05d$", tlbl->key + 100);
4996 freeForBranchAsmop (result);
4997 freeForBranchAsmop (right);
4998 freeForBranchAsmop (left);
4999 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5000 emitcode ("", "%05d$:", tlbl->key + 100);
5002 /* mark the icode as generated */
5006 /*-----------------------------------------------------------------*/
5007 /* genCmp :- greater or less than comparison */
5008 /*-----------------------------------------------------------------*/
5010 genCmp (operand * left, operand * right,
5011 operand * result, iCode * ifx, int sign, iCode *ic)
5013 int size, offset = 0;
5014 unsigned long lit = 0L;
5017 D(emitcode ("; genCmp",""));
5019 /* if left & right are bit variables */
5020 if (AOP_TYPE (left) == AOP_CRY &&
5021 AOP_TYPE (right) == AOP_CRY)
5023 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5024 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5028 /* subtract right from left if at the
5029 end the carry flag is set then we know that
5030 left is greater than right */
5031 size = max (AOP_SIZE (left), AOP_SIZE (right));
5033 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5034 if ((size == 1) && !sign &&
5035 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5037 symbol *lbl = newiTempLabel (NULL);
5038 emitcode ("cjne", "%s,%s,%05d$",
5039 aopGet (AOP (left), offset, FALSE, FALSE),
5040 aopGet (AOP (right), offset, FALSE, FALSE),
5042 emitcode ("", "%05d$:", lbl->key + 100);
5046 if (AOP_TYPE (right) == AOP_LIT)
5048 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5049 /* optimize if(x < 0) or if(x >= 0) */
5058 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5059 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5061 genIfxJump (ifx, "acc.7", left, right, result);
5062 freeAsmop (right, NULL, ic, TRUE);
5063 freeAsmop (left, NULL, ic, TRUE);
5068 emitcode ("rlc", "a");
5076 bool pushedB = FALSE;
5077 rightInB = aopGetUsesAcc(AOP (right), offset);
5081 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5083 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5084 if (sign && size == 0)
5086 emitcode ("xrl", "a,#0x80");
5087 if (AOP_TYPE (right) == AOP_LIT)
5089 unsigned long lit = (unsigned long)
5090 floatFromVal (AOP (right)->aopu.aop_lit);
5091 emitcode ("subb", "a,#0x%02x",
5092 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5100 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5102 emitcode ("xrl", "b,#0x80");
5103 emitcode ("subb", "a,b");
5109 emitcode ("subb", "a,b");
5111 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5121 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5122 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5123 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5129 /* if the result is used in the next
5130 ifx conditional branch then generate
5131 code a little differently */
5133 genIfxJump (ifx, "c", NULL, NULL, result);
5136 /* leave the result in acc */
5140 /*-----------------------------------------------------------------*/
5141 /* genCmpGt :- greater than comparison */
5142 /*-----------------------------------------------------------------*/
5144 genCmpGt (iCode * ic, iCode * ifx)
5146 operand *left, *right, *result;
5147 sym_link *letype, *retype;
5150 D(emitcode ("; genCmpGt",""));
5152 left = IC_LEFT (ic);
5153 right = IC_RIGHT (ic);
5154 result = IC_RESULT (ic);
5156 letype = getSpec (operandType (left));
5157 retype = getSpec (operandType (right));
5158 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5159 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5160 /* assign the amsops */
5161 aopOp (left, ic, FALSE);
5162 aopOp (right, ic, FALSE);
5163 aopOp (result, ic, TRUE);
5165 genCmp (right, left, result, ifx, sign, ic);
5167 freeAsmop (result, NULL, ic, TRUE);
5170 /*-----------------------------------------------------------------*/
5171 /* genCmpLt - less than comparisons */
5172 /*-----------------------------------------------------------------*/
5174 genCmpLt (iCode * ic, iCode * ifx)
5176 operand *left, *right, *result;
5177 sym_link *letype, *retype;
5180 D(emitcode ("; genCmpLt",""));
5182 left = IC_LEFT (ic);
5183 right = IC_RIGHT (ic);
5184 result = IC_RESULT (ic);
5186 letype = getSpec (operandType (left));
5187 retype = getSpec (operandType (right));
5188 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5189 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5190 /* assign the amsops */
5191 aopOp (left, ic, FALSE);
5192 aopOp (right, ic, FALSE);
5193 aopOp (result, ic, TRUE);
5195 genCmp (left, right, result, ifx, sign,ic);
5197 freeAsmop (result, NULL, ic, TRUE);
5200 /*-----------------------------------------------------------------*/
5201 /* gencjneshort - compare and jump if not equal */
5202 /*-----------------------------------------------------------------*/
5204 gencjneshort (operand * left, operand * right, symbol * lbl)
5206 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5208 unsigned long lit = 0L;
5210 /* if the left side is a literal or
5211 if the right is in a pointer register and left
5213 if ((AOP_TYPE (left) == AOP_LIT) ||
5214 (AOP_TYPE (left) == AOP_IMMD) ||
5215 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5222 if (AOP_TYPE (right) == AOP_LIT)
5223 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5225 /* if the right side is a literal then anything goes */
5226 if (AOP_TYPE (right) == AOP_LIT &&
5227 AOP_TYPE (left) != AOP_DIR &&
5228 AOP_TYPE (left) != AOP_IMMD)
5232 emitcode ("cjne", "%s,%s,%05d$",
5233 aopGet (AOP (left), offset, FALSE, FALSE),
5234 aopGet (AOP (right), offset, FALSE, FALSE),
5240 /* if the right side is in a register or in direct space or
5241 if the left is a pointer register & right is not */
5242 else if (AOP_TYPE (right) == AOP_REG ||
5243 AOP_TYPE (right) == AOP_DIR ||
5244 AOP_TYPE (right) == AOP_LIT ||
5245 AOP_TYPE (right) == AOP_IMMD ||
5246 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5247 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5251 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5252 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5253 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5254 emitcode ("jnz", "%05d$", lbl->key + 100);
5256 emitcode ("cjne", "a,%s,%05d$",
5257 aopGet (AOP (right), offset, FALSE, TRUE),
5264 /* right is a pointer reg need both a & b */
5268 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5269 wassertl(!BINUSE, "B was in use");
5270 l = aopGet (AOP (left), offset, FALSE, FALSE);
5271 if (strcmp (l, "b"))
5272 emitcode ("mov", "b,%s", l);
5273 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5274 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5280 /*-----------------------------------------------------------------*/
5281 /* gencjne - compare and jump if not equal */
5282 /*-----------------------------------------------------------------*/
5284 gencjne (operand * left, operand * right, symbol * lbl)
5286 symbol *tlbl = newiTempLabel (NULL);
5288 gencjneshort (left, right, lbl);
5290 emitcode ("mov", "a,%s", one);
5291 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5292 emitcode ("", "%05d$:", lbl->key + 100);
5293 emitcode ("clr", "a");
5294 emitcode ("", "%05d$:", tlbl->key + 100);
5297 /*-----------------------------------------------------------------*/
5298 /* genCmpEq - generates code for equal to */
5299 /*-----------------------------------------------------------------*/
5301 genCmpEq (iCode * ic, iCode * ifx)
5303 operand *left, *right, *result;
5305 D(emitcode ("; genCmpEq",""));
5307 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5308 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5309 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5311 /* if literal, literal on the right or
5312 if the right is in a pointer register and left
5314 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5315 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5317 operand *t = IC_RIGHT (ic);
5318 IC_RIGHT (ic) = IC_LEFT (ic);
5322 if (ifx && !AOP_SIZE (result))
5325 /* if they are both bit variables */
5326 if (AOP_TYPE (left) == AOP_CRY &&
5327 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5329 if (AOP_TYPE (right) == AOP_LIT)
5331 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5334 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5335 emitcode ("cpl", "c");
5339 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5343 emitcode ("clr", "c");
5345 /* AOP_TYPE(right) == AOP_CRY */
5349 symbol *lbl = newiTempLabel (NULL);
5350 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5351 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5352 emitcode ("cpl", "c");
5353 emitcode ("", "%05d$:", (lbl->key + 100));
5355 /* if true label then we jump if condition
5357 tlbl = newiTempLabel (NULL);
5360 emitcode ("jnc", "%05d$", tlbl->key + 100);
5361 freeForBranchAsmop (result);
5362 freeForBranchAsmop (right);
5363 freeForBranchAsmop (left);
5364 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5368 emitcode ("jc", "%05d$", tlbl->key + 100);
5369 freeForBranchAsmop (result);
5370 freeForBranchAsmop (right);
5371 freeForBranchAsmop (left);
5372 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5374 emitcode ("", "%05d$:", tlbl->key + 100);
5378 tlbl = newiTempLabel (NULL);
5379 gencjneshort (left, right, tlbl);
5382 freeForBranchAsmop (result);
5383 freeForBranchAsmop (right);
5384 freeForBranchAsmop (left);
5385 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5386 emitcode ("", "%05d$:", tlbl->key + 100);
5390 symbol *lbl = newiTempLabel (NULL);
5391 emitcode ("sjmp", "%05d$", lbl->key + 100);
5392 emitcode ("", "%05d$:", tlbl->key + 100);
5393 freeForBranchAsmop (result);
5394 freeForBranchAsmop (right);
5395 freeForBranchAsmop (left);
5396 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5397 emitcode ("", "%05d$:", lbl->key + 100);
5400 /* mark the icode as generated */
5405 /* if they are both bit variables */
5406 if (AOP_TYPE (left) == AOP_CRY &&
5407 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5409 if (AOP_TYPE (right) == AOP_LIT)
5411 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5414 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5415 emitcode ("cpl", "c");
5419 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5423 emitcode ("clr", "c");
5425 /* AOP_TYPE(right) == AOP_CRY */
5429 symbol *lbl = newiTempLabel (NULL);
5430 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5431 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5432 emitcode ("cpl", "c");
5433 emitcode ("", "%05d$:", (lbl->key + 100));
5436 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5443 genIfxJump (ifx, "c", left, right, result);
5446 /* if the result is used in an arithmetic operation
5447 then put the result in place */
5452 gencjne (left, right, newiTempLabel (NULL));
5453 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5455 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5460 genIfxJump (ifx, "a", left, right, result);
5463 /* if the result is used in an arithmetic operation
5464 then put the result in place */
5465 if (AOP_TYPE (result) != AOP_CRY)
5467 /* leave the result in acc */
5471 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5472 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5473 freeAsmop (result, NULL, ic, TRUE);
5476 /*-----------------------------------------------------------------*/
5477 /* ifxForOp - returns the icode containing the ifx for operand */
5478 /*-----------------------------------------------------------------*/
5480 ifxForOp (operand * op, iCode * ic)
5482 /* if true symbol then needs to be assigned */
5483 if (IS_TRUE_SYMOP (op))
5486 /* if this has register type condition and
5487 the next instruction is ifx with the same operand
5488 and live to of the operand is upto the ifx only then */
5490 ic->next->op == IFX &&
5491 IC_COND (ic->next)->key == op->key &&
5492 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5498 /*-----------------------------------------------------------------*/
5499 /* hasInc - operand is incremented before any other use */
5500 /*-----------------------------------------------------------------*/
5502 hasInc (operand *op, iCode *ic,int osize)
5504 sym_link *type = operandType(op);
5505 sym_link *retype = getSpec (type);
5506 iCode *lic = ic->next;
5509 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5510 if (!IS_SYMOP(op)) return NULL;
5512 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5513 if (IS_AGGREGATE(type->next)) return NULL;
5514 if (osize != (isize = getSize(type->next))) return NULL;
5517 /* if operand of the form op = op + <sizeof *op> */
5518 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5519 isOperandEqual(IC_RESULT(lic),op) &&
5520 isOperandLiteral(IC_RIGHT(lic)) &&
5521 operandLitValue(IC_RIGHT(lic)) == isize) {
5524 /* if the operand used or deffed */
5525 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5528 /* if GOTO or IFX */
5529 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5535 /*-----------------------------------------------------------------*/
5536 /* genAndOp - for && operation */
5537 /*-----------------------------------------------------------------*/
5539 genAndOp (iCode * ic)
5541 operand *left, *right, *result;
5544 D(emitcode ("; genAndOp",""));
5546 /* note here that && operations that are in an
5547 if statement are taken away by backPatchLabels
5548 only those used in arthmetic operations remain */
5549 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5550 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5551 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5553 /* if both are bit variables */
5554 if (AOP_TYPE (left) == AOP_CRY &&
5555 AOP_TYPE (right) == AOP_CRY)
5557 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5558 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5563 tlbl = newiTempLabel (NULL);
5565 emitcode ("jz", "%05d$", tlbl->key + 100);
5567 emitcode ("", "%05d$:", tlbl->key + 100);
5571 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5572 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5573 freeAsmop (result, NULL, ic, TRUE);
5577 /*-----------------------------------------------------------------*/
5578 /* genOrOp - for || operation */
5579 /*-----------------------------------------------------------------*/
5581 genOrOp (iCode * ic)
5583 operand *left, *right, *result;
5586 D(emitcode ("; genOrOp",""));
5588 /* note here that || operations that are in an
5589 if statement are taken away by backPatchLabels
5590 only those used in arthmetic operations remain */
5591 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5592 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5593 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5595 /* if both are bit variables */
5596 if (AOP_TYPE (left) == AOP_CRY &&
5597 AOP_TYPE (right) == AOP_CRY)
5599 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5600 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5605 tlbl = newiTempLabel (NULL);
5607 emitcode ("jnz", "%05d$", tlbl->key + 100);
5609 emitcode ("", "%05d$:", tlbl->key + 100);
5613 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5614 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5615 freeAsmop (result, NULL, ic, TRUE);
5618 /*-----------------------------------------------------------------*/
5619 /* isLiteralBit - test if lit == 2^n */
5620 /*-----------------------------------------------------------------*/
5622 isLiteralBit (unsigned long lit)
5624 unsigned long pw[32] =
5625 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5626 0x100L, 0x200L, 0x400L, 0x800L,
5627 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5628 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5629 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5630 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5631 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5634 for (idx = 0; idx < 32; idx++)
5640 /*-----------------------------------------------------------------*/
5641 /* continueIfTrue - */
5642 /*-----------------------------------------------------------------*/
5644 continueIfTrue (iCode * ic)
5647 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5651 /*-----------------------------------------------------------------*/
5653 /*-----------------------------------------------------------------*/
5655 jumpIfTrue (iCode * ic)
5658 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5662 /*-----------------------------------------------------------------*/
5663 /* jmpTrueOrFalse - */
5664 /*-----------------------------------------------------------------*/
5666 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5668 // ugly but optimized by peephole
5671 symbol *nlbl = newiTempLabel (NULL);
5672 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5673 emitcode ("", "%05d$:", tlbl->key + 100);
5674 freeForBranchAsmop (result);
5675 freeForBranchAsmop (right);
5676 freeForBranchAsmop (left);
5677 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5678 emitcode ("", "%05d$:", nlbl->key + 100);
5682 freeForBranchAsmop (result);
5683 freeForBranchAsmop (right);
5684 freeForBranchAsmop (left);
5685 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5686 emitcode ("", "%05d$:", tlbl->key + 100);
5691 /*-----------------------------------------------------------------*/
5692 /* genAnd - code for and */
5693 /*-----------------------------------------------------------------*/
5695 genAnd (iCode * ic, iCode * ifx)
5697 operand *left, *right, *result;
5698 int size, offset = 0;
5699 unsigned long lit = 0L;
5703 D(emitcode ("; genAnd",""));
5705 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5706 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5707 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5710 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5712 AOP_TYPE (left), AOP_TYPE (right));
5713 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5715 AOP_SIZE (left), AOP_SIZE (right));
5718 /* if left is a literal & right is not then exchange them */
5719 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5720 AOP_NEEDSACC (left))
5722 operand *tmp = right;
5727 /* if result = right then exchange left and right */
5728 if (sameRegs (AOP (result), AOP (right)))
5730 operand *tmp = right;
5735 /* if right is bit then exchange them */
5736 if (AOP_TYPE (right) == AOP_CRY &&
5737 AOP_TYPE (left) != AOP_CRY)
5739 operand *tmp = right;
5743 if (AOP_TYPE (right) == AOP_LIT)
5744 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5746 size = AOP_SIZE (result);
5749 // result = bit & yy;
5750 if (AOP_TYPE (left) == AOP_CRY)
5752 // c = bit & literal;
5753 if (AOP_TYPE (right) == AOP_LIT)
5757 if (size && sameRegs (AOP (result), AOP (left)))
5760 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5765 if (size && (AOP_TYPE (result) == AOP_CRY))
5767 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5770 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5775 emitcode ("clr", "c");
5780 if (AOP_TYPE (right) == AOP_CRY)
5783 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5784 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5789 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5791 emitcode ("rrc", "a");
5792 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5800 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5801 genIfxJump (ifx, "c", left, right, result);
5805 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5806 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5807 if ((AOP_TYPE (right) == AOP_LIT) &&
5808 (AOP_TYPE (result) == AOP_CRY) &&
5809 (AOP_TYPE (left) != AOP_CRY))
5811 int posbit = isLiteralBit (lit);
5816 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5820 switch (posbit & 0x07)
5822 case 0: emitcode ("rrc", "a");
5824 case 7: emitcode ("rlc", "a");
5826 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
5835 SNPRINTF (buffer, sizeof(buffer),
5836 "acc.%d", posbit & 0x07);
5837 genIfxJump (ifx, buffer, left, right, result);
5840 {// what is this case? just found it in ds390/gen.c
5841 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5848 symbol *tlbl = newiTempLabel (NULL);
5849 int sizel = AOP_SIZE (left);
5851 emitcode ("setb", "c");
5854 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5856 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5858 if ((posbit = isLiteralBit (bytelit)) != 0)
5859 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5862 if (bytelit != 0x0FFL)
5863 emitcode ("anl", "a,%s",
5864 aopGet (AOP (right), offset, FALSE, TRUE));
5865 emitcode ("jnz", "%05d$", tlbl->key + 100);
5870 // bit = left & literal
5873 emitcode ("clr", "c");
5874 emitcode ("", "%05d$:", tlbl->key + 100);
5876 // if(left & literal)
5880 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5882 emitcode ("", "%05d$:", tlbl->key + 100);
5890 /* if left is same as result */
5891 if (sameRegs (AOP (result), AOP (left)))
5893 for (; size--; offset++)
5895 if (AOP_TYPE (right) == AOP_LIT)
5897 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5898 if (bytelit == 0x0FF)
5900 /* dummy read of volatile operand */
5901 if (isOperandVolatile (left, FALSE))
5902 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5906 else if (bytelit == 0)
5908 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5910 else if (IS_AOP_PREG (result))
5912 MOVA (aopGet (AOP (left), offset, FALSE, TRUE));
5913 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5914 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5917 emitcode ("anl", "%s,%s",
5918 aopGet (AOP (left), offset, FALSE, TRUE),
5919 aopGet (AOP (right), offset, FALSE, FALSE));
5923 if (AOP_TYPE (left) == AOP_ACC && offset == 0)
5925 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5929 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5930 if (IS_AOP_PREG (result))
5932 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5933 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5936 emitcode ("anl", "%s,a",
5937 aopGet (AOP (left), offset, FALSE, TRUE));
5944 // left & result in different registers
5945 if (AOP_TYPE (result) == AOP_CRY)
5948 // if(size), result in bit
5949 // if(!size && ifx), conditional oper: if(left & right)
5950 symbol *tlbl = newiTempLabel (NULL);
5951 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5953 emitcode ("setb", "c");
5956 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
5957 && AOP_TYPE(left)==AOP_ACC)
5960 emitcode("mov", "a,b");
5961 emitcode ("anl", "a,%s",
5962 aopGet (AOP (right), offset, FALSE, FALSE));
5964 if (AOP_TYPE(left)==AOP_ACC)
5968 bool pushedB = pushB ();
5969 emitcode("mov", "b,a");
5970 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5971 emitcode("anl", "a,b");
5976 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5977 emitcode("anl", "a,b");
5980 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5981 emitcode ("anl", "a,%s",
5982 aopGet (AOP (left), offset, FALSE, FALSE));
5985 emitcode ("jnz", "%05d$", tlbl->key + 100);
5991 emitcode ("", "%05d$:", tlbl->key + 100);
5995 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5997 emitcode ("", "%05d$:", tlbl->key + 100);
6001 for (; (size--); offset++)
6004 // result = left & right
6005 if (AOP_TYPE (right) == AOP_LIT)
6007 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6008 if (bytelit == 0x0FF)
6010 aopPut (AOP (result),
6011 aopGet (AOP (left), offset, FALSE, FALSE),
6013 isOperandVolatile (result, FALSE));
6016 else if (bytelit == 0)
6018 /* dummy read of volatile operand */
6019 if (isOperandVolatile (left, FALSE))
6020 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6021 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
6024 else if (AOP_TYPE (left) == AOP_ACC)
6028 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6029 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6034 emitcode ("anl", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6035 aopPut (AOP (result), "b", offset, isOperandVolatile (result, FALSE));
6040 // faster than result <- left, anl result,right
6041 // and better if result is SFR
6042 if (AOP_TYPE (left) == AOP_ACC)
6045 emitcode("mov", "a,b");
6046 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6050 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6051 emitcode ("anl", "a,%s",
6052 aopGet (AOP (left), offset, FALSE, FALSE));
6054 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6060 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6061 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6062 freeAsmop (result, NULL, ic, TRUE);
6065 /*-----------------------------------------------------------------*/
6066 /* genOr - code for or */
6067 /*-----------------------------------------------------------------*/
6069 genOr (iCode * ic, iCode * ifx)
6071 operand *left, *right, *result;
6072 int size, offset = 0;
6073 unsigned long lit = 0L;
6076 D(emitcode ("; genOr",""));
6078 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6079 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6080 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6083 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6085 AOP_TYPE (left), AOP_TYPE (right));
6086 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6088 AOP_SIZE (left), AOP_SIZE (right));
6091 /* if left is a literal & right is not then exchange them */
6092 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6093 AOP_NEEDSACC (left))
6095 operand *tmp = right;
6100 /* if result = right then exchange them */
6101 if (sameRegs (AOP (result), AOP (right)))
6103 operand *tmp = right;
6108 /* if right is bit then exchange them */
6109 if (AOP_TYPE (right) == AOP_CRY &&
6110 AOP_TYPE (left) != AOP_CRY)
6112 operand *tmp = right;
6116 if (AOP_TYPE (right) == AOP_LIT)
6117 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6119 size = AOP_SIZE (result);
6123 if (AOP_TYPE (left) == AOP_CRY)
6125 if (AOP_TYPE (right) == AOP_LIT)
6127 // c = bit | literal;
6130 // lit != 0 => result = 1
6131 if (AOP_TYPE (result) == AOP_CRY)
6134 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6136 continueIfTrue (ifx);
6139 emitcode ("setb", "c");
6143 // lit == 0 => result = left
6144 if (size && sameRegs (AOP (result), AOP (left)))
6146 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6151 if (AOP_TYPE (right) == AOP_CRY)
6154 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6155 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6160 symbol *tlbl = newiTempLabel (NULL);
6161 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6162 emitcode ("setb", "c");
6163 emitcode ("jb", "%s,%05d$",
6164 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6166 emitcode ("jnz", "%05d$", tlbl->key + 100);
6167 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6169 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6175 emitcode ("", "%05d$:", tlbl->key + 100);
6184 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6185 genIfxJump (ifx, "c", left, right, result);
6189 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6190 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6191 if ((AOP_TYPE (right) == AOP_LIT) &&
6192 (AOP_TYPE (result) == AOP_CRY) &&
6193 (AOP_TYPE (left) != AOP_CRY))
6199 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6201 continueIfTrue (ifx);
6206 // lit = 0, result = boolean(left)
6208 emitcode ("setb", "c");
6212 symbol *tlbl = newiTempLabel (NULL);
6213 emitcode ("jnz", "%05d$", tlbl->key + 100);
6215 emitcode ("", "%05d$:", tlbl->key + 100);
6219 genIfxJump (ifx, "a", left, right, result);
6227 /* if left is same as result */
6228 if (sameRegs (AOP (result), AOP (left)))
6230 for (; size--; offset++)
6232 if (AOP_TYPE (right) == AOP_LIT)
6234 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6237 /* dummy read of volatile operand */
6238 if (isOperandVolatile (left, FALSE))
6239 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6243 else if (bytelit == 0x0FF)
6245 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6247 else if (IS_AOP_PREG (left))
6249 MOVA (aopGet (AOP (left), offset, FALSE, TRUE));
6250 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6251 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6255 emitcode ("orl", "%s,%s",
6256 aopGet (AOP (left), offset, FALSE, TRUE),
6257 aopGet (AOP (right), offset, FALSE, FALSE));
6262 if (AOP_TYPE (left) == AOP_ACC)
6265 emitcode("mov", "a,b");
6266 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6270 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6271 if (IS_AOP_PREG (left))
6273 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6274 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6278 emitcode ("orl", "%s,a",
6279 aopGet (AOP (left), offset, FALSE, TRUE));
6287 // left & result in different registers
6288 if (AOP_TYPE (result) == AOP_CRY)
6291 // if(size), result in bit
6292 // if(!size && ifx), conditional oper: if(left | right)
6293 symbol *tlbl = newiTempLabel (NULL);
6294 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6296 emitcode ("setb", "c");
6299 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6301 emitcode("mov", "a,b");
6302 emitcode ("orl", "a,%s",
6303 aopGet (AOP (right), offset, FALSE, FALSE));
6305 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6306 emitcode ("orl", "a,%s",
6307 aopGet (AOP (left), offset, FALSE, FALSE));
6309 emitcode ("jnz", "%05d$", tlbl->key + 100);
6315 emitcode ("", "%05d$:", tlbl->key + 100);
6319 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6321 emitcode ("", "%05d$:", tlbl->key + 100);
6325 for (; (size--); offset++)
6328 // result = left | right
6329 if (AOP_TYPE (right) == AOP_LIT)
6331 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6334 aopPut (AOP (result),
6335 aopGet (AOP (left), offset, FALSE, FALSE),
6337 isOperandVolatile (result, FALSE));
6340 else if (bytelit == 0x0FF)
6342 /* dummy read of volatile operand */
6343 if (isOperandVolatile (left, FALSE))
6344 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6345 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6349 // faster than result <- left, anl result,right
6350 // and better if result is SFR
6351 if (AOP_TYPE (left) == AOP_ACC)
6354 emitcode("mov", "a,b");
6355 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6359 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6360 emitcode ("orl", "a,%s",
6361 aopGet (AOP (left), offset, FALSE, FALSE));
6363 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6369 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6370 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6371 freeAsmop (result, NULL, ic, TRUE);
6374 /*-----------------------------------------------------------------*/
6375 /* genXor - code for xclusive or */
6376 /*-----------------------------------------------------------------*/
6378 genXor (iCode * ic, iCode * ifx)
6380 operand *left, *right, *result;
6381 int size, offset = 0;
6382 unsigned long lit = 0L;
6385 D(emitcode ("; genXor",""));
6387 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6388 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6389 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6392 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6394 AOP_TYPE (left), AOP_TYPE (right));
6395 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6397 AOP_SIZE (left), AOP_SIZE (right));
6400 /* if left is a literal & right is not ||
6401 if left needs acc & right does not */
6402 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6403 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6405 operand *tmp = right;
6410 /* if result = right then exchange them */
6411 if (sameRegs (AOP (result), AOP (right)))
6413 operand *tmp = right;
6418 /* if right is bit then exchange them */
6419 if (AOP_TYPE (right) == AOP_CRY &&
6420 AOP_TYPE (left) != AOP_CRY)
6422 operand *tmp = right;
6426 if (AOP_TYPE (right) == AOP_LIT)
6427 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6429 size = AOP_SIZE (result);
6433 if (AOP_TYPE (left) == AOP_CRY)
6435 if (AOP_TYPE (right) == AOP_LIT)
6437 // c = bit & literal;
6440 // lit>>1 != 0 => result = 1
6441 if (AOP_TYPE (result) == AOP_CRY)
6444 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6446 continueIfTrue (ifx);
6449 emitcode ("setb", "c");
6456 // lit == 0, result = left
6457 if (size && sameRegs (AOP (result), AOP (left)))
6459 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6463 // lit == 1, result = not(left)
6464 if (size && sameRegs (AOP (result), AOP (left)))
6466 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6471 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6472 emitcode ("cpl", "c");
6481 symbol *tlbl = newiTempLabel (NULL);
6482 if (AOP_TYPE (right) == AOP_CRY)
6485 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6489 int sizer = AOP_SIZE (right);
6491 // if val>>1 != 0, result = 1
6492 emitcode ("setb", "c");
6495 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6497 // test the msb of the lsb
6498 emitcode ("anl", "a,#0xfe");
6499 emitcode ("jnz", "%05d$", tlbl->key + 100);
6503 emitcode ("rrc", "a");
6505 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6506 emitcode ("cpl", "c");
6507 emitcode ("", "%05d$:", (tlbl->key + 100));
6514 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6515 genIfxJump (ifx, "c", left, right, result);
6519 /* if left is same as result */
6520 if (sameRegs (AOP (result), AOP (left)))
6522 for (; size--; offset++)
6524 if (AOP_TYPE (right) == AOP_LIT)
6526 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6529 /* dummy read of volatile operand */
6530 if (isOperandVolatile (left, FALSE))
6531 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6535 else if (IS_AOP_PREG (left))
6537 MOVA (aopGet (AOP (left), offset, FALSE, TRUE));
6538 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6539 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6543 emitcode ("xrl", "%s,%s",
6544 aopGet (AOP (left), offset, FALSE, TRUE),
6545 aopGet (AOP (right), offset, FALSE, FALSE));
6550 if (AOP_TYPE (left) == AOP_ACC)
6553 emitcode("mov", "a,b");
6554 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6558 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6559 if (IS_AOP_PREG (left))
6561 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6562 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6565 emitcode ("xrl", "%s,a",
6566 aopGet (AOP (left), offset, FALSE, TRUE));
6573 // left & result in different registers
6574 if (AOP_TYPE (result) == AOP_CRY)
6577 // if(size), result in bit
6578 // if(!size && ifx), conditional oper: if(left ^ right)
6579 symbol *tlbl = newiTempLabel (NULL);
6580 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6582 emitcode ("setb", "c");
6585 if ((AOP_TYPE (right) == AOP_LIT) &&
6586 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6588 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6592 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6594 emitcode("mov", "a,b");
6595 emitcode ("xrl", "a,%s",
6596 aopGet (AOP (right), offset, FALSE, FALSE));
6598 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6599 emitcode ("xrl", "a,%s",
6600 aopGet (AOP (left), offset, FALSE, FALSE));
6603 emitcode ("jnz", "%05d$", tlbl->key + 100);
6609 emitcode ("", "%05d$:", tlbl->key + 100);
6613 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6617 for (; (size--); offset++)
6620 // result = left & right
6621 if (AOP_TYPE (right) == AOP_LIT)
6623 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6626 aopPut (AOP (result),
6627 aopGet (AOP (left), offset, FALSE, FALSE),
6629 isOperandVolatile (result, FALSE));
6633 // faster than result <- left, anl result,right
6634 // and better if result is SFR
6635 if (AOP_TYPE (left) == AOP_ACC)
6638 emitcode("mov", "a,b");
6639 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6643 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6644 emitcode ("xrl", "a,%s",
6645 aopGet (AOP (left), offset, FALSE, TRUE));
6647 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6653 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6654 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6655 freeAsmop (result, NULL, ic, TRUE);
6658 /*-----------------------------------------------------------------*/
6659 /* genInline - write the inline code out */
6660 /*-----------------------------------------------------------------*/
6662 genInline (iCode * ic)
6664 char *buffer, *bp, *bp1;
6666 D(emitcode ("; genInline",""));
6668 _G.inLine += (!options.asmpeep);
6670 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6671 strcpy (buffer, IC_INLINE (ic));
6673 /* emit each line as a code */
6684 /* Add \n for labels, not dirs such as c:\mydir */
6685 if ( (*bp == ':') && (isspace(bp[1])) )
6699 /* emitcode("",buffer); */
6700 _G.inLine -= (!options.asmpeep);
6703 /*-----------------------------------------------------------------*/
6704 /* genRRC - rotate right with carry */
6705 /*-----------------------------------------------------------------*/
6709 operand *left, *result;
6710 int size, offset = 0;
6713 D(emitcode ("; genRRC",""));
6715 /* rotate right with carry */
6716 left = IC_LEFT (ic);
6717 result = IC_RESULT (ic);
6718 aopOp (left, ic, FALSE);
6719 aopOp (result, ic, FALSE);
6721 /* move it to the result */
6722 size = AOP_SIZE (result);
6724 if (size == 1) { /* special case for 1 byte */
6725 l = aopGet (AOP (left), offset, FALSE, FALSE);
6727 emitcode ("rr", "a");
6730 /* no need to clear carry, bit7 will be written later */
6733 l = aopGet (AOP (left), offset, FALSE, FALSE);
6735 emitcode ("rrc", "a");
6736 if (AOP_SIZE (result) > 1)
6737 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6739 /* now we need to put the carry into the
6740 highest order byte of the result */
6741 if (AOP_SIZE (result) > 1)
6743 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6746 emitcode ("mov", "acc.7,c");
6748 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6749 freeAsmop (left, NULL, ic, TRUE);
6750 freeAsmop (result, NULL, ic, TRUE);
6753 /*-----------------------------------------------------------------*/
6754 /* genRLC - generate code for rotate left with carry */
6755 /*-----------------------------------------------------------------*/
6759 operand *left, *result;
6760 int size, offset = 0;
6763 D(emitcode ("; genRLC",""));
6765 /* rotate right with carry */
6766 left = IC_LEFT (ic);
6767 result = IC_RESULT (ic);
6768 aopOp (left, ic, FALSE);
6769 aopOp (result, ic, FALSE);
6771 /* move it to the result */
6772 size = AOP_SIZE (result);
6776 l = aopGet (AOP (left), offset, FALSE, FALSE);
6778 if (size == 0) { /* special case for 1 byte */
6782 emitcode("rlc","a"); /* bit0 will be written later */
6783 if (AOP_SIZE (result) > 1)
6784 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6787 l = aopGet (AOP (left), offset, FALSE, FALSE);
6789 emitcode ("rlc", "a");
6790 if (AOP_SIZE (result) > 1)
6791 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6794 /* now we need to put the carry into the
6795 highest order byte of the result */
6796 if (AOP_SIZE (result) > 1)
6798 l = aopGet (AOP (result), 0, FALSE, FALSE);
6801 emitcode ("mov", "acc.0,c");
6803 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6804 freeAsmop (left, NULL, ic, TRUE);
6805 freeAsmop (result, NULL, ic, TRUE);
6808 /*-----------------------------------------------------------------*/
6809 /* genGetHbit - generates code get highest order bit */
6810 /*-----------------------------------------------------------------*/
6812 genGetHbit (iCode * ic)
6814 operand *left, *result;
6816 D(emitcode ("; genGetHbit",""));
6818 left = IC_LEFT (ic);
6819 result = IC_RESULT (ic);
6820 aopOp (left, ic, FALSE);
6821 aopOp (result, ic, FALSE);
6823 /* get the highest order byte into a */
6824 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6825 if (AOP_TYPE (result) == AOP_CRY)
6827 emitcode ("rlc", "a");
6832 emitcode ("rl", "a");
6833 emitcode ("anl", "a,#0x01");
6838 freeAsmop (left, NULL, ic, TRUE);
6839 freeAsmop (result, NULL, ic, TRUE);
6842 /*-----------------------------------------------------------------*/
6843 /* genSwap - generates code to swap nibbles or bytes */
6844 /*-----------------------------------------------------------------*/
6846 genSwap (iCode * ic)
6848 operand *left, *result;
6850 D(emitcode ("; genSwap",""));
6852 left = IC_LEFT (ic);
6853 result = IC_RESULT (ic);
6854 aopOp (left, ic, FALSE);
6855 aopOp (result, ic, FALSE);
6857 switch (AOP_SIZE (left))
6859 case 1: /* swap nibbles in byte */
6860 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6861 emitcode ("swap", "a");
6862 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6864 case 2: /* swap bytes in word */
6865 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6867 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6868 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6869 0, isOperandVolatile (result, FALSE));
6870 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6872 else if (operandsEqu (left, result))
6875 bool pushedB = FALSE, leftInB = FALSE;
6877 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6878 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6881 emitcode ("mov", "b,a");
6885 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6886 0, isOperandVolatile (result, FALSE));
6887 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6894 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6895 0, isOperandVolatile (result, FALSE));
6896 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6897 1, isOperandVolatile (result, FALSE));
6901 wassertl(FALSE, "unsupported SWAP operand size");
6904 freeAsmop (left, NULL, ic, TRUE);
6905 freeAsmop (result, NULL, ic, TRUE);
6909 /*-----------------------------------------------------------------*/
6910 /* AccRol - rotate left accumulator by known count */
6911 /*-----------------------------------------------------------------*/
6913 AccRol (int shCount)
6915 shCount &= 0x0007; // shCount : 0..7
6922 emitcode ("rl", "a");
6925 emitcode ("rl", "a");
6926 emitcode ("rl", "a");
6929 emitcode ("swap", "a");
6930 emitcode ("rr", "a");
6933 emitcode ("swap", "a");
6936 emitcode ("swap", "a");
6937 emitcode ("rl", "a");
6940 emitcode ("rr", "a");
6941 emitcode ("rr", "a");
6944 emitcode ("rr", "a");
6949 /*-----------------------------------------------------------------*/
6950 /* AccLsh - left shift accumulator by known count */
6951 /*-----------------------------------------------------------------*/
6953 AccLsh (int shCount)
6958 emitcode ("add", "a,acc");
6959 else if (shCount == 2)
6961 emitcode ("add", "a,acc");
6962 emitcode ("add", "a,acc");
6966 /* rotate left accumulator */
6968 /* and kill the lower order bits */
6969 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6974 /*-----------------------------------------------------------------*/
6975 /* AccRsh - right shift accumulator by known count */
6976 /*-----------------------------------------------------------------*/
6978 AccRsh (int shCount)
6985 emitcode ("rrc", "a");
6989 /* rotate right accumulator */
6990 AccRol (8 - shCount);
6991 /* and kill the higher order bits */
6992 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6997 /*-----------------------------------------------------------------*/
6998 /* AccSRsh - signed right shift accumulator by known count */
6999 /*-----------------------------------------------------------------*/
7001 AccSRsh (int shCount)
7008 emitcode ("mov", "c,acc.7");
7009 emitcode ("rrc", "a");
7011 else if (shCount == 2)
7013 emitcode ("mov", "c,acc.7");
7014 emitcode ("rrc", "a");
7015 emitcode ("mov", "c,acc.7");
7016 emitcode ("rrc", "a");
7020 tlbl = newiTempLabel (NULL);
7021 /* rotate right accumulator */
7022 AccRol (8 - shCount);
7023 /* and kill the higher order bits */
7024 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7025 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7026 emitcode ("orl", "a,#0x%02x",
7027 (unsigned char) ~SRMask[shCount]);
7028 emitcode ("", "%05d$:", tlbl->key + 100);
7033 /*-----------------------------------------------------------------*/
7034 /* shiftR1Left2Result - shift right one byte from left to result */
7035 /*-----------------------------------------------------------------*/
7037 shiftR1Left2Result (operand * left, int offl,
7038 operand * result, int offr,
7039 int shCount, int sign)
7041 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7042 /* shift right accumulator */
7047 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7050 /*-----------------------------------------------------------------*/
7051 /* shiftL1Left2Result - shift left one byte from left to result */
7052 /*-----------------------------------------------------------------*/
7054 shiftL1Left2Result (operand * left, int offl,
7055 operand * result, int offr, int shCount)
7058 l = aopGet (AOP (left), offl, FALSE, FALSE);
7060 /* shift left accumulator */
7062 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7065 /*-----------------------------------------------------------------*/
7066 /* movLeft2Result - move byte from left to result */
7067 /*-----------------------------------------------------------------*/
7069 movLeft2Result (operand * left, int offl,
7070 operand * result, int offr, int sign)
7073 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7075 l = aopGet (AOP (left), offl, FALSE, FALSE);
7077 if (*l == '@' && (IS_AOP_PREG (result)))
7079 emitcode ("mov", "a,%s", l);
7080 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7085 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
7088 /* MSB sign in acc.7 ! */
7089 if (getDataSize (left) == offl + 1)
7091 emitcode ("mov", "a,%s", l);
7092 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7099 /*-----------------------------------------------------------------*/
7100 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7101 /*-----------------------------------------------------------------*/
7105 emitcode ("rrc", "a");
7106 emitcode ("xch", "a,%s", x);
7107 emitcode ("rrc", "a");
7108 emitcode ("xch", "a,%s", x);
7111 /*-----------------------------------------------------------------*/
7112 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7113 /*-----------------------------------------------------------------*/
7117 emitcode ("xch", "a,%s", x);
7118 emitcode ("rlc", "a");
7119 emitcode ("xch", "a,%s", x);
7120 emitcode ("rlc", "a");
7123 /*-----------------------------------------------------------------*/
7124 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7125 /*-----------------------------------------------------------------*/
7129 emitcode ("xch", "a,%s", x);
7130 emitcode ("add", "a,acc");
7131 emitcode ("xch", "a,%s", x);
7132 emitcode ("rlc", "a");
7135 /*-----------------------------------------------------------------*/
7136 /* AccAXLsh - left shift a:x by known count (0..7) */
7137 /*-----------------------------------------------------------------*/
7139 AccAXLsh (char *x, int shCount)
7154 case 5: // AAAAABBB:CCCCCDDD
7156 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7158 emitcode ("anl", "a,#0x%02x",
7159 SLMask[shCount]); // BBB00000:CCCCCDDD
7161 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7163 AccRol (shCount); // DDDCCCCC:BBB00000
7165 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7167 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7169 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7171 emitcode ("anl", "a,#0x%02x",
7172 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7174 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7176 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7179 case 6: // AAAAAABB:CCCCCCDD
7180 emitcode ("anl", "a,#0x%02x",
7181 SRMask[shCount]); // 000000BB:CCCCCCDD
7182 emitcode ("mov", "c,acc.0"); // c = B
7183 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7185 AccAXRrl1 (x); // BCCCCCCD:D000000B
7186 AccAXRrl1 (x); // BBCCCCCC:DD000000
7188 emitcode("rrc","a");
7189 emitcode("xch","a,%s", x);
7190 emitcode("rrc","a");
7191 emitcode("mov","c,acc.0"); //<< get correct bit
7192 emitcode("xch","a,%s", x);
7194 emitcode("rrc","a");
7195 emitcode("xch","a,%s", x);
7196 emitcode("rrc","a");
7197 emitcode("xch","a,%s", x);
7200 case 7: // a:x <<= 7
7202 emitcode ("anl", "a,#0x%02x",
7203 SRMask[shCount]); // 0000000B:CCCCCCCD
7205 emitcode ("mov", "c,acc.0"); // c = B
7207 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7209 AccAXRrl1 (x); // BCCCCCCC:D0000000
7217 /*-----------------------------------------------------------------*/
7218 /* AccAXRsh - right shift a:x known count (0..7) */
7219 /*-----------------------------------------------------------------*/
7221 AccAXRsh (char *x, int shCount)
7229 AccAXRrl1 (x); // 0->a:x
7234 AccAXRrl1 (x); // 0->a:x
7237 AccAXRrl1 (x); // 0->a:x
7242 case 5: // AAAAABBB:CCCCCDDD = a:x
7244 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7246 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7248 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7250 emitcode ("anl", "a,#0x%02x",
7251 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7253 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7255 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7257 emitcode ("anl", "a,#0x%02x",
7258 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7260 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7262 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7264 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7267 case 6: // AABBBBBB:CCDDDDDD
7269 emitcode ("mov", "c,acc.7");
7270 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7272 emitcode ("mov", "c,acc.7");
7273 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7275 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7277 emitcode ("anl", "a,#0x%02x",
7278 SRMask[shCount]); // 000000AA:BBBBBBCC
7281 case 7: // ABBBBBBB:CDDDDDDD
7283 emitcode ("mov", "c,acc.7"); // c = A
7285 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7287 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7289 emitcode ("anl", "a,#0x%02x",
7290 SRMask[shCount]); // 0000000A:BBBBBBBC
7298 /*-----------------------------------------------------------------*/
7299 /* AccAXRshS - right shift signed a:x known count (0..7) */
7300 /*-----------------------------------------------------------------*/
7302 AccAXRshS (char *x, int shCount)
7310 emitcode ("mov", "c,acc.7");
7311 AccAXRrl1 (x); // s->a:x
7315 emitcode ("mov", "c,acc.7");
7316 AccAXRrl1 (x); // s->a:x
7318 emitcode ("mov", "c,acc.7");
7319 AccAXRrl1 (x); // s->a:x
7324 case 5: // AAAAABBB:CCCCCDDD = a:x
7326 tlbl = newiTempLabel (NULL);
7327 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7329 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7331 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7333 emitcode ("anl", "a,#0x%02x",
7334 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7336 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7338 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7340 emitcode ("anl", "a,#0x%02x",
7341 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7343 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7345 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7347 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7349 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7350 emitcode ("orl", "a,#0x%02x",
7351 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7353 emitcode ("", "%05d$:", tlbl->key + 100);
7354 break; // SSSSAAAA:BBBCCCCC
7356 case 6: // AABBBBBB:CCDDDDDD
7358 tlbl = newiTempLabel (NULL);
7359 emitcode ("mov", "c,acc.7");
7360 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7362 emitcode ("mov", "c,acc.7");
7363 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7365 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7367 emitcode ("anl", "a,#0x%02x",
7368 SRMask[shCount]); // 000000AA:BBBBBBCC
7370 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7371 emitcode ("orl", "a,#0x%02x",
7372 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7374 emitcode ("", "%05d$:", tlbl->key + 100);
7376 case 7: // ABBBBBBB:CDDDDDDD
7378 tlbl = newiTempLabel (NULL);
7379 emitcode ("mov", "c,acc.7"); // c = A
7381 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7383 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7385 emitcode ("anl", "a,#0x%02x",
7386 SRMask[shCount]); // 0000000A:BBBBBBBC
7388 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7389 emitcode ("orl", "a,#0x%02x",
7390 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7392 emitcode ("", "%05d$:", tlbl->key + 100);
7399 /*-----------------------------------------------------------------*/
7400 /* shiftL2Left2Result - shift left two bytes from left to result */
7401 /*-----------------------------------------------------------------*/
7403 shiftL2Left2Result (operand * left, int offl,
7404 operand * result, int offr, int shCount)
7406 if (sameRegs (AOP (result), AOP (left)) &&
7407 ((offl + MSB16) == offr))
7409 /* don't crash result[offr] */
7410 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7411 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7415 movLeft2Result (left, offl, result, offr, 0);
7416 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7418 /* ax << shCount (x = lsb(result)) */
7419 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7420 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7424 /*-----------------------------------------------------------------*/
7425 /* shiftR2Left2Result - shift right two bytes from left to result */
7426 /*-----------------------------------------------------------------*/
7428 shiftR2Left2Result (operand * left, int offl,
7429 operand * result, int offr,
7430 int shCount, int sign)
7432 if (sameRegs (AOP (result), AOP (left)) &&
7433 ((offl + MSB16) == offr))
7435 /* don't crash result[offr] */
7436 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7437 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7441 movLeft2Result (left, offl, result, offr, 0);
7442 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7444 /* a:x >> shCount (x = lsb(result)) */
7446 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7448 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7449 if (getDataSize (result) > 1)
7450 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7453 /*-----------------------------------------------------------------*/
7454 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7455 /*-----------------------------------------------------------------*/
7457 shiftLLeftOrResult (operand * left, int offl,
7458 operand * result, int offr, int shCount)
7460 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7461 /* shift left accumulator */
7463 /* or with result */
7464 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7465 /* back to result */
7466 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7469 /*-----------------------------------------------------------------*/
7470 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7471 /*-----------------------------------------------------------------*/
7473 shiftRLeftOrResult (operand * left, int offl,
7474 operand * result, int offr, int shCount)
7476 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7477 /* shift right accumulator */
7479 /* or with result */
7480 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7481 /* back to result */
7482 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7485 /*-----------------------------------------------------------------*/
7486 /* genlshOne - left shift a one byte quantity by known count */
7487 /*-----------------------------------------------------------------*/
7489 genlshOne (operand * result, operand * left, int shCount)
7491 D(emitcode ("; genlshOne",""));
7493 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7496 /*-----------------------------------------------------------------*/
7497 /* genlshTwo - left shift two bytes by known amount != 0 */
7498 /*-----------------------------------------------------------------*/
7500 genlshTwo (operand * result, operand * left, int shCount)
7504 D(emitcode ("; genlshTwo",""));
7506 size = getDataSize (result);
7508 /* if shCount >= 8 */
7516 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7518 movLeft2Result (left, LSB, result, MSB16, 0);
7520 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7523 /* 1 <= shCount <= 7 */
7527 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7529 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7533 /*-----------------------------------------------------------------*/
7534 /* shiftLLong - shift left one long from left to result */
7535 /* offl = LSB or MSB16 */
7536 /*-----------------------------------------------------------------*/
7538 shiftLLong (operand * left, operand * result, int offr)
7541 int size = AOP_SIZE (result);
7543 if (size >= LSB + offr)
7545 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7547 emitcode ("add", "a,acc");
7548 if (sameRegs (AOP (left), AOP (result)) &&
7549 size >= MSB16 + offr && offr != LSB)
7550 emitcode ("xch", "a,%s",
7551 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7553 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7556 if (size >= MSB16 + offr)
7558 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7560 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7563 emitcode ("rlc", "a");
7564 if (sameRegs (AOP (left), AOP (result)) &&
7565 size >= MSB24 + offr && offr != LSB)
7566 emitcode ("xch", "a,%s",
7567 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7569 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7572 if (size >= MSB24 + offr)
7574 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7576 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7579 emitcode ("rlc", "a");
7580 if (sameRegs (AOP (left), AOP (result)) &&
7581 size >= MSB32 + offr && offr != LSB)
7582 emitcode ("xch", "a,%s",
7583 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7585 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7588 if (size > MSB32 + offr)
7590 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7592 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7595 emitcode ("rlc", "a");
7596 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7599 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7602 /*-----------------------------------------------------------------*/
7603 /* genlshFour - shift four byte by a known amount != 0 */
7604 /*-----------------------------------------------------------------*/
7606 genlshFour (operand * result, operand * left, int shCount)
7610 D(emitcode ("; genlshFour",""));
7612 size = AOP_SIZE (result);
7614 /* if shifting more that 3 bytes */
7619 /* lowest order of left goes to the highest
7620 order of the destination */
7621 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7623 movLeft2Result (left, LSB, result, MSB32, 0);
7624 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7625 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7626 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7630 /* more than two bytes */
7631 else if (shCount >= 16)
7633 /* lower order two bytes goes to higher order two bytes */
7635 /* if some more remaining */
7637 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7640 movLeft2Result (left, MSB16, result, MSB32, 0);
7641 movLeft2Result (left, LSB, result, MSB24, 0);
7643 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7644 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7648 /* if more than 1 byte */
7649 else if (shCount >= 8)
7651 /* lower order three bytes goes to higher order three bytes */
7656 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7658 movLeft2Result (left, LSB, result, MSB16, 0);
7664 movLeft2Result (left, MSB24, result, MSB32, 0);
7665 movLeft2Result (left, MSB16, result, MSB24, 0);
7666 movLeft2Result (left, LSB, result, MSB16, 0);
7667 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7669 else if (shCount == 1)
7670 shiftLLong (left, result, MSB16);
7673 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7674 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7675 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7676 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7681 /* 1 <= shCount <= 7 */
7682 else if (shCount <= 2)
7684 shiftLLong (left, result, LSB);
7686 shiftLLong (result, result, LSB);
7688 /* 3 <= shCount <= 7, optimize */
7691 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7692 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7693 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7697 /*-----------------------------------------------------------------*/
7698 /* genLeftShiftLiteral - left shifting by known count */
7699 /*-----------------------------------------------------------------*/
7701 genLeftShiftLiteral (operand * left,
7706 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7709 D(emitcode ("; genLeftShiftLiteral",""));
7711 freeAsmop (right, NULL, ic, TRUE);
7713 aopOp (left, ic, FALSE);
7714 aopOp (result, ic, FALSE);
7716 size = getSize (operandType (result));
7719 emitcode ("; shift left ", "result %d, left %d", size,
7723 /* I suppose that the left size >= result size */
7728 movLeft2Result (left, size, result, size, 0);
7732 else if (shCount >= (size * 8))
7734 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7740 genlshOne (result, left, shCount);
7744 genlshTwo (result, left, shCount);
7748 genlshFour (result, left, shCount);
7751 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7752 "*** ack! mystery literal shift!\n");
7756 freeAsmop (left, NULL, ic, TRUE);
7757 freeAsmop (result, NULL, ic, TRUE);
7760 /*-----------------------------------------------------------------*/
7761 /* genLeftShift - generates code for left shifting */
7762 /*-----------------------------------------------------------------*/
7764 genLeftShift (iCode * ic)
7766 operand *left, *right, *result;
7769 symbol *tlbl, *tlbl1;
7772 D(emitcode ("; genLeftShift",""));
7774 right = IC_RIGHT (ic);
7775 left = IC_LEFT (ic);
7776 result = IC_RESULT (ic);
7778 aopOp (right, ic, FALSE);
7780 /* if the shift count is known then do it
7781 as efficiently as possible */
7782 if (AOP_TYPE (right) == AOP_LIT)
7784 genLeftShiftLiteral (left, right, result, ic);
7788 /* shift count is unknown then we have to form
7789 a loop get the loop count in B : Note: we take
7790 only the lower order byte since shifting
7791 more that 32 bits make no sense anyway, ( the
7792 largest size of an object can be only 32 bits ) */
7795 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7796 emitcode ("inc", "b");
7797 freeAsmop (right, NULL, ic, TRUE);
7798 aopOp (left, ic, FALSE);
7799 aopOp (result, ic, FALSE);
7801 /* now move the left to the result if they are not the same */
7802 if (!sameRegs (AOP (left), AOP (result)) &&
7803 AOP_SIZE (result) > 1)
7806 size = AOP_SIZE (result);
7810 l = aopGet (AOP (left), offset, FALSE, TRUE);
7811 if (*l == '@' && (IS_AOP_PREG (result)))
7814 emitcode ("mov", "a,%s", l);
7815 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7818 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7823 tlbl = newiTempLabel (NULL);
7824 size = AOP_SIZE (result);
7826 tlbl1 = newiTempLabel (NULL);
7828 /* if it is only one byte then */
7831 symbol *tlbl1 = newiTempLabel (NULL);
7833 l = aopGet (AOP (left), 0, FALSE, FALSE);
7835 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7836 emitcode ("", "%05d$:", tlbl->key + 100);
7837 emitcode ("add", "a,acc");
7838 emitcode ("", "%05d$:", tlbl1->key + 100);
7839 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7841 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7845 reAdjustPreg (AOP (result));
7847 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7848 emitcode ("", "%05d$:", tlbl->key + 100);
7849 l = aopGet (AOP (result), offset, FALSE, FALSE);
7851 emitcode ("add", "a,acc");
7852 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7855 l = aopGet (AOP (result), offset, FALSE, FALSE);
7857 emitcode ("rlc", "a");
7858 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7860 reAdjustPreg (AOP (result));
7862 emitcode ("", "%05d$:", tlbl1->key + 100);
7863 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7866 freeAsmop (left, NULL, ic, TRUE);
7867 freeAsmop (result, NULL, ic, TRUE);
7870 /*-----------------------------------------------------------------*/
7871 /* genrshOne - right shift a one byte quantity by known count */
7872 /*-----------------------------------------------------------------*/
7874 genrshOne (operand * result, operand * left,
7875 int shCount, int sign)
7877 D(emitcode ("; genrshOne",""));
7879 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7882 /*-----------------------------------------------------------------*/
7883 /* genrshTwo - right shift two bytes by known amount != 0 */
7884 /*-----------------------------------------------------------------*/
7886 genrshTwo (operand * result, operand * left,
7887 int shCount, int sign)
7889 D(emitcode ("; genrshTwo",""));
7891 /* if shCount >= 8 */
7896 shiftR1Left2Result (left, MSB16, result, LSB,
7899 movLeft2Result (left, MSB16, result, LSB, sign);
7900 addSign (result, MSB16, sign);
7903 /* 1 <= shCount <= 7 */
7905 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7908 /*-----------------------------------------------------------------*/
7909 /* shiftRLong - shift right one long from left to result */
7910 /* offl = LSB or MSB16 */
7911 /*-----------------------------------------------------------------*/
7913 shiftRLong (operand * left, int offl,
7914 operand * result, int sign)
7916 int isSameRegs=sameRegs(AOP(left),AOP(result));
7918 if (isSameRegs && offl>1) {
7919 // we are in big trouble, but this shouldn't happen
7920 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7923 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7928 emitcode ("rlc", "a");
7929 emitcode ("subb", "a,acc");
7931 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7933 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7934 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7937 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7942 emitcode ("clr", "c");
7944 emitcode ("mov", "c,acc.7");
7947 emitcode ("rrc", "a");
7949 if (isSameRegs && offl==MSB16) {
7950 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7952 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7953 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7956 emitcode ("rrc", "a");
7957 if (isSameRegs && offl==1) {
7958 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7960 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7961 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7963 emitcode ("rrc", "a");
7964 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7968 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7969 emitcode ("rrc", "a");
7970 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7974 /*-----------------------------------------------------------------*/
7975 /* genrshFour - shift four byte by a known amount != 0 */
7976 /*-----------------------------------------------------------------*/
7978 genrshFour (operand * result, operand * left,
7979 int shCount, int sign)
7981 D(emitcode ("; genrshFour",""));
7983 /* if shifting more that 3 bytes */
7988 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7990 movLeft2Result (left, MSB32, result, LSB, sign);
7991 addSign (result, MSB16, sign);
7993 else if (shCount >= 16)
7997 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8000 movLeft2Result (left, MSB24, result, LSB, 0);
8001 movLeft2Result (left, MSB32, result, MSB16, sign);
8003 addSign (result, MSB24, sign);
8005 else if (shCount >= 8)
8009 shiftRLong (left, MSB16, result, sign);
8010 else if (shCount == 0)
8012 movLeft2Result (left, MSB16, result, LSB, 0);
8013 movLeft2Result (left, MSB24, result, MSB16, 0);
8014 movLeft2Result (left, MSB32, result, MSB24, sign);
8015 addSign (result, MSB32, sign);
8019 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8020 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8021 /* the last shift is signed */
8022 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8023 addSign (result, MSB32, sign);
8027 { /* 1 <= shCount <= 7 */
8030 shiftRLong (left, LSB, result, sign);
8032 shiftRLong (result, LSB, result, sign);
8036 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8037 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8038 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8043 /*-----------------------------------------------------------------*/
8044 /* genRightShiftLiteral - right shifting by known count */
8045 /*-----------------------------------------------------------------*/
8047 genRightShiftLiteral (operand * left,
8053 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8056 D(emitcode ("; genRightShiftLiteral",""));
8058 freeAsmop (right, NULL, ic, TRUE);
8060 aopOp (left, ic, FALSE);
8061 aopOp (result, ic, FALSE);
8064 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8068 size = getDataSize (left);
8069 /* test the LEFT size !!! */
8071 /* I suppose that the left size >= result size */
8074 size = getDataSize (result);
8076 movLeft2Result (left, size, result, size, 0);
8079 else if (shCount >= (size * 8))
8082 /* get sign in acc.7 */
8083 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
8085 addSign (result, LSB, sign);
8092 genrshOne (result, left, shCount, sign);
8096 genrshTwo (result, left, shCount, sign);
8100 genrshFour (result, left, shCount, sign);
8106 freeAsmop (left, NULL, ic, TRUE);
8107 freeAsmop (result, NULL, ic, TRUE);
8110 /*-----------------------------------------------------------------*/
8111 /* genSignedRightShift - right shift of signed number */
8112 /*-----------------------------------------------------------------*/
8114 genSignedRightShift (iCode * ic)
8116 operand *right, *left, *result;
8119 symbol *tlbl, *tlbl1;
8122 D(emitcode ("; genSignedRightShift",""));
8124 /* we do it the hard way put the shift count in b
8125 and loop thru preserving the sign */
8127 right = IC_RIGHT (ic);
8128 left = IC_LEFT (ic);
8129 result = IC_RESULT (ic);
8131 aopOp (right, ic, FALSE);
8134 if (AOP_TYPE (right) == AOP_LIT)
8136 genRightShiftLiteral (left, right, result, ic, 1);
8139 /* shift count is unknown then we have to form
8140 a loop get the loop count in B : Note: we take
8141 only the lower order byte since shifting
8142 more that 32 bits make no sense anyway, ( the
8143 largest size of an object can be only 32 bits ) */
8146 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8147 emitcode ("inc", "b");
8148 freeAsmop (right, NULL, ic, TRUE);
8149 aopOp (left, ic, FALSE);
8150 aopOp (result, ic, FALSE);
8152 /* now move the left to the result if they are not the
8154 if (!sameRegs (AOP (left), AOP (result)) &&
8155 AOP_SIZE (result) > 1)
8158 size = AOP_SIZE (result);
8162 l = aopGet (AOP (left), offset, FALSE, TRUE);
8163 if (*l == '@' && IS_AOP_PREG (result))
8166 emitcode ("mov", "a,%s", l);
8167 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8170 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8175 /* mov the highest order bit to OVR */
8176 tlbl = newiTempLabel (NULL);
8177 tlbl1 = newiTempLabel (NULL);
8179 size = AOP_SIZE (result);
8181 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
8182 emitcode ("rlc", "a");
8183 emitcode ("mov", "ov,c");
8184 /* if it is only one byte then */
8187 l = aopGet (AOP (left), 0, FALSE, FALSE);
8189 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8190 emitcode ("", "%05d$:", tlbl->key + 100);
8191 emitcode ("mov", "c,ov");
8192 emitcode ("rrc", "a");
8193 emitcode ("", "%05d$:", tlbl1->key + 100);
8194 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8196 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8200 reAdjustPreg (AOP (result));
8201 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8202 emitcode ("", "%05d$:", tlbl->key + 100);
8203 emitcode ("mov", "c,ov");
8206 l = aopGet (AOP (result), offset, FALSE, FALSE);
8208 emitcode ("rrc", "a");
8209 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8211 reAdjustPreg (AOP (result));
8212 emitcode ("", "%05d$:", tlbl1->key + 100);
8213 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8217 freeAsmop (left, NULL, ic, TRUE);
8218 freeAsmop (result, NULL, ic, TRUE);
8221 /*-----------------------------------------------------------------*/
8222 /* genRightShift - generate code for right shifting */
8223 /*-----------------------------------------------------------------*/
8225 genRightShift (iCode * ic)
8227 operand *right, *left, *result;
8231 symbol *tlbl, *tlbl1;
8234 D(emitcode ("; genRightShift",""));
8236 /* if signed then we do it the hard way preserve the
8237 sign bit moving it inwards */
8238 letype = getSpec (operandType (IC_LEFT (ic)));
8240 if (!SPEC_USIGN (letype))
8242 genSignedRightShift (ic);
8246 /* signed & unsigned types are treated the same : i.e. the
8247 signed is NOT propagated inwards : quoting from the
8248 ANSI - standard : "for E1 >> E2, is equivalent to division
8249 by 2**E2 if unsigned or if it has a non-negative value,
8250 otherwise the result is implementation defined ", MY definition
8251 is that the sign does not get propagated */
8253 right = IC_RIGHT (ic);
8254 left = IC_LEFT (ic);
8255 result = IC_RESULT (ic);
8257 aopOp (right, ic, FALSE);
8259 /* if the shift count is known then do it
8260 as efficiently as possible */
8261 if (AOP_TYPE (right) == AOP_LIT)
8263 genRightShiftLiteral (left, right, result, ic, 0);
8267 /* shift count is unknown then we have to form
8268 a loop get the loop count in B : Note: we take
8269 only the lower order byte since shifting
8270 more that 32 bits make no sense anyway, ( the
8271 largest size of an object can be only 32 bits ) */
8274 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8275 emitcode ("inc", "b");
8276 freeAsmop (right, NULL, ic, TRUE);
8277 aopOp (left, ic, FALSE);
8278 aopOp (result, ic, FALSE);
8280 /* now move the left to the result if they are not the
8282 if (!sameRegs (AOP (left), AOP (result)) &&
8283 AOP_SIZE (result) > 1)
8286 size = AOP_SIZE (result);
8290 l = aopGet (AOP (left), offset, FALSE, TRUE);
8291 if (*l == '@' && IS_AOP_PREG (result))
8294 emitcode ("mov", "a,%s", l);
8295 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8298 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8303 tlbl = newiTempLabel (NULL);
8304 tlbl1 = newiTempLabel (NULL);
8305 size = AOP_SIZE (result);
8308 /* if it is only one byte then */
8311 l = aopGet (AOP (left), 0, FALSE, FALSE);
8313 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8314 emitcode ("", "%05d$:", tlbl->key + 100);
8316 emitcode ("rrc", "a");
8317 emitcode ("", "%05d$:", tlbl1->key + 100);
8318 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8320 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8324 reAdjustPreg (AOP (result));
8325 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8326 emitcode ("", "%05d$:", tlbl->key + 100);
8330 l = aopGet (AOP (result), offset, FALSE, FALSE);
8332 emitcode ("rrc", "a");
8333 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8335 reAdjustPreg (AOP (result));
8337 emitcode ("", "%05d$:", tlbl1->key + 100);
8338 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8342 freeAsmop (left, NULL, ic, TRUE);
8343 freeAsmop (result, NULL, ic, TRUE);
8346 /*-----------------------------------------------------------------*/
8347 /* emitPtrByteGet - emits code to get a byte into A through a */
8348 /* pointer register (R0, R1, or DPTR). The */
8349 /* original value of A can be preserved in B. */
8350 /*-----------------------------------------------------------------*/
8352 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8359 emitcode ("mov", "b,a");
8360 emitcode ("mov", "a,@%s", rname);
8365 emitcode ("mov", "b,a");
8366 emitcode ("movx", "a,@%s", rname);
8371 emitcode ("mov", "b,a");
8372 emitcode ("movx", "a,@dptr");
8377 emitcode ("mov", "b,a");
8378 emitcode ("clr", "a");
8379 emitcode ("movc", "a,@a+dptr");
8385 emitcode ("push", "b");
8386 emitcode ("push", "acc");
8388 emitcode ("lcall", "__gptrget");
8390 emitcode ("pop", "b");
8395 /*-----------------------------------------------------------------*/
8396 /* emitPtrByteSet - emits code to set a byte from src through a */
8397 /* pointer register (R0, R1, or DPTR). */
8398 /*-----------------------------------------------------------------*/
8400 emitPtrByteSet (char *rname, int p_type, char *src)
8409 emitcode ("mov", "@%s,a", rname);
8412 emitcode ("mov", "@%s,%s", rname, src);
8417 emitcode ("movx", "@%s,a", rname);
8422 emitcode ("movx", "@dptr,a");
8427 emitcode ("lcall", "__gptrput");
8432 /*-----------------------------------------------------------------*/
8433 /* genUnpackBits - generates code for unpacking bits */
8434 /*-----------------------------------------------------------------*/
8436 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8438 int offset = 0; /* result byte offset */
8439 int rsize; /* result size */
8440 int rlen = 0; /* remaining bitfield length */
8441 sym_link *etype; /* bitfield type information */
8442 int blen; /* bitfield length */
8443 int bstr; /* bitfield starting bit within byte */
8446 D(emitcode ("; genUnpackBits",""));
8448 etype = getSpec (operandType (result));
8449 rsize = getSize (operandType (result));
8450 blen = SPEC_BLEN (etype);
8451 bstr = SPEC_BSTR (etype);
8453 if (ifx && blen <= 8)
8455 emitPtrByteGet (rname, ptype, FALSE);
8458 SNPRINTF (buffer, sizeof(buffer),
8460 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8465 emitcode ("anl", "a,#0x%02x",
8466 (((unsigned char) -1) >> (8 - blen)) << bstr);
8467 genIfxJump (ifx, "a", NULL, NULL, NULL);
8473 /* If the bitfield length is less than a byte */
8476 emitPtrByteGet (rname, ptype, FALSE);
8478 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8479 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8483 /* Bit field did not fit in a byte. Copy all
8484 but the partial byte at the end. */
8485 for (rlen=blen;rlen>=8;rlen-=8)
8487 emitPtrByteGet (rname, ptype, FALSE);
8488 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8490 emitcode ("inc", "%s", rname);
8493 /* Handle the partial byte at the end */
8496 emitPtrByteGet (rname, ptype, FALSE);
8497 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8498 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8506 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8511 /*-----------------------------------------------------------------*/
8512 /* genDataPointerGet - generates code when ptr offset is known */
8513 /*-----------------------------------------------------------------*/
8515 genDataPointerGet (operand * left,
8521 int size, offset = 0;
8523 D(emitcode ("; genDataPointerGet",""));
8525 aopOp (result, ic, TRUE);
8527 /* get the string representation of the name */
8528 l = aopGet (AOP (left), 0, FALSE, TRUE);
8529 size = AOP_SIZE (result);
8533 sprintf (buffer, "(%s + %d)", l + 1, offset);
8535 sprintf (buffer, "%s", l + 1);
8536 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8539 freeAsmop (left, NULL, ic, TRUE);
8540 freeAsmop (result, NULL, ic, TRUE);
8543 /*-----------------------------------------------------------------*/
8544 /* genNearPointerGet - emitcode for near pointer fetch */
8545 /*-----------------------------------------------------------------*/
8547 genNearPointerGet (operand * left,
8556 sym_link *rtype, *retype;
8557 sym_link *ltype = operandType (left);
8560 D(emitcode ("; genNearPointerGet",""));
8562 rtype = operandType (result);
8563 retype = getSpec (rtype);
8565 aopOp (left, ic, FALSE);
8567 /* if left is rematerialisable and
8568 result is not bitfield variable type and
8569 the left is pointer to data space i.e
8570 lower 128 bytes of space */
8571 if (AOP_TYPE (left) == AOP_IMMD &&
8572 !IS_BITFIELD (retype) &&
8573 DCL_TYPE (ltype) == POINTER)
8575 genDataPointerGet (left, result, ic);
8579 /* if the value is already in a pointer register
8580 then don't need anything more */
8581 if (!AOP_INPREG (AOP (left)))
8583 if (IS_AOP_PREG (left))
8585 // Aha, it is a pointer, just in disguise.
8586 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8589 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8590 __FILE__, __LINE__);
8595 emitcode ("mov", "a%s,%s", rname + 1, rname);
8596 rname++; // skip the '@'.
8601 /* otherwise get a free pointer register */
8603 preg = getFreePtr (ic, &aop, FALSE);
8604 emitcode ("mov", "%s,%s",
8606 aopGet (AOP (left), 0, FALSE, TRUE));
8611 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8613 //aopOp (result, ic, FALSE);
8614 aopOp (result, ic, result?TRUE:FALSE);
8616 /* if bitfield then unpack the bits */
8617 if (IS_BITFIELD (retype))
8618 genUnpackBits (result, rname, POINTER, ifx);
8621 /* we have can just get the values */
8622 int size = AOP_SIZE (result);
8627 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8630 emitcode ("mov", "a,@%s", rname);
8632 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8636 sprintf (buffer, "@%s", rname);
8637 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8641 emitcode ("inc", "%s", rname);
8645 /* now some housekeeping stuff */
8646 if (aop) /* we had to allocate for this iCode */
8648 if (pi) { /* post increment present */
8649 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8651 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8655 /* we did not allocate which means left
8656 already in a pointer register, then
8657 if size > 0 && this could be used again
8658 we have to point it back to where it
8660 if ((AOP_SIZE (result) > 1 &&
8661 !OP_SYMBOL (left)->remat &&
8662 (OP_SYMBOL (left)->liveTo > ic->seq ||
8666 int size = AOP_SIZE (result) - 1;
8668 emitcode ("dec", "%s", rname);
8672 if (ifx && !ifx->generated)
8674 genIfxJump (ifx, "a", left, NULL, result);
8678 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8679 freeAsmop (left, NULL, ic, TRUE);
8680 if (pi) pi->generated = 1;
8683 /*-----------------------------------------------------------------*/
8684 /* genPagedPointerGet - emitcode for paged pointer fetch */
8685 /*-----------------------------------------------------------------*/
8687 genPagedPointerGet (operand * left,
8696 sym_link *rtype, *retype;
8698 D(emitcode ("; genPagedPointerGet",""));
8700 rtype = operandType (result);
8701 retype = getSpec (rtype);
8703 aopOp (left, ic, FALSE);
8705 /* if the value is already in a pointer register
8706 then don't need anything more */
8707 if (!AOP_INPREG (AOP (left)))
8709 /* otherwise get a free pointer register */
8711 preg = getFreePtr (ic, &aop, FALSE);
8712 emitcode ("mov", "%s,%s",
8714 aopGet (AOP (left), 0, FALSE, TRUE));
8718 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8720 aopOp (result, ic, FALSE);
8722 /* if bitfield then unpack the bits */
8723 if (IS_BITFIELD (retype))
8724 genUnpackBits (result, rname, PPOINTER, ifx);
8727 /* we have can just get the values */
8728 int size = AOP_SIZE (result);
8734 emitcode ("movx", "a,@%s", rname);
8736 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8741 emitcode ("inc", "%s", rname);
8745 /* now some housekeeping stuff */
8746 if (aop) /* we had to allocate for this iCode */
8748 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8749 freeAsmop (NULL, aop, ic, TRUE);
8753 /* we did not allocate which means left
8754 already in a pointer register, then
8755 if size > 0 && this could be used again
8756 we have to point it back to where it
8758 if ((AOP_SIZE (result) > 1 &&
8759 !OP_SYMBOL (left)->remat &&
8760 (OP_SYMBOL (left)->liveTo > ic->seq ||
8764 int size = AOP_SIZE (result) - 1;
8766 emitcode ("dec", "%s", rname);
8770 if (ifx && !ifx->generated)
8772 genIfxJump (ifx, "a", left, NULL, result);
8776 freeAsmop (left, NULL, ic, TRUE);
8777 freeAsmop (result, NULL, ic, TRUE);
8778 if (pi) pi->generated = 1;
8782 /*--------------------------------------------------------------------*/
8783 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8784 /*--------------------------------------------------------------------*/
8786 loadDptrFromOperand (operand *op, bool loadBToo)
8788 if (AOP_TYPE (op) != AOP_STR)
8790 /* if this is rematerializable */
8791 if (AOP_TYPE (op) == AOP_IMMD)
8793 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8796 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8797 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8800 wassertl(FALSE, "need pointerCode");
8801 emitcode ("", "; mov b,???");
8802 /* genPointerGet and genPointerSet originally did different
8803 ** things for this case. Both seem wrong.
8804 ** from genPointerGet:
8805 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8806 ** from genPointerSet:
8807 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8812 else if (AOP_TYPE (op) == AOP_DPTR)
8816 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8817 emitcode ("push", "acc");
8818 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8819 emitcode ("push", "acc");
8820 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8821 emitcode ("pop", "dph");
8822 emitcode ("pop", "dpl");
8826 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8827 emitcode ("push", "acc");
8828 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8829 emitcode ("pop", "dpl");
8833 { /* we need to get it byte by byte */
8834 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8835 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8837 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8842 /*-----------------------------------------------------------------*/
8843 /* genFarPointerGet - gget value from far space */
8844 /*-----------------------------------------------------------------*/
8846 genFarPointerGet (operand * left,
8847 operand * result, iCode * ic, iCode * pi, iCode * ifx)
8850 sym_link *retype = getSpec (operandType (result));
8852 D(emitcode ("; genFarPointerGet",""));
8854 aopOp (left, ic, FALSE);
8855 loadDptrFromOperand (left, FALSE);
8857 /* so dptr now contains the address */
8858 aopOp (result, ic, FALSE);
8860 /* if bit then unpack */
8861 if (IS_BITFIELD (retype))
8862 genUnpackBits (result, "dptr", FPOINTER, ifx);
8865 size = AOP_SIZE (result);
8870 emitcode ("movx", "a,@dptr");
8872 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8874 emitcode ("inc", "dptr");
8878 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8880 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8881 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8885 if (ifx && !ifx->generated)
8887 genIfxJump (ifx, "a", left, NULL, result);
8890 freeAsmop (left, NULL, ic, TRUE);
8891 freeAsmop (result, NULL, ic, TRUE);
8894 /*-----------------------------------------------------------------*/
8895 /* genCodePointerGet - gget value from code space */
8896 /*-----------------------------------------------------------------*/
8898 genCodePointerGet (operand * left,
8899 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8902 sym_link *retype = getSpec (operandType (result));
8904 D(emitcode ("; genCodePointerGet",""));
8906 aopOp (left, ic, FALSE);
8907 loadDptrFromOperand (left, FALSE);
8909 /* so dptr now contains the address */
8910 aopOp (result, ic, FALSE);
8912 /* if bit then unpack */
8913 if (IS_BITFIELD (retype))
8914 genUnpackBits (result, "dptr", CPOINTER, ifx);
8917 size = AOP_SIZE (result);
8924 emitcode ("clr", "a");
8925 emitcode ("movc", "a,@a+dptr");
8927 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8928 emitcode ("inc", "dptr");
8932 emitcode ("mov", "a,#0x%02x", offset);
8933 emitcode ("movc", "a,@a+dptr");
8935 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8940 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8942 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8943 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8947 if (ifx && !ifx->generated)
8949 genIfxJump (ifx, "a", left, NULL, result);
8952 freeAsmop (left, NULL, ic, TRUE);
8953 freeAsmop (result, NULL, ic, TRUE);
8956 /*-----------------------------------------------------------------*/
8957 /* genGenPointerGet - gget value from generic pointer space */
8958 /*-----------------------------------------------------------------*/
8960 genGenPointerGet (operand * left,
8961 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8964 sym_link *retype = getSpec (operandType (result));
8966 D(emitcode ("; genGenPointerGet",""));
8968 aopOp (left, ic, FALSE);
8969 loadDptrFromOperand (left, TRUE);
8971 /* so dptr know contains the address */
8972 aopOp (result, ic, FALSE);
8974 /* if bit then unpack */
8975 if (IS_BITFIELD (retype))
8976 genUnpackBits (result, "dptr", GPOINTER, ifx);
8979 size = AOP_SIZE (result);
8984 emitcode ("lcall", "__gptrget");
8986 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8988 emitcode ("inc", "dptr");
8992 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8994 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8995 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8999 if (ifx && !ifx->generated)
9001 genIfxJump (ifx, "a", left, NULL, result);
9005 freeAsmop (left, NULL, ic, TRUE);
9006 freeAsmop (result, NULL, ic, TRUE);
9009 /*-----------------------------------------------------------------*/
9010 /* genPointerGet - generate code for pointer get */
9011 /*-----------------------------------------------------------------*/
9013 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9015 operand *left, *result;
9016 sym_link *type, *etype;
9019 D(emitcode ("; genPointerGet",""));
9021 left = IC_LEFT (ic);
9022 result = IC_RESULT (ic);
9024 if (getSize (operandType (result))>1)
9027 /* depending on the type of pointer we need to
9028 move it to the correct pointer register */
9029 type = operandType (left);
9030 etype = getSpec (type);
9031 /* if left is of type of pointer then it is simple */
9032 if (IS_PTR (type) && !IS_FUNC (type->next))
9033 p_type = DCL_TYPE (type);
9036 /* we have to go by the storage class */
9037 p_type = PTR_TYPE (SPEC_OCLS (etype));
9040 /* special case when cast remat */
9041 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9042 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9043 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9044 type = operandType (left);
9045 p_type = DCL_TYPE (type);
9047 /* now that we have the pointer type we assign
9048 the pointer values */
9054 genNearPointerGet (left, result, ic, pi, ifx);
9058 genPagedPointerGet (left, result, ic, pi, ifx);
9062 genFarPointerGet (left, result, ic, pi, ifx);
9066 genCodePointerGet (left, result, ic, pi, ifx);
9070 genGenPointerGet (left, result, ic, pi, ifx);
9078 /*-----------------------------------------------------------------*/
9079 /* genPackBits - generates code for packed bit storage */
9080 /*-----------------------------------------------------------------*/
9082 genPackBits (sym_link * etype,
9084 char *rname, int p_type)
9086 int offset = 0; /* source byte offset */
9087 int rlen = 0; /* remaining bitfield length */
9088 int blen; /* bitfield length */
9089 int bstr; /* bitfield starting bit within byte */
9090 int litval; /* source literal value (if AOP_LIT) */
9091 unsigned char mask; /* bitmask within current byte */
9093 D(emitcode ("; genPackBits",""));
9095 blen = SPEC_BLEN (etype);
9096 bstr = SPEC_BSTR (etype);
9098 /* If the bitfield length is less than a byte */
9101 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9102 (unsigned char) (0xFF >> (8 - bstr)));
9104 if (AOP_TYPE (right) == AOP_LIT)
9106 /* Case with a bitfield length <8 and literal source
9108 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9110 litval &= (~mask) & 0xff;
9111 emitPtrByteGet (rname, p_type, FALSE);
9112 if ((mask|litval)!=0xff)
9113 emitcode ("anl","a,#0x%02x", mask);
9115 emitcode ("orl","a,#0x%02x", litval);
9119 if ((blen==1) && (p_type!=GPOINTER))
9121 /* Case with a bitfield length == 1 and no generic pointer
9123 if (AOP_TYPE (right) == AOP_CRY)
9124 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9127 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9128 emitcode ("rrc","a");
9130 emitPtrByteGet (rname, p_type, FALSE);
9131 emitcode ("mov","acc.%d,c",bstr);
9136 /* Case with a bitfield length < 8 and arbitrary source
9138 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9139 /* shift and mask source value */
9141 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9144 /* transfer A to B and get next byte */
9145 emitPtrByteGet (rname, p_type, TRUE);
9147 emitcode ("anl", "a,#0x%02x", mask);
9148 emitcode ("orl", "a,b");
9149 if (p_type == GPOINTER)
9150 emitcode ("pop", "b");
9156 emitPtrByteSet (rname, p_type, "a");
9160 /* Bit length is greater than 7 bits. In this case, copy */
9161 /* all except the partial byte at the end */
9162 for (rlen=blen;rlen>=8;rlen-=8)
9164 emitPtrByteSet (rname, p_type,
9165 aopGet (AOP (right), offset++, FALSE, TRUE) );
9167 emitcode ("inc", "%s", rname);
9170 /* If there was a partial byte at the end */
9173 mask = (((unsigned char) -1 << rlen) & 0xff);
9175 if (AOP_TYPE (right) == AOP_LIT)
9177 /* Case with partial byte and literal source
9179 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9180 litval >>= (blen-rlen);
9181 litval &= (~mask) & 0xff;
9182 emitPtrByteGet (rname, p_type, FALSE);
9183 if ((mask|litval)!=0xff)
9184 emitcode ("anl","a,#0x%02x", mask);
9186 emitcode ("orl","a,#0x%02x", litval);
9191 /* Case with partial byte and arbitrary source
9193 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9194 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9197 /* transfer A to B and get next byte */
9198 emitPtrByteGet (rname, p_type, TRUE);
9200 emitcode ("anl", "a,#0x%02x", mask);
9201 emitcode ("orl", "a,b");
9202 if (p_type == GPOINTER)
9203 emitcode ("pop", "b");
9207 emitPtrByteSet (rname, p_type, "a");
9213 /*-----------------------------------------------------------------*/
9214 /* genDataPointerSet - remat pointer to data space */
9215 /*-----------------------------------------------------------------*/
9217 genDataPointerSet (operand * right,
9221 int size, offset = 0;
9222 char *l, buffer[256];
9224 D(emitcode ("; genDataPointerSet",""));
9226 aopOp (right, ic, FALSE);
9228 l = aopGet (AOP (result), 0, FALSE, TRUE);
9229 size = AOP_SIZE (right);
9233 sprintf (buffer, "(%s + %d)", l + 1, offset);
9235 sprintf (buffer, "%s", l + 1);
9236 emitcode ("mov", "%s,%s", buffer,
9237 aopGet (AOP (right), offset++, FALSE, FALSE));
9240 freeAsmop (right, NULL, ic, TRUE);
9241 freeAsmop (result, NULL, ic, TRUE);
9244 /*-----------------------------------------------------------------*/
9245 /* genNearPointerSet - emitcode for near pointer put */
9246 /*-----------------------------------------------------------------*/
9248 genNearPointerSet (operand * right,
9256 sym_link *retype, *letype;
9257 sym_link *ptype = operandType (result);
9259 D(emitcode ("; genNearPointerSet",""));
9261 retype = getSpec (operandType (right));
9262 letype = getSpec (ptype);
9263 aopOp (result, ic, FALSE);
9265 /* if the result is rematerializable &
9266 in data space & not a bit variable */
9267 if (AOP_TYPE (result) == AOP_IMMD &&
9268 DCL_TYPE (ptype) == POINTER &&
9269 !IS_BITVAR (retype) &&
9270 !IS_BITVAR (letype))
9272 genDataPointerSet (right, result, ic);
9276 /* if the value is already in a pointer register
9277 then don't need anything more */
9278 if (!AOP_INPREG (AOP (result)))
9281 //AOP_TYPE (result) == AOP_STK
9285 // Aha, it is a pointer, just in disguise.
9286 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9289 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9290 __FILE__, __LINE__);
9295 emitcode ("mov", "a%s,%s", rname + 1, rname);
9296 rname++; // skip the '@'.
9301 /* otherwise get a free pointer register */
9303 preg = getFreePtr (ic, &aop, FALSE);
9304 emitcode ("mov", "%s,%s",
9306 aopGet (AOP (result), 0, FALSE, TRUE));
9312 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9315 aopOp (right, ic, FALSE);
9317 /* if bitfield then unpack the bits */
9318 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9319 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9322 /* we have can just get the values */
9323 int size = AOP_SIZE (right);
9328 l = aopGet (AOP (right), offset, FALSE, TRUE);
9332 emitcode ("mov", "@%s,a", rname);
9335 emitcode ("mov", "@%s,%s", rname, l);
9337 emitcode ("inc", "%s", rname);
9342 /* now some housekeeping stuff */
9343 if (aop) /* we had to allocate for this iCode */
9346 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9347 freeAsmop (NULL, aop, ic, TRUE);
9351 /* we did not allocate which means left
9352 already in a pointer register, then
9353 if size > 0 && this could be used again
9354 we have to point it back to where it
9356 if ((AOP_SIZE (right) > 1 &&
9357 !OP_SYMBOL (result)->remat &&
9358 (OP_SYMBOL (result)->liveTo > ic->seq ||
9362 int size = AOP_SIZE (right) - 1;
9364 emitcode ("dec", "%s", rname);
9369 if (pi) pi->generated = 1;
9370 freeAsmop (result, NULL, ic, TRUE);
9371 freeAsmop (right, NULL, ic, TRUE);
9374 /*-----------------------------------------------------------------*/
9375 /* genPagedPointerSet - emitcode for Paged pointer put */
9376 /*-----------------------------------------------------------------*/
9378 genPagedPointerSet (operand * right,
9386 sym_link *retype, *letype;
9388 D(emitcode ("; genPagedPointerSet",""));
9390 retype = getSpec (operandType (right));
9391 letype = getSpec (operandType (result));
9393 aopOp (result, ic, FALSE);
9395 /* if the value is already in a pointer register
9396 then don't need anything more */
9397 if (!AOP_INPREG (AOP (result)))
9399 /* otherwise get a free pointer register */
9401 preg = getFreePtr (ic, &aop, FALSE);
9402 emitcode ("mov", "%s,%s",
9404 aopGet (AOP (result), 0, FALSE, TRUE));
9408 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9410 aopOp (right, ic, FALSE);
9412 /* if bitfield then unpack the bits */
9413 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9414 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9417 /* we have can just get the values */
9418 int size = AOP_SIZE (right);
9423 l = aopGet (AOP (right), offset, FALSE, TRUE);
9426 emitcode ("movx", "@%s,a", rname);
9429 emitcode ("inc", "%s", rname);
9435 /* now some housekeeping stuff */
9436 if (aop) /* we had to allocate for this iCode */
9439 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9440 freeAsmop (NULL, aop, ic, TRUE);
9444 /* we did not allocate which means left
9445 already in a pointer register, then
9446 if size > 0 && this could be used again
9447 we have to point it back to where it
9449 if (AOP_SIZE (right) > 1 &&
9450 !OP_SYMBOL (result)->remat &&
9451 (OP_SYMBOL (result)->liveTo > ic->seq ||
9454 int size = AOP_SIZE (right) - 1;
9456 emitcode ("dec", "%s", rname);
9461 if (pi) pi->generated = 1;
9462 freeAsmop (result, NULL, ic, TRUE);
9463 freeAsmop (right, NULL, ic, TRUE);
9468 /*-----------------------------------------------------------------*/
9469 /* genFarPointerSet - set value from far space */
9470 /*-----------------------------------------------------------------*/
9472 genFarPointerSet (operand * right,
9473 operand * result, iCode * ic, iCode * pi)
9476 sym_link *retype = getSpec (operandType (right));
9477 sym_link *letype = getSpec (operandType (result));
9479 D(emitcode ("; genFarPointerSet",""));
9481 aopOp (result, ic, FALSE);
9482 loadDptrFromOperand (result, FALSE);
9484 /* so dptr know contains the address */
9485 aopOp (right, ic, FALSE);
9487 /* if bit then unpack */
9488 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9489 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9492 size = AOP_SIZE (right);
9497 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9499 emitcode ("movx", "@dptr,a");
9501 emitcode ("inc", "dptr");
9504 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9505 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9506 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9509 freeAsmop (result, NULL, ic, TRUE);
9510 freeAsmop (right, NULL, ic, TRUE);
9513 /*-----------------------------------------------------------------*/
9514 /* genGenPointerSet - set value from generic pointer space */
9515 /*-----------------------------------------------------------------*/
9517 genGenPointerSet (operand * right,
9518 operand * result, iCode * ic, iCode * pi)
9521 sym_link *retype = getSpec (operandType (right));
9522 sym_link *letype = getSpec (operandType (result));
9524 D(emitcode ("; genGenPointerSet",""));
9526 aopOp (result, ic, FALSE);
9527 loadDptrFromOperand (result, TRUE);
9529 /* so dptr know contains the address */
9530 aopOp (right, ic, FALSE);
9532 /* if bit then unpack */
9533 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9534 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9537 size = AOP_SIZE (right);
9542 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9544 emitcode ("lcall", "__gptrput");
9546 emitcode ("inc", "dptr");
9550 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9551 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9552 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9555 freeAsmop (result, NULL, ic, TRUE);
9556 freeAsmop (right, NULL, ic, TRUE);
9559 /*-----------------------------------------------------------------*/
9560 /* genPointerSet - stores the value into a pointer location */
9561 /*-----------------------------------------------------------------*/
9563 genPointerSet (iCode * ic, iCode *pi)
9565 operand *right, *result;
9566 sym_link *type, *etype;
9569 D(emitcode ("; genPointerSet",""));
9571 right = IC_RIGHT (ic);
9572 result = IC_RESULT (ic);
9574 /* depending on the type of pointer we need to
9575 move it to the correct pointer register */
9576 type = operandType (result);
9577 etype = getSpec (type);
9578 /* if left is of type of pointer then it is simple */
9579 if (IS_PTR (type) && !IS_FUNC (type->next))
9581 p_type = DCL_TYPE (type);
9585 /* we have to go by the storage class */
9586 p_type = PTR_TYPE (SPEC_OCLS (etype));
9589 /* special case when cast remat */
9590 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9591 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9592 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9593 type = operandType (result);
9594 p_type = DCL_TYPE (type);
9596 /* now that we have the pointer type we assign
9597 the pointer values */
9603 genNearPointerSet (right, result, ic, pi);
9607 genPagedPointerSet (right, result, ic, pi);
9611 genFarPointerSet (right, result, ic, pi);
9615 genGenPointerSet (right, result, ic, pi);
9619 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9620 "genPointerSet: illegal pointer type");
9625 /*-----------------------------------------------------------------*/
9626 /* genIfx - generate code for Ifx statement */
9627 /*-----------------------------------------------------------------*/
9629 genIfx (iCode * ic, iCode * popIc)
9631 operand *cond = IC_COND (ic);
9634 D(emitcode ("; genIfx",""));
9636 aopOp (cond, ic, FALSE);
9638 /* get the value into acc */
9639 if (AOP_TYPE (cond) != AOP_CRY)
9643 /* the result is now in the accumulator */
9644 freeAsmop (cond, NULL, ic, TRUE);
9646 /* if there was something to be popped then do it */
9650 /* if the condition is a bit variable */
9651 if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
9652 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9653 else if (isbit && !IS_ITEMP (cond))
9654 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9656 genIfxJump (ic, "a", NULL, NULL, NULL);
9661 /*-----------------------------------------------------------------*/
9662 /* genAddrOf - generates code for address of */
9663 /*-----------------------------------------------------------------*/
9665 genAddrOf (iCode * ic)
9667 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9670 D(emitcode ("; genAddrOf",""));
9672 aopOp (IC_RESULT (ic), ic, FALSE);
9674 /* if the operand is on the stack then we
9675 need to get the stack offset of this
9679 /* if it has an offset then we need to compute
9683 emitcode ("mov", "a,%s", SYM_BP (sym));
9684 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9685 ((char) (sym->stack - _G.nRegsSaved)) :
9686 ((char) sym->stack)) & 0xff);
9687 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9691 /* we can just move _bp */
9692 aopPut (AOP (IC_RESULT (ic)), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9694 /* fill the result with zero */
9695 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9700 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9706 /* object not on stack then we need the name */
9707 size = AOP_SIZE (IC_RESULT (ic));
9712 char s[SDCC_NAME_MAX];
9714 sprintf (s, "#(%s >> %d)",
9718 sprintf (s, "#%s", sym->rname);
9719 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9723 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9727 /*-----------------------------------------------------------------*/
9728 /* genFarFarAssign - assignment when both are in far space */
9729 /*-----------------------------------------------------------------*/
9731 genFarFarAssign (operand * result, operand * right, iCode * ic)
9733 int size = AOP_SIZE (right);
9737 D(emitcode ("; genFarFarAssign",""));
9739 /* first push the right side on to the stack */
9742 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9744 emitcode ("push", "acc");
9747 freeAsmop (right, NULL, ic, FALSE);
9748 /* now assign DPTR to result */
9749 aopOp (result, ic, FALSE);
9750 size = AOP_SIZE (result);
9753 emitcode ("pop", "acc");
9754 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9756 freeAsmop (result, NULL, ic, FALSE);
9760 /*-----------------------------------------------------------------*/
9761 /* genAssign - generate code for assignment */
9762 /*-----------------------------------------------------------------*/
9764 genAssign (iCode * ic)
9766 operand *result, *right;
9768 unsigned long lit = 0L;
9770 D(emitcode("; genAssign",""));
9772 result = IC_RESULT (ic);
9773 right = IC_RIGHT (ic);
9775 /* if they are the same */
9776 if (operandsEqu (result, right) &&
9777 !isOperandVolatile (result, FALSE) &&
9778 !isOperandVolatile (right, FALSE))
9781 aopOp (right, ic, FALSE);
9783 /* special case both in far space */
9784 if (AOP_TYPE (right) == AOP_DPTR &&
9785 IS_TRUE_SYMOP (result) &&
9786 isOperandInFarSpace (result))
9789 genFarFarAssign (result, right, ic);
9793 aopOp (result, ic, TRUE);
9795 /* if they are the same registers */
9796 if (sameRegs (AOP (right), AOP (result)) &&
9797 !isOperandVolatile (result, FALSE) &&
9798 !isOperandVolatile (right, FALSE))
9801 /* if the result is a bit */
9802 if (AOP_TYPE (result) == AOP_CRY)
9805 /* if the right size is a literal then
9806 we know what the value is */
9807 if (AOP_TYPE (right) == AOP_LIT)
9809 if (((int) operandLitValue (right)))
9810 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9812 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9816 /* the right is also a bit variable */
9817 if (AOP_TYPE (right) == AOP_CRY)
9819 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9820 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9826 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9830 /* bit variables done */
9832 size = AOP_SIZE (result);
9834 if (AOP_TYPE (right) == AOP_LIT)
9835 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9837 (AOP_TYPE (result) != AOP_REG) &&
9838 (AOP_TYPE (right) == AOP_LIT) &&
9839 !IS_FLOAT (operandType (right)) &&
9842 while ((size) && (lit))
9844 aopPut (AOP (result),
9845 aopGet (AOP (right), offset, FALSE, FALSE),
9847 isOperandVolatile (result, FALSE));
9852 emitcode ("clr", "a");
9855 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
9863 aopPut (AOP (result),
9864 aopGet (AOP (right), offset, FALSE, FALSE),
9866 isOperandVolatile (result, FALSE));
9872 freeAsmop (right, NULL, ic, TRUE);
9873 freeAsmop (result, NULL, ic, TRUE);
9876 /*-----------------------------------------------------------------*/
9877 /* genJumpTab - generates code for jump table */
9878 /*-----------------------------------------------------------------*/
9880 genJumpTab (iCode * ic)
9882 symbol *jtab,*jtablo,*jtabhi;
9886 D(emitcode ("; genJumpTab",""));
9888 count = elementsInSet( IC_JTLABELS (ic) );
9892 /* this algorithm needs 9 cycles and 7 + 3*n bytes
9893 if the switch argument is in a register.
9894 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9895 /* (MB) What if peephole converts ljmp to sjmp or ret ???
9896 How will multiply by three be updated ???*/
9897 aopOp (IC_JTCOND (ic), ic, FALSE);
9898 /* get the condition into accumulator */
9899 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9901 /* multiply by three */
9902 emitcode ("add", "a,acc");
9903 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9904 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9906 jtab = newiTempLabel (NULL);
9907 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9908 emitcode ("jmp", "@a+dptr");
9909 emitcode ("", "%05d$:", jtab->key + 100);
9910 /* now generate the jump labels */
9911 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9912 jtab = setNextItem (IC_JTLABELS (ic)))
9913 emitcode ("ljmp", "%05d$", jtab->key + 100);
9917 /* this algorithm needs 14 cycles and 13 + 2*n bytes
9918 if the switch argument is in a register.
9919 For n>6 this algorithm may be more compact */
9920 jtablo = newiTempLabel (NULL);
9921 jtabhi = newiTempLabel (NULL);
9923 /* get the condition into accumulator.
9924 Using b as temporary storage, if register push/pop is needed */
9925 aopOp (IC_JTCOND (ic), ic, FALSE);
9926 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9927 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9928 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9930 // (MB) what if B is in use???
9931 wassertl(!BINUSE, "B was in use");
9932 emitcode ("mov", "b,%s", l);
9935 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9939 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9940 emitcode ("movc", "a,@a+pc");
9941 emitcode ("push", "acc");
9944 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9945 emitcode ("movc", "a,@a+pc");
9946 emitcode ("push", "acc");
9950 /* this scales up to n<=255, but needs two more bytes
9952 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9953 emitcode ("movc", "a,@a+dptr");
9954 emitcode ("push", "acc");
9957 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9958 emitcode ("movc", "a,@a+dptr");
9959 emitcode ("push", "acc");
9962 emitcode ("ret", "");
9964 /* now generate jump table, LSB */
9965 emitcode ("", "%05d$:", jtablo->key + 100);
9966 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9967 jtab = setNextItem (IC_JTLABELS (ic)))
9968 emitcode (".db", "%05d$", jtab->key + 100);
9970 /* now generate jump table, MSB */
9971 emitcode ("", "%05d$:", jtabhi->key + 100);
9972 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9973 jtab = setNextItem (IC_JTLABELS (ic)))
9974 emitcode (".db", "%05d$>>8", jtab->key + 100);
9978 /*-----------------------------------------------------------------*/
9979 /* genCast - gen code for casting */
9980 /*-----------------------------------------------------------------*/
9982 genCast (iCode * ic)
9984 operand *result = IC_RESULT (ic);
9985 sym_link *ctype = operandType (IC_LEFT (ic));
9986 sym_link *rtype = operandType (IC_RIGHT (ic));
9987 operand *right = IC_RIGHT (ic);
9990 D(emitcode("; genCast",""));
9992 /* if they are equivalent then do nothing */
9993 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9996 aopOp (right, ic, FALSE);
9997 aopOp (result, ic, FALSE);
9999 /* if the result is a bit (and not a bitfield) */
10000 // if (AOP_TYPE (result) == AOP_CRY)
10001 if (IS_BITVAR (OP_SYMBOL (result)->type)
10002 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10004 /* if the right size is a literal then
10005 we know what the value is */
10006 if (AOP_TYPE (right) == AOP_LIT)
10008 if (((int) operandLitValue (right)))
10009 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
10011 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
10016 /* the right is also a bit variable */
10017 if (AOP_TYPE (right) == AOP_CRY)
10019 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10020 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
10024 /* we need to or */
10026 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
10031 /* if they are the same size : or less */
10032 if (AOP_SIZE (result) <= AOP_SIZE (right))
10035 /* if they are in the same place */
10036 if (sameRegs (AOP (right), AOP (result)))
10039 /* if they in different places then copy */
10040 size = AOP_SIZE (result);
10044 aopPut (AOP (result),
10045 aopGet (AOP (right), offset, FALSE, FALSE),
10047 isOperandVolatile (result, FALSE));
10054 /* if the result is of type pointer */
10055 if (IS_PTR (ctype))
10059 sym_link *type = operandType (right);
10060 sym_link *etype = getSpec (type);
10062 /* pointer to generic pointer */
10063 if (IS_GENPTR (ctype))
10066 p_type = DCL_TYPE (type);
10069 if (SPEC_SCLS(etype)==S_REGISTER) {
10070 // let's assume it is a generic pointer
10073 /* we have to go by the storage class */
10074 p_type = PTR_TYPE (SPEC_OCLS (etype));
10078 /* the first two bytes are known */
10079 size = GPTRSIZE - 1;
10083 aopPut (AOP (result),
10084 aopGet (AOP (right), offset, FALSE, FALSE),
10086 isOperandVolatile (result, FALSE));
10089 /* the last byte depending on type */
10091 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10096 // pointerTypeToGPByte will have bitched.
10100 sprintf(gpValStr, "#0x%d", gpVal);
10101 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10106 /* just copy the pointers */
10107 size = AOP_SIZE (result);
10111 aopPut (AOP (result),
10112 aopGet (AOP (right), offset, FALSE, FALSE),
10114 isOperandVolatile (result, FALSE));
10120 /* so we now know that the size of destination is greater
10121 than the size of the source */
10122 /* we move to result for the size of source */
10123 size = AOP_SIZE (right);
10127 aopPut (AOP (result),
10128 aopGet (AOP (right), offset, FALSE, FALSE),
10130 isOperandVolatile (result, FALSE));
10134 /* now depending on the sign of the source && destination */
10135 size = AOP_SIZE (result) - AOP_SIZE (right);
10136 /* if unsigned or not an integral type */
10137 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10140 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
10144 /* we need to extend the sign :{ */
10145 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10148 emitcode ("rlc", "a");
10149 emitcode ("subb", "a,acc");
10151 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
10154 /* we are done hurray !!!! */
10157 freeAsmop (right, NULL, ic, TRUE);
10158 freeAsmop (result, NULL, ic, TRUE);
10162 /*-----------------------------------------------------------------*/
10163 /* genDjnz - generate decrement & jump if not zero instrucion */
10164 /*-----------------------------------------------------------------*/
10166 genDjnz (iCode * ic, iCode * ifx)
10168 symbol *lbl, *lbl1;
10172 D(emitcode ("; genDjnz",""));
10174 /* if the if condition has a false label
10175 then we cannot save */
10176 if (IC_FALSE (ifx))
10179 /* if the minus is not of the form
10181 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10182 !IS_OP_LITERAL (IC_RIGHT (ic)))
10185 if (operandLitValue (IC_RIGHT (ic)) != 1)
10188 /* if the size of this greater than one then no
10190 if (getSize (operandType (IC_RESULT (ic))) > 1)
10193 /* otherwise we can save BIG */
10194 lbl = newiTempLabel (NULL);
10195 lbl1 = newiTempLabel (NULL);
10197 aopOp (IC_RESULT (ic), ic, FALSE);
10199 if (AOP_NEEDSACC(IC_RESULT(ic)))
10201 /* If the result is accessed indirectly via
10202 * the accumulator, we must explicitly write
10203 * it back after the decrement.
10205 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
10207 if (strcmp(rByte, "a"))
10209 /* Something is hopelessly wrong */
10210 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10211 __FILE__, __LINE__);
10212 /* We can just give up; the generated code will be inefficient,
10213 * but what the hey.
10215 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10218 emitcode ("dec", "%s", rByte);
10219 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10220 emitcode ("jnz", "%05d$", lbl->key + 100);
10222 else if (IS_AOP_PREG (IC_RESULT (ic)))
10224 emitcode ("dec", "%s",
10225 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10226 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10227 emitcode ("jnz", "%05d$", lbl->key + 100);
10231 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
10234 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10235 emitcode ("", "%05d$:", lbl->key + 100);
10236 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10237 emitcode ("", "%05d$:", lbl1->key + 100);
10239 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10240 ifx->generated = 1;
10244 /*-----------------------------------------------------------------*/
10245 /* genReceive - generate code for a receive iCode */
10246 /*-----------------------------------------------------------------*/
10248 genReceive (iCode * ic)
10250 int size = getSize (operandType (IC_RESULT (ic)));
10252 D(emitcode ("; genReceive",""));
10254 if (ic->argreg == 1) { /* first parameter */
10255 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10256 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10257 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10260 int receivingA = 0;
10263 for (offset = 0; offset<size; offset++)
10264 if (!strcmp (fReturn[offset], "a"))
10269 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10271 for (offset = size-1; offset>0; offset--)
10272 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10273 emitcode("mov","a,%s", fReturn[0]);
10275 aopOp (IC_RESULT (ic), ic, FALSE);
10277 aopPut (AOP (IC_RESULT (ic)), "a", offset,
10278 isOperandVolatile (IC_RESULT (ic), FALSE));
10279 for (offset = 1; offset<size; offset++)
10280 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
10281 isOperandVolatile (IC_RESULT (ic), FALSE));
10287 if (getTempRegs(tempRegs, size, ic))
10289 for (offset = 0; offset<size; offset++)
10290 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10291 aopOp (IC_RESULT (ic), ic, FALSE);
10292 for (offset = 0; offset<size; offset++)
10293 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
10294 isOperandVolatile (IC_RESULT (ic), FALSE));
10299 offset = fReturnSizeMCS51 - size;
10301 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10302 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10305 aopOp (IC_RESULT (ic), ic, FALSE);
10306 size = AOP_SIZE (IC_RESULT (ic));
10309 emitcode ("pop", "acc");
10310 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10315 aopOp (IC_RESULT (ic), ic, FALSE);
10317 assignResultValue (IC_RESULT (ic));
10319 } else { /* second receive onwards */
10321 aopOp (IC_RESULT (ic), ic, FALSE);
10322 rb1off = ic->argreg;
10324 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10329 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10332 /*-----------------------------------------------------------------*/
10333 /* genDummyRead - generate code for dummy read of volatiles */
10334 /*-----------------------------------------------------------------*/
10336 genDummyRead (iCode * ic)
10341 D(emitcode("; genDummyRead",""));
10343 op = IC_RIGHT (ic);
10344 if (op && IS_SYMOP (op))
10346 aopOp (op, ic, FALSE);
10348 /* if the result is a bit */
10349 if (AOP_TYPE (op) == AOP_CRY)
10350 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10353 /* bit variables done */
10355 size = AOP_SIZE (op);
10359 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10364 freeAsmop (op, NULL, ic, TRUE);
10368 if (op && IS_SYMOP (op))
10370 aopOp (op, ic, FALSE);
10372 /* if the result is a bit */
10373 if (AOP_TYPE (op) == AOP_CRY)
10374 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10377 /* bit variables done */
10379 size = AOP_SIZE (op);
10383 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10388 freeAsmop (op, NULL, ic, TRUE);
10392 /*-----------------------------------------------------------------*/
10393 /* genCritical - generate code for start of a critical sequence */
10394 /*-----------------------------------------------------------------*/
10396 genCritical (iCode *ic)
10398 symbol *tlbl = newiTempLabel (NULL);
10400 D(emitcode("; genCritical",""));
10402 if (IC_RESULT (ic))
10404 aopOp (IC_RESULT (ic), ic, TRUE);
10405 aopPut (AOP (IC_RESULT (ic)), one, 0, 0);
10406 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10407 aopPut (AOP (IC_RESULT (ic)), zero, 0, 0);
10408 emitcode ("", "%05d$:", (tlbl->key + 100));
10409 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10413 emitcode ("setb", "c");
10414 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10415 emitcode ("clr", "c");
10416 emitcode ("", "%05d$:", (tlbl->key + 100));
10417 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10421 /*-----------------------------------------------------------------*/
10422 /* genEndCritical - generate code for end of a critical sequence */
10423 /*-----------------------------------------------------------------*/
10425 genEndCritical (iCode *ic)
10427 D(emitcode("; genEndCritical",""));
10431 aopOp (IC_RIGHT (ic), ic, FALSE);
10432 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10434 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10435 emitcode ("mov", "ea,c");
10439 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10440 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
10441 emitcode ("rrc", "a");
10442 emitcode ("mov", "ea,c");
10444 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10448 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10449 emitcode ("mov", "ea,c");
10453 /*-----------------------------------------------------------------*/
10454 /* gen51Code - generate code for 8051 based controllers */
10455 /*-----------------------------------------------------------------*/
10457 gen51Code (iCode * lic)
10461 /* int cseq = 0; */
10463 _G.currentFunc = NULL;
10464 lineHead = lineCurr = NULL;
10466 /* print the allocation information */
10467 if (allocInfo && currFunc)
10468 printAllocInfo (currFunc, codeOutFile);
10469 /* if debug information required */
10470 if (options.debug && currFunc)
10472 debugFile->writeFunction (currFunc, lic);
10474 /* stack pointer name */
10475 if (options.useXstack)
10481 for (ic = lic; ic; ic = ic->next)
10483 _G.current_iCode = ic;
10485 if (ic->lineno && cln != ic->lineno)
10489 debugFile->writeCLine (ic);
10491 if (!options.noCcodeInAsm) {
10492 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10493 printCLine(ic->filename, ic->lineno));
10498 if (ic->seqPoint && ic->seqPoint != cseq)
10500 emitcode ("", "; sequence point %d", ic->seqPoint);
10501 cseq = ic->seqPoint;
10504 if (options.iCodeInAsm) {
10505 char regsInUse[80];
10508 for (i=0; i<8; i++) {
10509 sprintf (®sInUse[i],
10510 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10513 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10515 /* if the result is marked as
10516 spilt and rematerializable or code for
10517 this has already been generated then
10519 if (resultRemat (ic) || ic->generated)
10522 /* depending on the operation */
10542 /* IPOP happens only when trying to restore a
10543 spilt live range, if there is an ifx statement
10544 following this pop then the if statement might
10545 be using some of the registers being popped which
10546 would destory the contents of the register so
10547 we need to check for this condition and handle it */
10549 ic->next->op == IFX &&
10550 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10551 genIfx (ic->next, ic);
10569 genEndFunction (ic);
10589 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10606 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10610 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10617 /* note these two are xlated by algebraic equivalence
10618 during parsing SDCC.y */
10619 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10620 "got '>=' or '<=' shouldn't have come here");
10624 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10636 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10640 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10644 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10668 genRightShift (ic);
10671 case GET_VALUE_AT_ADDRESS:
10673 hasInc (IC_LEFT (ic), ic,
10674 getSize (operandType (IC_RESULT (ic)))),
10675 ifxForOp (IC_RESULT (ic), ic) );
10679 if (POINTER_SET (ic))
10680 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10706 addSet (&_G.sendSet, ic);
10709 case DUMMY_READ_VOLATILE:
10718 genEndCritical (ic);
10730 _G.current_iCode = NULL;
10732 /* now we are ready to call the
10733 peep hole optimizer */
10734 if (!options.nopeep)
10735 peepHole (&lineHead);
10737 /* now do the actual printing */
10738 printLine (lineHead, codeOutFile);