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"));
1114 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1120 /* Error case --- will have been caught already */
1126 /*-----------------------------------------------------------------*/
1127 /* aopGet - for fetching value of the aop */
1128 /*-----------------------------------------------------------------*/
1130 aopGet (asmop * aop, int offset, bool bit16, bool dname)
1135 /* offset is greater than
1137 if (offset > (aop->size - 1) &&
1138 aop->type != AOP_LIT)
1141 /* depending on type */
1149 /* if we need to increment it */
1150 while (offset > aop->coff)
1152 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1156 while (offset < aop->coff)
1158 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1165 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1166 return (dname ? "acc" : "a");
1168 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1169 rs = Safe_calloc (1, strlen (s) + 1);
1174 if (aop->code && aop->coff==0 && offset>=1) {
1175 emitcode ("mov", "a,#0x%02x", offset);
1176 emitcode ("movc", "a,@a+dptr");
1177 return (dname ? "acc" : "a");
1180 while (offset > aop->coff)
1182 emitcode ("inc", "dptr");
1186 while (offset < aop->coff)
1188 emitcode ("lcall", "__decdptr");
1195 emitcode ("clr", "a");
1196 emitcode ("movc", "a,@a+dptr");
1200 emitcode ("movx", "a,@dptr");
1202 return (dname ? "acc" : "a");
1206 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1207 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1209 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1211 sprintf (s, "#(%s >> %d)",
1212 aop->aopu.aop_immd.aop_immd1,
1216 aop->aopu.aop_immd.aop_immd1);
1217 rs = Safe_calloc (1, strlen (s) + 1);
1223 sprintf (s, "(%s + %d)",
1227 sprintf (s, "%s", aop->aopu.aop_dir);
1228 rs = Safe_calloc (1, strlen (s) + 1);
1234 return aop->aopu.aop_reg[offset]->dname;
1236 return aop->aopu.aop_reg[offset]->name;
1239 emitcode ("clr", "a");
1240 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1241 emitcode ("rlc", "a");
1242 return (dname ? "acc" : "a");
1245 if (!offset && dname)
1247 return aop->aopu.aop_str[offset];
1250 return aopLiteral (aop->aopu.aop_lit, offset);
1254 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1258 return aop->aopu.aop_str[offset];
1262 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1263 "aopget got unsupported aop->type");
1266 /*-----------------------------------------------------------------*/
1267 /* aopPut - puts a string for a aop and indicates if acc is in use */
1268 /*-----------------------------------------------------------------*/
1270 aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
1273 bool accuse = FALSE;
1275 if (aop->size && offset > (aop->size - 1))
1277 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1278 "aopPut got offset > aop->size");
1282 /* will assign value to value */
1283 /* depending on where it is ofcourse */
1287 MOVA (s); /* read s in case it was volatile */
1293 sprintf (d, "(%s + %d)",
1294 aop->aopu.aop_dir, offset);
1296 sprintf (d, "%s", aop->aopu.aop_dir);
1298 if (strcmp (d, s) ||
1300 emitcode ("mov", "%s,%s", d, s);
1301 if (!strcmp (d, "acc"))
1307 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1308 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1311 strcmp (s, "r0") == 0 ||
1312 strcmp (s, "r1") == 0 ||
1313 strcmp (s, "r2") == 0 ||
1314 strcmp (s, "r3") == 0 ||
1315 strcmp (s, "r4") == 0 ||
1316 strcmp (s, "r5") == 0 ||
1317 strcmp (s, "r6") == 0 ||
1318 strcmp (s, "r7") == 0)
1319 emitcode ("mov", "%s,%s",
1320 aop->aopu.aop_reg[offset]->dname, s);
1322 emitcode ("mov", "%s,%s",
1323 aop->aopu.aop_reg[offset]->name, s);
1330 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1331 "aopPut writing to code space");
1335 while (offset > aop->coff)
1338 emitcode ("inc", "dptr");
1341 while (offset < aop->coff)
1344 emitcode ("lcall", "__decdptr");
1349 /* if not in accumulator */
1352 emitcode ("movx", "@dptr,a");
1357 while (offset > aop->coff)
1360 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1362 while (offset < aop->coff)
1365 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1372 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1378 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1380 else if (strcmp (s, "r0") == 0 ||
1381 strcmp (s, "r1") == 0 ||
1382 strcmp (s, "r2") == 0 ||
1383 strcmp (s, "r3") == 0 ||
1384 strcmp (s, "r4") == 0 ||
1385 strcmp (s, "r5") == 0 ||
1386 strcmp (s, "r6") == 0 ||
1387 strcmp (s, "r7") == 0)
1390 sprintf (buffer, "a%s", s);
1391 emitcode ("mov", "@%s,%s",
1392 aop->aopu.aop_ptr->name, buffer);
1395 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1400 if (strcmp (s, "a") == 0)
1401 emitcode ("push", "acc");
1405 emitcode ("push", "acc");
1407 emitcode ("push", s);
1413 /* if not bit variable */
1414 if (!aop->aopu.aop_dir)
1416 /* inefficient: move carry into A and use jz/jnz */
1417 emitcode ("clr", "a");
1418 emitcode ("rlc", "a");
1424 emitcode ("clr", "%s", aop->aopu.aop_dir);
1426 emitcode ("setb", "%s", aop->aopu.aop_dir);
1427 else if (!strcmp (s, "c"))
1428 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1432 /* set C, if a >= 1 */
1433 emitcode ("add", "a,#0xff");
1434 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1441 if (strcmp (aop->aopu.aop_str[offset], s) ||
1443 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1449 if (!offset && (strcmp (s, "acc") == 0) &&
1453 if (strcmp (aop->aopu.aop_str[offset], s) &&
1455 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1459 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1460 "aopPut got unsupported aop->type");
1469 /*-----------------------------------------------------------------*/
1470 /* pointToEnd :- points to the last byte of the operand */
1471 /*-----------------------------------------------------------------*/
1473 pointToEnd (asmop * aop)
1479 aop->coff = count = (aop->size - 1);
1485 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1489 emitcode ("inc", "dptr");
1496 /*-----------------------------------------------------------------*/
1497 /* reAdjustPreg - points a register back to where it should */
1498 /*-----------------------------------------------------------------*/
1500 reAdjustPreg (asmop * aop)
1502 if ((aop->coff==0) || aop->size <= 1)
1510 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1515 emitcode ("lcall", "__decdptr");
1522 #define AOP(op) op->aop
1523 #define AOP_TYPE(op) AOP(op)->type
1524 #define AOP_SIZE(op) AOP(op)->size
1525 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1526 AOP_TYPE(x) == AOP_R0))
1528 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1529 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1531 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1532 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1533 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1536 /*-----------------------------------------------------------------*/
1537 /* opIsGptr: returns non-zero if the passed operand is */
1538 /* a generic pointer type. */
1539 /*-----------------------------------------------------------------*/
1541 opIsGptr (operand * op)
1543 sym_link *type = operandType (op);
1545 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1552 /*-----------------------------------------------------------------*/
1553 /* getDataSize - get the operand data size */
1554 /*-----------------------------------------------------------------*/
1556 getDataSize (operand * op)
1559 size = AOP_SIZE (op);
1560 if (size == GPTRSIZE)
1562 sym_link *type = operandType (op);
1563 if (IS_GENPTR (type))
1565 /* generic pointer; arithmetic operations
1566 * should ignore the high byte (pointer type).
1574 /*-----------------------------------------------------------------*/
1575 /* outAcc - output Acc */
1576 /*-----------------------------------------------------------------*/
1578 outAcc (operand * result)
1581 size = getDataSize (result);
1584 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
1587 /* unsigned or positive */
1590 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
1595 /*-----------------------------------------------------------------*/
1596 /* outBitC - output a bit C */
1597 /*-----------------------------------------------------------------*/
1599 outBitC (operand * result)
1601 /* if the result is bit */
1602 if (AOP_TYPE (result) == AOP_CRY)
1603 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
1606 emitcode ("clr", "a");
1607 emitcode ("rlc", "a");
1612 /*-----------------------------------------------------------------*/
1613 /* toBoolean - emit code for orl a,operator(sizeop) */
1614 /*-----------------------------------------------------------------*/
1616 toBoolean (operand * oper)
1618 int size = AOP_SIZE (oper) - 1;
1620 bool AccUsed = FALSE;
1623 while (!AccUsed && size--)
1625 AccUsed |= aopGetUsesAcc(AOP (oper), offset++);
1628 size = AOP_SIZE (oper) - 1;
1630 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1631 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1634 emitcode("mov", "b,a");
1637 MOVA (aopGet (AOP (oper), offset++, FALSE, FALSE));
1638 emitcode ("orl", "b,a");
1640 MOVA (aopGet (AOP (oper), offset++, FALSE, FALSE));
1641 emitcode ("orl", "a,b");
1648 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1654 /*-----------------------------------------------------------------*/
1655 /* genNot - generate code for ! operation */
1656 /*-----------------------------------------------------------------*/
1662 D(emitcode ("; genNot",""));
1664 /* assign asmOps to operand & result */
1665 aopOp (IC_LEFT (ic), ic, FALSE);
1666 aopOp (IC_RESULT (ic), ic, TRUE);
1668 /* if in bit space then a special case */
1669 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1671 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1672 emitcode ("cpl", "c");
1673 outBitC (IC_RESULT (ic));
1677 toBoolean (IC_LEFT (ic));
1679 tlbl = newiTempLabel (NULL);
1680 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1681 emitcode ("", "%05d$:", tlbl->key + 100);
1682 outBitC (IC_RESULT (ic));
1685 /* release the aops */
1686 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1687 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1691 /*-----------------------------------------------------------------*/
1692 /* genCpl - generate code for complement */
1693 /*-----------------------------------------------------------------*/
1700 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1702 D(emitcode (";", "genCpl"));
1704 /* assign asmOps to operand & result */
1705 aopOp (IC_LEFT (ic), ic, FALSE);
1706 aopOp (IC_RESULT (ic), ic, TRUE);
1708 /* special case if in bit space */
1709 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1713 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1714 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1716 /* promotion rules are responsible for this strange result:
1717 bit -> int -> ~int -> bit
1718 uchar -> int -> ~int -> bit
1720 werror(W_COMPLEMENT);
1721 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1725 tlbl=newiTempLabel(NULL);
1726 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE);
1727 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC ||
1728 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1729 IS_AOP_PREG (IC_LEFT (ic)))
1731 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1736 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1738 emitcode ("", "%05d$:", tlbl->key + 100);
1739 outBitC (IC_RESULT(ic));
1743 size = AOP_SIZE (IC_RESULT (ic));
1746 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1748 emitcode ("cpl", "a");
1749 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1754 /* release the aops */
1755 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1756 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1759 /*-----------------------------------------------------------------*/
1760 /* genUminusFloat - unary minus for floating points */
1761 /*-----------------------------------------------------------------*/
1763 genUminusFloat (operand * op, operand * result)
1765 int size, offset = 0;
1768 D(emitcode ("; genUminusFloat",""));
1770 /* for this we just copy and then flip the bit */
1772 size = AOP_SIZE (op) - 1;
1776 aopPut (AOP (result),
1777 aopGet (AOP (op), offset, FALSE, FALSE),
1779 isOperandVolatile (result, FALSE));
1783 l = aopGet (AOP (op), offset, FALSE, FALSE);
1787 emitcode ("cpl", "acc.7");
1788 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
1791 /*-----------------------------------------------------------------*/
1792 /* genUminus - unary minus code generation */
1793 /*-----------------------------------------------------------------*/
1795 genUminus (iCode * ic)
1798 sym_link *optype, *rtype;
1801 D(emitcode ("; genUminus",""));
1804 aopOp (IC_LEFT (ic), ic, FALSE);
1805 aopOp (IC_RESULT (ic), ic, TRUE);
1807 /* if both in bit space then special
1809 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1810 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1813 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1814 emitcode ("cpl", "c");
1815 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1819 optype = operandType (IC_LEFT (ic));
1820 rtype = operandType (IC_RESULT (ic));
1822 /* if float then do float stuff */
1823 if (IS_FLOAT (optype))
1825 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1829 /* otherwise subtract from zero */
1830 size = AOP_SIZE (IC_LEFT (ic));
1835 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1836 if (!strcmp (l, "a"))
1840 emitcode ("cpl", "a");
1841 emitcode ("addc", "a,#0");
1847 emitcode ("clr", "a");
1848 emitcode ("subb", "a,%s", l);
1850 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1853 /* if any remaining bytes in the result */
1854 /* we just need to propagate the sign */
1855 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1857 emitcode ("rlc", "a");
1858 emitcode ("subb", "a,acc");
1860 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1864 /* release the aops */
1865 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1866 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1869 /*-----------------------------------------------------------------*/
1870 /* saveRegisters - will look for a call and save the registers */
1871 /*-----------------------------------------------------------------*/
1873 saveRegisters (iCode * lic)
1880 for (ic = lic; ic; ic = ic->next)
1881 if (ic->op == CALL || ic->op == PCALL)
1886 fprintf (stderr, "found parameter push with no function call\n");
1890 /* if the registers have been saved already or don't need to be then
1894 if (IS_SYMOP(IC_LEFT(ic)) &&
1895 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1896 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1899 /* save the registers in use at this time but skip the
1900 ones for the result */
1901 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1902 mcs51_rUmaskForOp (IC_RESULT(ic)));
1905 if (options.useXstack)
1907 int count = bitVectnBitsOn (rsave);
1911 i = bitVectFirstBit (rsave);
1912 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1913 emitcode ("mov", "r0,%s", spname);
1914 emitcode ("inc", "%s", spname);// allocate before use
1915 emitcode ("movx", "@r0,a");
1916 if (bitVectBitValue (rsave, R0_IDX))
1917 emitcode ("mov", "r0,a");
1919 else if (count != 0)
1921 if (bitVectBitValue (rsave, R0_IDX))
1923 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1925 emitcode ("mov", "r0,%s", spname);
1927 emitcode ("add", "a,#%d", count);
1928 emitcode ("mov", "%s,a", spname);
1929 for (i = 0; i < mcs51_nRegs; i++)
1931 if (bitVectBitValue (rsave, i))
1935 emitcode ("pop", "acc");
1936 emitcode ("push", "acc");
1940 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1942 emitcode ("movx", "@r0,a");
1945 emitcode ("inc", "r0");
1949 if (bitVectBitValue (rsave, R0_IDX))
1951 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
1956 for (i = 0; i < mcs51_nRegs; i++)
1958 if (bitVectBitValue (rsave, i))
1959 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1963 /*-----------------------------------------------------------------*/
1964 /* unsaveRegisters - pop the pushed registers */
1965 /*-----------------------------------------------------------------*/
1967 unsaveRegisters (iCode * ic)
1972 /* restore the registers in use at this time but skip the
1973 ones for the result */
1974 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1975 mcs51_rUmaskForOp (IC_RESULT(ic)));
1977 if (options.useXstack)
1979 int count = bitVectnBitsOn (rsave);
1983 emitcode ("mov", "r0,%s", spname);
1984 emitcode ("dec", "r0");
1985 emitcode ("movx", "a,@r0");
1986 i = bitVectFirstBit (rsave);
1987 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1988 emitcode ("dec", "%s", spname);
1990 else if (count != 0)
1992 emitcode ("mov", "r0,%s", spname);
1993 for (i = mcs51_nRegs; i >= 0; i--)
1995 if (bitVectBitValue (rsave, i))
1997 emitcode ("dec", "r0");
1998 emitcode ("movx", "a,@r0");
2000 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
2002 emitcode ("push", "acc");
2005 emitcode ("mov", "%s,r0", spname);
2006 if (bitVectBitValue (rsave, R0_IDX))
2008 emitcode ("pop", "ar0");
2013 for (i = mcs51_nRegs; i >= 0; i--)
2015 if (bitVectBitValue (rsave, i))
2016 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2021 /*-----------------------------------------------------------------*/
2023 /*-----------------------------------------------------------------*/
2025 pushSide (operand * oper, int size)
2030 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
2031 if (AOP_TYPE (oper) != AOP_REG &&
2032 AOP_TYPE (oper) != AOP_DIR &&
2036 emitcode ("push", "acc");
2039 emitcode ("push", "%s", l);
2043 /*-----------------------------------------------------------------*/
2044 /* assignResultValue - also indicates if acc is in use afterwards */
2045 /*-----------------------------------------------------------------*/
2047 assignResultValue (operand * oper)
2050 int size = AOP_SIZE (oper);
2051 bool accuse = FALSE;
2055 accuse |= aopPut (AOP (oper), fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2062 /*-----------------------------------------------------------------*/
2063 /* genXpush - pushes onto the external stack */
2064 /*-----------------------------------------------------------------*/
2066 genXpush (iCode * ic)
2068 asmop *aop = newAsmop (0);
2070 int size, offset = 0;
2072 D(emitcode ("; genXpush",""));
2074 aopOp (IC_LEFT (ic), ic, FALSE);
2075 r = getFreePtr (ic, &aop, FALSE);
2077 size = AOP_SIZE (IC_LEFT (ic));
2081 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2082 emitcode ("mov", "%s,%s", r->name, spname);
2083 emitcode ("inc", "%s", spname); // allocate space first
2084 emitcode ("movx", "@%s,a", r->name);
2088 // allocate space first
2089 emitcode ("mov", "%s,%s", r->name, spname);
2091 emitcode ("add", "a,#%d", size);
2092 emitcode ("mov", "%s,a", spname);
2096 MOVA (aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE));
2097 emitcode ("movx", "@%s,a", r->name);
2098 emitcode ("inc", "%s", r->name);
2102 freeAsmop (NULL, aop, ic, TRUE);
2103 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2106 /*-----------------------------------------------------------------*/
2107 /* genIpush - generate code for pushing this gets a little complex */
2108 /*-----------------------------------------------------------------*/
2110 genIpush (iCode * ic)
2112 int size, offset = 0;
2115 D(emitcode ("; genIpush",""));
2117 /* if this is not a parm push : ie. it is spill push
2118 and spill push is always done on the local stack */
2122 /* and the item is spilt then do nothing */
2123 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2126 aopOp (IC_LEFT (ic), ic, FALSE);
2127 size = AOP_SIZE (IC_LEFT (ic));
2128 /* push it on the stack */
2131 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2137 emitcode ("push", "%s", l);
2142 /* this is a paramter push: in this case we call
2143 the routine to find the call and save those
2144 registers that need to be saved */
2147 /* if use external stack then call the external
2148 stack pushing routine */
2149 if (options.useXstack)
2155 /* then do the push */
2156 aopOp (IC_LEFT (ic), ic, FALSE);
2158 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2159 size = AOP_SIZE (IC_LEFT (ic));
2163 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
2164 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2165 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2169 emitcode ("push", "acc");
2172 emitcode ("push", "%s", l);
2175 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2178 /*-----------------------------------------------------------------*/
2179 /* genIpop - recover the registers: can happen only for spilling */
2180 /*-----------------------------------------------------------------*/
2182 genIpop (iCode * ic)
2186 D(emitcode ("; genIpop",""));
2188 /* if the temp was not pushed then */
2189 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2192 aopOp (IC_LEFT (ic), ic, FALSE);
2193 size = AOP_SIZE (IC_LEFT (ic));
2194 offset = (size - 1);
2196 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2199 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2202 /*-----------------------------------------------------------------*/
2203 /* saveRBank - saves an entire register bank on the stack */
2204 /*-----------------------------------------------------------------*/
2206 saveRBank (int bank, iCode * ic, bool pushPsw)
2209 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2213 if (options.useXstack)
2217 /* Assume r0 is available for use. */
2218 r = mcs51_regWithIdx (R0_IDX);;
2223 r = getFreePtr (ic, &aop, FALSE);
2225 // allocate space first
2226 emitcode ("mov", "%s,%s", r->name, spname);
2228 emitcode ("add", "a,#%d", count);
2229 emitcode ("mov", "%s,a", spname);
2232 for (i = 0; i < mcs51_nRegs; i++)
2234 if (options.useXstack)
2236 emitcode ("mov", "a,(%s+%d)",
2237 regs8051[i].base, 8 * bank + regs8051[i].offset);
2238 emitcode ("movx", "@%s,a", r->name);
2240 emitcode ("inc", "%s", r->name);
2243 emitcode ("push", "(%s+%d)",
2244 regs8051[i].base, 8 * bank + regs8051[i].offset);
2249 if (options.useXstack)
2251 emitcode ("mov", "a,psw");
2252 emitcode ("movx", "@%s,a", r->name);
2257 emitcode ("push", "psw");
2260 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2265 freeAsmop (NULL, aop, ic, TRUE);
2274 /*-----------------------------------------------------------------*/
2275 /* unsaveRBank - restores the register bank from stack */
2276 /*-----------------------------------------------------------------*/
2278 unsaveRBank (int bank, iCode * ic, bool popPsw)
2284 if (options.useXstack)
2288 /* Assume r0 is available for use. */
2289 r = mcs51_regWithIdx (R0_IDX);;
2294 r = getFreePtr (ic, &aop, FALSE);
2296 emitcode ("mov", "%s,%s", r->name, spname);
2301 if (options.useXstack)
2303 emitcode ("dec", "%s", r->name);
2304 emitcode ("movx", "a,@%s", r->name);
2305 emitcode ("mov", "psw,a");
2309 emitcode ("pop", "psw");
2313 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2315 if (options.useXstack)
2317 emitcode ("dec", "%s", r->name);
2318 emitcode ("movx", "a,@%s", r->name);
2319 emitcode ("mov", "(%s+%d),a",
2320 regs8051[i].base, 8 * bank + regs8051[i].offset);
2324 emitcode ("pop", "(%s+%d)",
2325 regs8051[i].base, 8 * bank + regs8051[i].offset);
2329 if (options.useXstack)
2331 emitcode ("mov", "%s,%s", spname, r->name);
2336 freeAsmop (NULL, aop, ic, TRUE);
2340 /*-----------------------------------------------------------------*/
2341 /* genSend - gen code for SEND */
2342 /*-----------------------------------------------------------------*/
2343 static void genSend(set *sendSet)
2348 for (sic = setFirstItem (sendSet); sic;
2349 sic = setNextItem (sendSet)) {
2350 int size, offset = 0;
2351 aopOp (IC_LEFT (sic), sic, FALSE);
2352 size = AOP_SIZE (IC_LEFT (sic));
2354 if (sic->argreg == 1) {
2356 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2358 if (strcmp (l, fReturn[offset]))
2359 emitcode ("mov", "%s,%s", fReturn[offset], l);
2365 emitcode ("mov","b1_%d,%s",rb1_count++,
2366 aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
2369 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2373 /*-----------------------------------------------------------------*/
2374 /* genCall - generates a call statement */
2375 /*-----------------------------------------------------------------*/
2377 genCall (iCode * ic)
2380 // bool restoreBank = FALSE;
2381 bool swapBanks = FALSE;
2382 bool accuse = FALSE;
2383 bool accPushed = FALSE;
2385 D(emitcode("; genCall",""));
2387 dtype = operandType (IC_LEFT (ic));
2388 /* if send set is not empty then assign */
2391 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2392 genSend(reverseSet(_G.sendSet));
2394 genSend(_G.sendSet);
2400 /* if we are calling a not _naked function that is not using
2401 the same register bank then we need to save the
2402 destination registers on the stack */
2403 dtype = operandType (IC_LEFT (ic));
2404 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2405 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2406 !IFFUNC_ISISR (dtype))
2411 /* if caller saves & we have not saved then */
2417 emitcode ("mov", "psw,#0x%02x",
2418 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2422 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2423 OP_SYMBOL (IC_LEFT (ic))->rname :
2424 OP_SYMBOL (IC_LEFT (ic))->name));
2428 emitcode ("mov", "psw,#0x%02x",
2429 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2432 /* if we need assign a result value */
2433 if ((IS_ITEMP (IC_RESULT (ic)) &&
2434 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2435 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2436 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2437 IS_TRUE_SYMOP (IC_RESULT (ic)))
2441 aopOp (IC_RESULT (ic), ic, FALSE);
2444 accuse = assignResultValue (IC_RESULT (ic));
2446 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2449 /* adjust the stack for parameters if
2454 if (ic->parmBytes > 3)
2458 emitcode ("push", "acc");
2461 emitcode ("mov", "a,%s", spname);
2462 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2463 emitcode ("mov", "%s,a", spname);
2466 for (i = 0; i < ic->parmBytes; i++)
2467 emitcode ("dec", "%s", spname);
2470 /* if we hade saved some registers then unsave them */
2471 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2473 if (accuse && !accPushed && options.useXstack)
2475 emitcode ("push", "acc");
2478 unsaveRegisters (ic);
2481 // /* if register bank was saved then pop them */
2483 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2486 emitcode ("pop", "acc");
2489 /*-----------------------------------------------------------------*/
2490 /* -10l - generates a call by pointer statement */
2491 /*-----------------------------------------------------------------*/
2493 genPcall (iCode * ic)
2496 symbol *rlbl = newiTempLabel (NULL);
2497 // bool restoreBank=FALSE;
2498 bool swapBanks = FALSE;
2500 D(emitcode("; genPCall",""));
2502 /* if caller saves & we have not saved then */
2506 /* if we are calling a not _naked function that is not using
2507 the same register bank then we need to save the
2508 destination registers on the stack */
2509 dtype = operandType (IC_LEFT (ic))->next;
2510 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2511 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2512 !IFFUNC_ISISR (dtype))
2514 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2515 // restoreBank=TRUE;
2517 // need caution message to user here
2520 /* push the return address on to the stack */
2521 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2522 emitcode ("push", "acc");
2523 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2524 emitcode ("push", "acc");
2526 /* now push the calling address */
2527 aopOp (IC_LEFT (ic), ic, FALSE);
2529 pushSide (IC_LEFT (ic), FPTRSIZE);
2531 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2533 /* if send set is not empty the assign */
2536 genSend(reverseSet(_G.sendSet));
2542 emitcode ("mov", "psw,#0x%02x",
2543 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2547 emitcode ("ret", "");
2548 emitcode ("", "%05d$:", (rlbl->key + 100));
2553 emitcode ("mov", "psw,#0x%02x",
2554 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2557 /* if we need assign a result value */
2558 if ((IS_ITEMP (IC_RESULT (ic)) &&
2559 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2560 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2561 IS_TRUE_SYMOP (IC_RESULT (ic)))
2565 aopOp (IC_RESULT (ic), ic, FALSE);
2568 assignResultValue (IC_RESULT (ic));
2570 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2573 /* adjust the stack for parameters if
2578 if (ic->parmBytes > 3)
2580 emitcode ("mov", "a,%s", spname);
2581 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2582 emitcode ("mov", "%s,a", spname);
2585 for (i = 0; i < ic->parmBytes; i++)
2586 emitcode ("dec", "%s", spname);
2590 // /* if register bank was saved then unsave them */
2592 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2594 /* if we hade saved some registers then
2596 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2597 unsaveRegisters (ic);
2600 /*-----------------------------------------------------------------*/
2601 /* resultRemat - result is rematerializable */
2602 /*-----------------------------------------------------------------*/
2604 resultRemat (iCode * ic)
2606 if (SKIP_IC (ic) || ic->op == IFX)
2609 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2611 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2612 if (sym->remat && !POINTER_SET (ic))
2619 #if defined(__BORLANDC__) || defined(_MSC_VER)
2620 #define STRCASECMP stricmp
2622 #define STRCASECMP strcasecmp
2625 /*-----------------------------------------------------------------*/
2626 /* inExcludeList - return 1 if the string is in exclude Reg list */
2627 /*-----------------------------------------------------------------*/
2629 regsCmp(void *p1, void *p2)
2631 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2635 inExcludeList (char *s)
2637 const char *p = setFirstItem(options.excludeRegsSet);
2639 if (p == NULL || STRCASECMP(p, "none") == 0)
2643 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2646 /*-----------------------------------------------------------------*/
2647 /* genFunction - generated code for function entry */
2648 /*-----------------------------------------------------------------*/
2650 genFunction (iCode * ic)
2652 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2654 bool switchedPSW = FALSE;
2655 int calleesaves_saved_register = -1;
2656 int stackAdjust = sym->stack;
2657 int accIsFree = sym->recvSize < 4;
2658 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2659 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
2662 /* create the function header */
2663 emitcode (";", "-----------------------------------------");
2664 emitcode (";", " function %s", sym->name);
2665 emitcode (";", "-----------------------------------------");
2667 emitcode ("", "%s:", sym->rname);
2668 ftype = operandType (IC_LEFT (ic));
2669 _G.currentFunc = sym;
2671 if (IFFUNC_ISNAKED(ftype))
2673 emitcode(";", "naked function: no prologue.");
2677 /* here we need to generate the equates for the
2678 register bank if required */
2679 if (FUNC_REGBANK (ftype) != rbank)
2683 rbank = FUNC_REGBANK (ftype);
2684 for (i = 0; i < mcs51_nRegs; i++)
2686 if (strcmp (regs8051[i].base, "0") == 0)
2687 emitcode ("", "%s = 0x%02x",
2689 8 * rbank + regs8051[i].offset);
2691 emitcode ("", "%s = %s + 0x%02x",
2694 8 * rbank + regs8051[i].offset);
2698 /* if this is an interrupt service routine then
2699 save acc, b, dpl, dph */
2700 if (IFFUNC_ISISR (sym->type))
2703 if (!inExcludeList ("acc"))
2704 emitcode ("push", "acc");
2705 if (!inExcludeList ("b"))
2706 emitcode ("push", "b");
2707 if (!inExcludeList ("dpl"))
2708 emitcode ("push", "dpl");
2709 if (!inExcludeList ("dph"))
2710 emitcode ("push", "dph");
2711 /* if this isr has no bank i.e. is going to
2712 run with bank 0 , then we need to save more
2714 if (!FUNC_REGBANK (sym->type))
2717 /* if this function does not call any other
2718 function then we can be economical and
2719 save only those registers that are used */
2720 if (!IFFUNC_HASFCALL(sym->type))
2724 /* if any registers used */
2727 /* save the registers used */
2728 for (i = 0; i < sym->regsUsed->size; i++)
2730 if (bitVectBitValue (sym->regsUsed, i))
2731 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2738 /* this function has a function call. We cannot
2739 determines register usage so we will have to push the
2741 saveRBank (0, ic, FALSE);
2742 if (options.parms_in_bank1) {
2744 for (i=0; i < 8 ; i++ ) {
2745 emitcode ("push","%s",rb1regs[i]);
2752 /* This ISR uses a non-zero bank.
2754 * We assume that the bank is available for our
2757 * However, if this ISR calls a function which uses some
2758 * other bank, we must save that bank entirely.
2760 unsigned long banksToSave = 0;
2762 if (IFFUNC_HASFCALL(sym->type))
2765 #define MAX_REGISTER_BANKS 4
2770 for (i = ic; i; i = i->next)
2772 if (i->op == ENDFUNCTION)
2774 /* we got to the end OK. */
2782 dtype = operandType (IC_LEFT(i));
2784 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2786 /* Mark this bank for saving. */
2787 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2789 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2793 banksToSave |= (1 << FUNC_REGBANK(dtype));
2796 /* And note that we don't need to do it in
2804 /* This is a mess; we have no idea what
2805 * register bank the called function might
2808 * The only thing I can think of to do is
2809 * throw a warning and hope.
2811 werror(W_FUNCPTR_IN_USING_ISR);
2815 if (banksToSave && options.useXstack)
2817 /* Since we aren't passing it an ic,
2818 * saveRBank will assume r0 is available to abuse.
2820 * So switch to our (trashable) bank now, so
2821 * the caller's R0 isn't trashed.
2823 emitcode ("push", "psw");
2824 emitcode ("mov", "psw,#0x%02x",
2825 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2829 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2831 if (banksToSave & (1 << ix))
2833 saveRBank(ix, NULL, FALSE);
2837 // TODO: this needs a closer look
2838 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2841 /* Set the register bank to the desired value if nothing else */
2842 /* has done so yet. */
2845 emitcode ("push", "psw");
2846 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2851 /* This is a non-ISR function. The caller has already switched register */
2852 /* banks, if necessary, so just handle the callee-saves option. */
2854 /* if callee-save to be used for this function
2855 then save the registers being used in this function */
2856 if (IFFUNC_CALLEESAVES(sym->type))
2860 /* if any registers used */
2863 /* save the registers used */
2864 for (i = 0; i < sym->regsUsed->size; i++)
2866 if (bitVectBitValue (sym->regsUsed, i))
2868 /* remember one saved register for later usage */
2869 if (calleesaves_saved_register < 0)
2870 calleesaves_saved_register = i;
2871 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2882 if (options.useXstack)
2884 emitcode ("mov", "r0,%s", spname);
2885 emitcode ("inc", "%s", spname);
2886 emitcode ("xch", "a,_bpx");
2887 emitcode ("movx", "@r0,a");
2888 emitcode ("inc", "r0");
2889 emitcode ("mov", "a,r0");
2890 emitcode ("xch", "a,_bpx");
2891 emitcode ("push", "_bp"); /* save the callers stack */
2892 emitcode ("mov", "_bp,sp");
2896 /* set up the stack */
2897 emitcode ("push", "_bp"); /* save the callers stack */
2898 emitcode ("mov", "_bp,sp");
2902 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2903 /* before setting up the stack frame completely. */
2904 if (ric && ric->argreg == 1 && IC_RESULT (ric))
2906 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2910 if (rsym && rsym->regType == REG_CND)
2912 if (rsym && (rsym->accuse || rsym->ruonly))
2914 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2915 rsym = rsym->usl.spillLoc;
2918 /* If the RECEIVE operand immediately spills to the first entry on the */
2919 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
2920 /* rather than the usual @r0/r1 machinations. */
2921 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
2925 _G.current_iCode = ric;
2926 D(emitcode ("; genReceive",""));
2927 for (ofs=0; ofs < sym->recvSize; ofs++)
2929 if (!strcmp (fReturn[ofs], "a"))
2930 emitcode ("push", "acc");
2932 emitcode ("push", fReturn[ofs]);
2934 stackAdjust -= sym->recvSize;
2937 assert (stackAdjust>=0);
2940 _G.current_iCode = ic;
2944 /* If the RECEIVE operand is 4 registers, we can do the moves now */
2945 /* to free up the accumulator. */
2946 else if (rsym && rsym->nRegs && sym->recvSize == 4)
2950 _G.current_iCode = ric;
2951 D(emitcode ("; genReceive",""));
2952 for (ofs=0; ofs < sym->recvSize; ofs++)
2954 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
2956 _G.current_iCode = ic;
2962 /* adjust the stack for the function */
2965 int i = stackAdjust;
2967 werror (W_STACK_OVERFLOW, sym->name);
2969 if (i > 3 && accIsFree)
2971 emitcode ("mov", "a,sp");
2972 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2973 emitcode ("mov", "sp,a");
2977 /* The accumulator is not free, so we will need another register */
2978 /* to clobber. No need to worry about a possible conflict with */
2979 /* the above early RECEIVE optimizations since they would have */
2980 /* freed the accumulator if they were generated. */
2982 if (IFFUNC_CALLEESAVES(sym->type))
2984 /* if it's a callee-saves function we need a saved register */
2985 if (calleesaves_saved_register >= 0)
2987 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2988 emitcode ("mov", "a,sp");
2989 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2990 emitcode ("mov", "sp,a");
2991 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
2994 /* do it the hard way */
2996 emitcode ("inc", "sp");
3000 /* not callee-saves, we can clobber r0 */
3001 emitcode ("mov", "r0,a");
3002 emitcode ("mov", "a,sp");
3003 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3004 emitcode ("mov", "sp,a");
3005 emitcode ("mov", "a,r0");
3010 emitcode ("inc", "sp");
3015 char i = ((char) sym->xstack & 0xff);
3017 if (i > 3 && accIsFree)
3019 emitcode ("mov", "a,_spx");
3020 emitcode ("add", "a,#0x%02x", i);
3021 emitcode ("mov", "_spx,a");
3025 emitcode ("push", "acc");
3026 emitcode ("mov", "a,_spx");
3027 emitcode ("add", "a,#0x%02x", i);
3028 emitcode ("mov", "_spx,a");
3029 emitcode ("pop", "acc");
3034 emitcode ("inc", "_spx");
3038 /* if critical function then turn interrupts off */
3039 if (IFFUNC_ISCRITICAL (ftype))
3041 symbol *tlbl = newiTempLabel (NULL);
3042 emitcode ("setb", "c");
3043 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3044 emitcode ("clr", "c");
3045 emitcode ("", "%05d$:", (tlbl->key + 100));
3046 emitcode ("push", "psw"); /* save old ea via c in psw */
3050 /*-----------------------------------------------------------------*/
3051 /* genEndFunction - generates epilogue for functions */
3052 /*-----------------------------------------------------------------*/
3054 genEndFunction (iCode * ic)
3056 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3057 lineNode *lnp = lineCurr;
3059 bitVect *regsUsedPrologue;
3060 bitVect *regsUnneeded;
3063 _G.currentFunc = NULL;
3064 if (IFFUNC_ISNAKED(sym->type))
3066 emitcode(";", "naked function: no epilogue.");
3067 if (options.debug && currFunc)
3068 debugFile->writeEndFunction (currFunc, ic, 0);
3072 if (IFFUNC_ISCRITICAL (sym->type))
3074 emitcode ("pop", "psw"); /* restore ea via c in psw */
3075 emitcode ("mov", "ea,c");
3078 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))// && !options.useXstack)
3080 emitcode ("mov", "sp,_bp");
3082 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3084 if (options.useXstack)
3086 emitcode ("pop", "_bp");
3087 emitcode ("xch", "a,_bpx");
3088 emitcode ("mov", "r0,a");
3089 emitcode ("dec", "r0");
3090 emitcode ("movx", "a,@r0");
3091 emitcode ("xch", "a,_bpx");
3092 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3096 emitcode ("pop", "_bp");
3100 /* restore the register bank */
3101 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3103 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3104 || !options.useXstack)
3106 /* Special case of ISR using non-zero bank with useXstack
3109 emitcode ("pop", "psw");
3113 if (IFFUNC_ISISR (sym->type))
3116 /* now we need to restore the registers */
3117 /* if this isr has no bank i.e. is going to
3118 run with bank 0 , then we need to save more
3120 if (!FUNC_REGBANK (sym->type))
3122 /* if this function does not call any other
3123 function then we can be economical and
3124 save only those registers that are used */
3125 if (!IFFUNC_HASFCALL(sym->type))
3129 /* if any registers used */
3132 /* save the registers used */
3133 for (i = sym->regsUsed->size; i >= 0; i--)
3135 if (bitVectBitValue (sym->regsUsed, i))
3136 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3142 if (options.parms_in_bank1) {
3144 for (i = 7 ; i >= 0 ; i-- ) {
3145 emitcode ("pop","%s",rb1regs[i]);
3148 /* this function has a function call cannot
3149 determines register usage so we will have to pop the
3151 unsaveRBank (0, ic, FALSE);
3156 /* This ISR uses a non-zero bank.
3158 * Restore any register banks saved by genFunction
3161 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3164 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3166 if (savedBanks & (1 << ix))
3168 unsaveRBank(ix, NULL, FALSE);
3172 if (options.useXstack)
3174 /* Restore bank AFTER calling unsaveRBank,
3175 * since it can trash r0.
3177 emitcode ("pop", "psw");
3181 if (!inExcludeList ("dph"))
3182 emitcode ("pop", "dph");
3183 if (!inExcludeList ("dpl"))
3184 emitcode ("pop", "dpl");
3185 if (!inExcludeList ("b"))
3186 emitcode ("pop", "b");
3187 if (!inExcludeList ("acc"))
3188 emitcode ("pop", "acc");
3190 /* if debug then send end of function */
3191 if (options.debug && currFunc)
3193 debugFile->writeEndFunction (currFunc, ic, 1);
3196 emitcode ("reti", "");
3200 if (IFFUNC_CALLEESAVES(sym->type))
3204 /* if any registers used */
3207 /* save the registers used */
3208 for (i = sym->regsUsed->size; i >= 0; i--)
3210 if (bitVectBitValue (sym->regsUsed, i) ||
3211 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3212 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3215 else if (mcs51_ptrRegReq)
3217 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3218 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3223 /* if debug then send end of function */
3224 if (options.debug && currFunc)
3226 debugFile->writeEndFunction (currFunc, ic, 1);
3229 emitcode ("ret", "");
3232 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3235 /* If this was an interrupt handler using bank 0 that called another */
3236 /* function, then all registers must be saved; nothing to optimized. */
3237 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3238 && !FUNC_REGBANK(sym->type))
3241 /* There are no push/pops to optimize if not callee-saves or ISR */
3242 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3245 /* If there were stack parameters, we cannot optimize without also */
3246 /* fixing all of the stack offsets; this is too dificult to consider. */
3247 if (FUNC_HASSTACKPARM(sym->type))
3250 /* Compute the registers actually used */
3251 regsUsed = newBitVect (mcs51_nRegs);
3252 regsUsedPrologue = newBitVect (mcs51_nRegs);
3255 if (lnp->ic && lnp->ic->op == FUNCTION)
3256 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3258 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3260 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3261 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3268 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3269 && !bitVectBitValue (regsUsed, CND_IDX))
3271 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3272 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3273 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3274 bitVectUnSetBit (regsUsed, CND_IDX);
3277 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3279 /* If this was an interrupt handler that called another function */
3280 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3281 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3283 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3284 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3285 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3286 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3287 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3290 /* Remove the unneeded push/pops */
3291 regsUnneeded = newBitVect (mcs51_nRegs);
3294 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3296 if (!strncmp(lnp->line, "push", 4))
3298 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3299 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3301 connectLine (lnp->prev, lnp->next);
3302 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3305 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3307 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3308 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3310 connectLine (lnp->prev, lnp->next);
3311 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3318 for (idx = 0; idx < regsUnneeded->size; idx++)
3319 if (bitVectBitValue (regsUnneeded, idx))
3320 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3322 freeBitVect (regsUnneeded);
3323 freeBitVect (regsUsed);
3324 freeBitVect (regsUsedPrologue);
3327 /*-----------------------------------------------------------------*/
3328 /* genRet - generate code for return statement */
3329 /*-----------------------------------------------------------------*/
3333 int size, offset = 0, pushed = 0;
3335 D(emitcode ("; genRet",""));
3337 /* if we have no return value then
3338 just generate the "ret" */
3342 /* we have something to return then
3343 move the return value into place */
3344 aopOp (IC_LEFT (ic), ic, FALSE);
3345 size = AOP_SIZE (IC_LEFT (ic));
3350 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3353 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3355 emitcode ("push", "%s", l);
3360 l = aopGet (AOP (IC_LEFT (ic)), offset,
3362 if (strcmp (fReturn[offset], l))
3363 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3372 if (strcmp (fReturn[pushed], "a"))
3373 emitcode ("pop", fReturn[pushed]);
3375 emitcode ("pop", "acc");
3378 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3381 /* generate a jump to the return label
3382 if the next is not the return statement */
3383 if (!(ic->next && ic->next->op == LABEL &&
3384 IC_LABEL (ic->next) == returnLabel))
3386 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3390 /*-----------------------------------------------------------------*/
3391 /* genLabel - generates a label */
3392 /*-----------------------------------------------------------------*/
3394 genLabel (iCode * ic)
3396 /* special case never generate */
3397 if (IC_LABEL (ic) == entryLabel)
3400 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3403 /*-----------------------------------------------------------------*/
3404 /* genGoto - generates a ljmp */
3405 /*-----------------------------------------------------------------*/
3407 genGoto (iCode * ic)
3409 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3412 /*-----------------------------------------------------------------*/
3413 /* findLabelBackwards: walks back through the iCode chain looking */
3414 /* for the given label. Returns number of iCode instructions */
3415 /* between that label and given ic. */
3416 /* Returns zero if label not found. */
3417 /*-----------------------------------------------------------------*/
3419 findLabelBackwards (iCode * ic, int key)
3428 /* If we have any pushes or pops, we cannot predict the distance.
3429 I don't like this at all, this should be dealt with in the
3431 if (ic->op == IPUSH || ic->op == IPOP) {
3435 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3444 /*-----------------------------------------------------------------*/
3445 /* genPlusIncr :- does addition with increment if possible */
3446 /*-----------------------------------------------------------------*/
3448 genPlusIncr (iCode * ic)
3450 unsigned int icount;
3451 unsigned int size = getDataSize (IC_RESULT (ic));
3453 /* will try to generate an increment */
3454 /* if the right side is not a literal
3456 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3459 /* if the literal value of the right hand side
3460 is greater than 4 then it is not worth it */
3461 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3464 D(emitcode ("; genPlusIncr",""));
3466 /* if increment >=16 bits in register or direct space */
3467 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3468 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3476 /* If the next instruction is a goto and the goto target
3477 * is < 10 instructions previous to this, we can generate
3478 * jumps straight to that target.
3480 if (ic->next && ic->next->op == GOTO
3481 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3482 && labelRange <= 10)
3484 emitcode (";", "tail increment optimized");
3485 tlbl = IC_LABEL (ic->next);
3490 tlbl = newiTempLabel (NULL);
3493 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3494 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3495 IS_AOP_PREG (IC_RESULT (ic)))
3496 emitcode ("cjne", "%s,#0x00,%05d$",
3497 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3501 emitcode ("clr", "a");
3502 emitcode ("cjne", "a,%s,%05d$",
3503 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3507 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3510 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3511 IS_AOP_PREG (IC_RESULT (ic)))
3512 emitcode ("cjne", "%s,#0x00,%05d$",
3513 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3516 emitcode ("cjne", "a,%s,%05d$",
3517 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3520 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3524 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3525 IS_AOP_PREG (IC_RESULT (ic)))
3526 emitcode ("cjne", "%s,#0x00,%05d$",
3527 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3531 emitcode ("cjne", "a,%s,%05d$",
3532 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3535 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3540 emitcode ("", "%05d$:", tlbl->key + 100);
3545 /* if the sizes are greater than 1 then we cannot */
3546 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3547 AOP_SIZE (IC_LEFT (ic)) > 1)
3550 /* we can if the aops of the left & result match or
3551 if they are in registers and the registers are the
3553 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3558 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3559 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3560 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3566 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3575 /*-----------------------------------------------------------------*/
3576 /* outBitAcc - output a bit in acc */
3577 /*-----------------------------------------------------------------*/
3579 outBitAcc (operand * result)
3581 symbol *tlbl = newiTempLabel (NULL);
3582 /* if the result is a bit */
3583 if (AOP_TYPE (result) == AOP_CRY)
3585 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3589 emitcode ("jz", "%05d$", tlbl->key + 100);
3590 emitcode ("mov", "a,%s", one);
3591 emitcode ("", "%05d$:", tlbl->key + 100);
3596 /*-----------------------------------------------------------------*/
3597 /* genPlusBits - generates code for addition of two bits */
3598 /*-----------------------------------------------------------------*/
3600 genPlusBits (iCode * ic)
3602 D(emitcode ("; genPlusBits",""));
3604 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3606 symbol *lbl = newiTempLabel (NULL);
3607 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3608 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3609 emitcode ("cpl", "c");
3610 emitcode ("", "%05d$:", (lbl->key + 100));
3611 outBitC (IC_RESULT (ic));
3615 emitcode ("clr", "a");
3616 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3617 emitcode ("rlc", "a");
3618 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3619 emitcode ("addc", "a,#0x00");
3620 outAcc (IC_RESULT (ic));
3625 /* This is the original version of this code.
3627 * This is being kept around for reference,
3628 * because I am not entirely sure I got it right...
3631 adjustArithmeticResult (iCode * ic)
3633 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3634 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3635 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3636 aopPut (AOP (IC_RESULT (ic)),
3637 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3639 isOperandVolatile (IC_RESULT (ic), FALSE));
3641 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3642 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3643 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3644 aopPut (AOP (IC_RESULT (ic)),
3645 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3647 isOperandVolatile (IC_RESULT (ic), FALSE));
3649 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3650 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3651 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3652 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3653 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3656 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3657 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3661 /* This is the pure and virtuous version of this code.
3662 * I'm pretty certain it's right, but not enough to toss the old
3666 adjustArithmeticResult (iCode * ic)
3668 if (opIsGptr (IC_RESULT (ic)) &&
3669 opIsGptr (IC_LEFT (ic)) &&
3670 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3672 aopPut (AOP (IC_RESULT (ic)),
3673 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3675 isOperandVolatile (IC_RESULT (ic), FALSE));
3678 if (opIsGptr (IC_RESULT (ic)) &&
3679 opIsGptr (IC_RIGHT (ic)) &&
3680 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3682 aopPut (AOP (IC_RESULT (ic)),
3683 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3685 isOperandVolatile (IC_RESULT (ic), FALSE));
3688 if (opIsGptr (IC_RESULT (ic)) &&
3689 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3690 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3691 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3692 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3695 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3696 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3701 /*-----------------------------------------------------------------*/
3702 /* genPlus - generates code for addition */
3703 /*-----------------------------------------------------------------*/
3705 genPlus (iCode * ic)
3707 int size, offset = 0;
3710 asmop *leftOp, *rightOp;
3713 /* special cases :- */
3715 D(emitcode ("; genPlus",""));
3717 aopOp (IC_LEFT (ic), ic, FALSE);
3718 aopOp (IC_RIGHT (ic), ic, FALSE);
3719 aopOp (IC_RESULT (ic), ic, TRUE);
3721 /* if literal, literal on the right or
3722 if left requires ACC or right is already
3724 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3725 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3726 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3728 operand *t = IC_RIGHT (ic);
3729 IC_RIGHT (ic) = IC_LEFT (ic);
3733 /* if both left & right are in bit
3735 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3736 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3742 /* if left in bit space & right literal */
3743 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3744 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3746 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3747 /* if result in bit space */
3748 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3750 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3751 emitcode ("cpl", "c");
3752 outBitC (IC_RESULT (ic));
3756 size = getDataSize (IC_RESULT (ic));
3759 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3760 emitcode ("addc", "a,#00");
3761 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3767 /* if I can do an increment instead
3768 of add then GOOD for ME */
3769 if (genPlusIncr (ic) == TRUE)
3772 size = getDataSize (IC_RESULT (ic));
3773 leftOp = AOP(IC_LEFT(ic));
3774 rightOp = AOP(IC_RIGHT(ic));
3777 /* if this is an add for an array access
3778 at a 256 byte boundary */
3780 && AOP_TYPE (op) == AOP_IMMD
3782 && IS_SPEC (OP_SYM_ETYPE (op))
3783 && SPEC_ABSA (OP_SYM_ETYPE (op))
3784 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3787 D(emitcode ("; genPlus aligned array",""));
3788 aopPut (AOP (IC_RESULT (ic)),
3789 aopGet (rightOp, 0, FALSE, FALSE),
3791 isOperandVolatile (IC_RESULT (ic), FALSE));
3793 if( 1 == getDataSize (IC_RIGHT (ic)) )
3795 aopPut (AOP (IC_RESULT (ic)),
3796 aopGet (leftOp, 1, FALSE, FALSE),
3798 isOperandVolatile (IC_RESULT (ic), FALSE));
3802 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3803 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3804 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3809 /* if the lower bytes of a literal are zero skip the addition */
3810 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3812 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3813 (skip_bytes+1 < size))
3818 D(emitcode ("; genPlus shortcut",""));
3823 if( offset >= skip_bytes )
3825 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3828 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3830 emitcode("xch", "a,b");
3831 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3832 emitcode (add, "a,b");
3835 else if (aopGetUsesAcc (leftOp, offset))
3837 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3838 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3842 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3843 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3845 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3846 add = "addc"; /* further adds must propagate carry */
3850 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3851 isOperandVolatile (IC_RESULT (ic), FALSE))
3854 aopPut (AOP (IC_RESULT (ic)),
3855 aopGet (leftOp, offset, FALSE, FALSE),
3857 isOperandVolatile (IC_RESULT (ic), FALSE));
3863 adjustArithmeticResult (ic);
3866 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3867 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3868 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3871 /*-----------------------------------------------------------------*/
3872 /* genMinusDec :- does subtraction with deccrement if possible */
3873 /*-----------------------------------------------------------------*/
3875 genMinusDec (iCode * ic)
3877 unsigned int icount;
3878 unsigned int size = getDataSize (IC_RESULT (ic));
3880 /* will try to generate an increment */
3881 /* if the right side is not a literal
3883 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3886 /* if the literal value of the right hand side
3887 is greater than 4 then it is not worth it */
3888 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3891 D(emitcode ("; genMinusDec",""));
3893 /* if decrement >=16 bits in register or direct space */
3894 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3895 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3903 /* If the next instruction is a goto and the goto target
3904 * is <= 10 instructions previous to this, we can generate
3905 * jumps straight to that target.
3907 if (ic->next && ic->next->op == GOTO
3908 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3909 && labelRange <= 10)
3911 emitcode (";", "tail decrement optimized");
3912 tlbl = IC_LABEL (ic->next);
3917 tlbl = newiTempLabel (NULL);
3921 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3922 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3923 IS_AOP_PREG (IC_RESULT (ic)))
3924 emitcode ("cjne", "%s,#0xff,%05d$"
3925 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3929 emitcode ("mov", "a,#0xff");
3930 emitcode ("cjne", "a,%s,%05d$"
3931 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3934 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3937 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3938 IS_AOP_PREG (IC_RESULT (ic)))
3939 emitcode ("cjne", "%s,#0xff,%05d$"
3940 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3944 emitcode ("cjne", "a,%s,%05d$"
3945 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3948 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3952 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3953 IS_AOP_PREG (IC_RESULT (ic)))
3954 emitcode ("cjne", "%s,#0xff,%05d$"
3955 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3959 emitcode ("cjne", "a,%s,%05d$"
3960 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3963 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3967 emitcode ("", "%05d$:", tlbl->key + 100);
3972 /* if the sizes are greater than 1 then we cannot */
3973 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3974 AOP_SIZE (IC_LEFT (ic)) > 1)
3977 /* we can if the aops of the left & result match or
3978 if they are in registers and the registers are the
3980 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3984 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3992 /*-----------------------------------------------------------------*/
3993 /* addSign - complete with sign */
3994 /*-----------------------------------------------------------------*/
3996 addSign (operand * result, int offset, int sign)
3998 int size = (getDataSize (result) - offset);
4003 emitcode ("rlc", "a");
4004 emitcode ("subb", "a,acc");
4006 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4010 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4014 /*-----------------------------------------------------------------*/
4015 /* genMinusBits - generates code for subtraction of two bits */
4016 /*-----------------------------------------------------------------*/
4018 genMinusBits (iCode * ic)
4020 symbol *lbl = newiTempLabel (NULL);
4022 D(emitcode ("; genMinusBits",""));
4024 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4026 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4027 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4028 emitcode ("cpl", "c");
4029 emitcode ("", "%05d$:", (lbl->key + 100));
4030 outBitC (IC_RESULT (ic));
4034 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4035 emitcode ("subb", "a,acc");
4036 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4037 emitcode ("inc", "a");
4038 emitcode ("", "%05d$:", (lbl->key + 100));
4039 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4040 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4044 /*-----------------------------------------------------------------*/
4045 /* genMinus - generates code for subtraction */
4046 /*-----------------------------------------------------------------*/
4048 genMinus (iCode * ic)
4050 int size, offset = 0;
4052 D(emitcode ("; genMinus",""));
4054 aopOp (IC_LEFT (ic), ic, FALSE);
4055 aopOp (IC_RIGHT (ic), ic, FALSE);
4056 aopOp (IC_RESULT (ic), ic, TRUE);
4058 /* special cases :- */
4059 /* if both left & right are in bit space */
4060 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4061 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4067 /* if I can do an decrement instead
4068 of subtract then GOOD for ME */
4069 if (genMinusDec (ic) == TRUE)
4072 size = getDataSize (IC_RESULT (ic));
4074 /* if literal, add a,#-lit, else normal subb */
4075 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4077 unsigned long lit = 0L;
4079 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4084 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
4085 /* first add without previous c */
4087 if (!size && lit== (unsigned long) -1) {
4088 emitcode ("dec", "a");
4090 emitcode ("add", "a,#0x%02x",
4091 (unsigned int) (lit & 0x0FFL));
4094 emitcode ("addc", "a,#0x%02x",
4095 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4097 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4102 asmop *leftOp, *rightOp;
4104 leftOp = AOP(IC_LEFT(ic));
4105 rightOp = AOP(IC_RIGHT(ic));
4109 if (aopGetUsesAcc(rightOp, offset)) {
4110 if (aopGetUsesAcc(leftOp, offset)) {
4113 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4115 emitcode ("mov", "b,a");
4118 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4119 emitcode ("subb", "a,b");
4122 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4123 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4125 emitcode( "setb", "c");
4127 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4128 emitcode("cpl", "a");
4131 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4134 emitcode ("subb", "a,%s",
4135 aopGet(rightOp, offset, FALSE, TRUE));
4138 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4143 adjustArithmeticResult (ic);
4146 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4147 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4148 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4152 /*-----------------------------------------------------------------*/
4153 /* genMultbits :- multiplication of bits */
4154 /*-----------------------------------------------------------------*/
4156 genMultbits (operand * left,
4160 D(emitcode ("; genMultbits",""));
4162 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4163 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4167 /*-----------------------------------------------------------------*/
4168 /* genMultOneByte : 8*8=8/16 bit multiplication */
4169 /*-----------------------------------------------------------------*/
4171 genMultOneByte (operand * left,
4176 int size = AOP_SIZE (result);
4177 bool runtimeSign, compiletimeSign;
4178 bool lUnsigned, rUnsigned, pushedB;
4180 D(emitcode ("; genMultOneByte",""));
4182 if (size < 1 || size > 2)
4184 /* this should never happen */
4185 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4186 AOP_SIZE(result), __FILE__, lineno);
4190 /* (if two literals: the value is computed before) */
4191 /* if one literal, literal on the right */
4192 if (AOP_TYPE (left) == AOP_LIT)
4197 /* emitcode (";", "swapped left and right"); */
4199 /* if no literal, unsigned on the right: shorter code */
4200 if ( AOP_TYPE (right) != AOP_LIT
4201 && SPEC_USIGN (getSpec (operandType (left))))
4208 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4209 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4213 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4214 no need to take care about the signedness! */
4215 || (lUnsigned && rUnsigned))
4217 /* just an unsigned 8 * 8 = 8 multiply
4219 /* emitcode (";","unsigned"); */
4220 /* TODO: check for accumulator clash between left & right aops? */
4222 if (AOP_TYPE (right) == AOP_LIT)
4224 /* moving to accumulator first helps peepholes */
4225 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4226 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4230 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4231 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4234 emitcode ("mul", "ab");
4235 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4237 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4243 /* we have to do a signed multiply */
4244 /* emitcode (";", "signed"); */
4246 /* now sign adjust for both left & right */
4248 /* let's see what's needed: */
4249 /* apply negative sign during runtime */
4250 runtimeSign = FALSE;
4251 /* negative sign from literals */
4252 compiletimeSign = FALSE;
4256 if (AOP_TYPE(left) == AOP_LIT)
4258 /* signed literal */
4259 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4261 compiletimeSign = TRUE;
4264 /* signed but not literal */
4270 if (AOP_TYPE(right) == AOP_LIT)
4272 /* signed literal */
4273 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4275 compiletimeSign ^= TRUE;
4278 /* signed but not literal */
4282 /* initialize F0, which stores the runtime sign */
4285 if (compiletimeSign)
4286 emitcode ("setb", "F0"); /* set sign flag */
4288 emitcode ("clr", "F0"); /* reset sign flag */
4291 /* save the signs of the operands */
4292 if (AOP_TYPE(right) == AOP_LIT)
4294 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4296 if (!rUnsigned && val < 0)
4297 emitcode ("mov", "b,#0x%02x", -val);
4299 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4301 else /* ! literal */
4303 if (rUnsigned) /* emitcode (";", "signed"); */
4305 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4308 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4309 lbl = newiTempLabel (NULL);
4310 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4311 emitcode ("cpl", "F0"); /* complement sign flag */
4312 emitcode ("cpl", "a"); /* 2's complement */
4313 emitcode ("inc", "a");
4314 emitcode ("", "%05d$:", (lbl->key + 100));
4315 emitcode ("mov", "b,a");
4319 if (AOP_TYPE(left) == AOP_LIT)
4321 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4323 if (!lUnsigned && val < 0)
4324 emitcode ("mov", "a,#0x%02x", -val);
4326 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4328 else /* ! literal */
4330 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4334 lbl = newiTempLabel (NULL);
4335 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4336 emitcode ("cpl", "F0"); /* complement sign flag */
4337 emitcode ("cpl", "a"); /* 2's complement */
4338 emitcode ("inc", "a");
4339 emitcode ("", "%05d$:", (lbl->key + 100));
4343 /* now the multiplication */
4344 emitcode ("mul", "ab");
4345 if (runtimeSign || compiletimeSign)
4347 lbl = newiTempLabel (NULL);
4349 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4350 emitcode ("cpl", "a"); /* lsb 2's complement */
4352 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4355 emitcode ("add", "a,#1"); /* this sets carry flag */
4356 emitcode ("xch", "a,b");
4357 emitcode ("cpl", "a"); /* msb 2's complement */
4358 emitcode ("addc", "a,#0");
4359 emitcode ("xch", "a,b");
4361 emitcode ("", "%05d$:", (lbl->key + 100));
4363 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4365 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4370 /*-----------------------------------------------------------------*/
4371 /* genMult - generates code for multiplication */
4372 /*-----------------------------------------------------------------*/
4374 genMult (iCode * ic)
4376 operand *left = IC_LEFT (ic);
4377 operand *right = IC_RIGHT (ic);
4378 operand *result = IC_RESULT (ic);
4380 D(emitcode ("; genMult",""));
4382 /* assign the amsops */
4383 aopOp (left, ic, FALSE);
4384 aopOp (right, ic, FALSE);
4385 aopOp (result, ic, TRUE);
4387 /* special cases first */
4389 if (AOP_TYPE (left) == AOP_CRY &&
4390 AOP_TYPE (right) == AOP_CRY)
4392 genMultbits (left, right, result);
4396 /* if both are of size == 1 */
4397 #if 0 // one of them can be a sloc shared with the result
4398 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4400 if (getSize(operandType(left)) == 1 &&
4401 getSize(operandType(right)) == 1)
4404 genMultOneByte (left, right, result);
4408 /* should have been converted to function call */
4409 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4410 getSize(OP_SYMBOL(right)->type));
4414 freeAsmop (result, NULL, ic, TRUE);
4415 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4416 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4419 /*-----------------------------------------------------------------*/
4420 /* genDivbits :- division of bits */
4421 /*-----------------------------------------------------------------*/
4423 genDivbits (operand * left,
4430 D(emitcode ("; genDivbits",""));
4434 /* the result must be bit */
4435 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4436 l = aopGet (AOP (left), 0, FALSE, FALSE);
4440 emitcode ("div", "ab");
4441 emitcode ("rrc", "a");
4445 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4448 /*-----------------------------------------------------------------*/
4449 /* genDivOneByte : 8 bit division */
4450 /*-----------------------------------------------------------------*/
4452 genDivOneByte (operand * left,
4456 bool lUnsigned, rUnsigned, pushedB;
4457 bool runtimeSign, compiletimeSign;
4461 D(emitcode ("; genDivOneByte",""));
4463 /* Why is it necessary that genDivOneByte() can return an int result?
4466 volatile unsigned char uc;
4467 volatile signed char sc1, sc2;
4480 In all cases a one byte result would overflow, the following cast to int
4481 would return the wrong result.
4483 Two possible solution:
4484 a) cast operands to int, if ((unsigned) / (signed)) or
4485 ((signed) / (signed))
4486 b) return an 16 bit signed int; this is what we're doing here!
4489 size = AOP_SIZE (result) - 1;
4491 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4492 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4496 /* signed or unsigned */
4497 if (lUnsigned && rUnsigned)
4499 /* unsigned is easy */
4500 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4501 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4502 emitcode ("div", "ab");
4503 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4505 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4511 /* signed is a little bit more difficult */
4513 /* now sign adjust for both left & right */
4515 /* let's see what's needed: */
4516 /* apply negative sign during runtime */
4517 runtimeSign = FALSE;
4518 /* negative sign from literals */
4519 compiletimeSign = FALSE;
4523 if (AOP_TYPE(left) == AOP_LIT)
4525 /* signed literal */
4526 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4528 compiletimeSign = TRUE;
4531 /* signed but not literal */
4537 if (AOP_TYPE(right) == AOP_LIT)
4539 /* signed literal */
4540 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4542 compiletimeSign ^= TRUE;
4545 /* signed but not literal */
4549 /* initialize F0, which stores the runtime sign */
4552 if (compiletimeSign)
4553 emitcode ("setb", "F0"); /* set sign flag */
4555 emitcode ("clr", "F0"); /* reset sign flag */
4558 /* save the signs of the operands */
4559 if (AOP_TYPE(right) == AOP_LIT)
4561 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4563 if (!rUnsigned && val < 0)
4564 emitcode ("mov", "b,#0x%02x", -val);
4566 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4568 else /* ! literal */
4571 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4574 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4575 lbl = newiTempLabel (NULL);
4576 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4577 emitcode ("cpl", "F0"); /* complement sign flag */
4578 emitcode ("cpl", "a"); /* 2's complement */
4579 emitcode ("inc", "a");
4580 emitcode ("", "%05d$:", (lbl->key + 100));
4581 emitcode ("mov", "b,a");
4585 if (AOP_TYPE(left) == AOP_LIT)
4587 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4589 if (!lUnsigned && val < 0)
4590 emitcode ("mov", "a,#0x%02x", -val);
4592 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4594 else /* ! literal */
4596 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4600 lbl = newiTempLabel (NULL);
4601 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4602 emitcode ("cpl", "F0"); /* complement sign flag */
4603 emitcode ("cpl", "a"); /* 2's complement */
4604 emitcode ("inc", "a");
4605 emitcode ("", "%05d$:", (lbl->key + 100));
4609 /* now the division */
4610 emitcode ("div", "ab");
4612 if (runtimeSign || compiletimeSign)
4614 lbl = newiTempLabel (NULL);
4616 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4617 emitcode ("cpl", "a"); /* lsb 2's complement */
4618 emitcode ("inc", "a");
4619 emitcode ("", "%05d$:", (lbl->key + 100));
4621 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4624 /* msb is 0x00 or 0xff depending on the sign */
4627 emitcode ("mov", "c,F0");
4628 emitcode ("subb", "a,acc");
4630 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4632 else /* compiletimeSign */
4634 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4639 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4641 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4647 /*-----------------------------------------------------------------*/
4648 /* genDiv - generates code for division */
4649 /*-----------------------------------------------------------------*/
4653 operand *left = IC_LEFT (ic);
4654 operand *right = IC_RIGHT (ic);
4655 operand *result = IC_RESULT (ic);
4657 D(emitcode ("; genDiv",""));
4659 /* assign the amsops */
4660 aopOp (left, ic, FALSE);
4661 aopOp (right, ic, FALSE);
4662 aopOp (result, ic, TRUE);
4664 /* special cases first */
4666 if (AOP_TYPE (left) == AOP_CRY &&
4667 AOP_TYPE (right) == AOP_CRY)
4669 genDivbits (left, right, result);
4673 /* if both are of size == 1 */
4674 if (AOP_SIZE (left) == 1 &&
4675 AOP_SIZE (right) == 1)
4677 genDivOneByte (left, right, result);
4681 /* should have been converted to function call */
4684 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4685 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4686 freeAsmop (result, NULL, ic, TRUE);
4689 /*-----------------------------------------------------------------*/
4690 /* genModbits :- modulus of bits */
4691 /*-----------------------------------------------------------------*/
4693 genModbits (operand * left,
4700 D(emitcode ("; genModbits",""));
4704 /* the result must be bit */
4705 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4706 l = aopGet (AOP (left), 0, FALSE, FALSE);
4710 emitcode ("div", "ab");
4711 emitcode ("mov", "a,b");
4712 emitcode ("rrc", "a");
4716 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4719 /*-----------------------------------------------------------------*/
4720 /* genModOneByte : 8 bit modulus */
4721 /*-----------------------------------------------------------------*/
4723 genModOneByte (operand * left,
4727 bool lUnsigned, rUnsigned, pushedB;
4728 bool runtimeSign, compiletimeSign;
4732 D(emitcode ("; genModOneByte",""));
4734 size = AOP_SIZE (result) - 1;
4736 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4737 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4739 /* if right is a literal, check it for 2^n */
4740 if (AOP_TYPE(right) == AOP_LIT)
4742 unsigned char val = abs((int) operandLitValue(right));
4743 symbol *lbl2 = NULL;
4747 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
4756 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4757 "modulus of unsigned char by 2^n literal shouldn't be processed here");
4758 /* because iCode should have been changed to genAnd */
4759 /* see file "SDCCopt.c", function "convertToFcall()" */
4761 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4762 emitcode ("mov", "c,acc.7");
4763 emitcode ("anl", "a,#0x%02x", val - 1);
4764 lbl = newiTempLabel (NULL);
4765 emitcode ("jz", "%05d$", (lbl->key + 100));
4766 emitcode ("jnc", "%05d$", (lbl->key + 100));
4767 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
4773 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4775 aopPut (AOP (result), "#0xff", offs2++, isOperandVolatile (result, FALSE));
4776 lbl2 = newiTempLabel (NULL);
4777 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
4779 emitcode ("", "%05d$:", (lbl->key + 100));
4780 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4782 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4785 emitcode ("", "%05d$:", (lbl2->key + 100));
4796 /* signed or unsigned */
4797 if (lUnsigned && rUnsigned)
4799 /* unsigned is easy */
4800 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4801 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4802 emitcode ("div", "ab");
4803 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4805 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4811 /* signed is a little bit more difficult */
4813 /* now sign adjust for both left & right */
4815 /* modulus: sign of the right operand has no influence on the result! */
4816 if (AOP_TYPE(right) == AOP_LIT)
4818 signed char val = (char) operandLitValue(right);
4820 if (!rUnsigned && val < 0)
4821 emitcode ("mov", "b,#0x%02x", -val);
4823 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4825 else /* not literal */
4828 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4831 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4832 lbl = newiTempLabel (NULL);
4833 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4834 emitcode ("cpl", "a"); /* 2's complement */
4835 emitcode ("inc", "a");
4836 emitcode ("", "%05d$:", (lbl->key + 100));
4837 emitcode ("mov", "b,a");
4841 /* let's see what's needed: */
4842 /* apply negative sign during runtime */
4843 runtimeSign = FALSE;
4844 /* negative sign from literals */
4845 compiletimeSign = FALSE;
4847 /* sign adjust left side */
4848 if (AOP_TYPE(left) == AOP_LIT)
4850 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4852 if (!lUnsigned && val < 0)
4854 compiletimeSign = TRUE; /* set sign flag */
4855 emitcode ("mov", "a,#0x%02x", -val);
4858 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4860 else /* ! literal */
4862 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4867 emitcode ("clr", "F0"); /* clear sign flag */
4869 lbl = newiTempLabel (NULL);
4870 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4871 emitcode ("setb", "F0"); /* set sign flag */
4872 emitcode ("cpl", "a"); /* 2's complement */
4873 emitcode ("inc", "a");
4874 emitcode ("", "%05d$:", (lbl->key + 100));
4878 /* now the modulus */
4879 emitcode ("div", "ab");
4881 if (runtimeSign || compiletimeSign)
4883 emitcode ("mov", "a,b");
4884 lbl = newiTempLabel (NULL);
4886 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4887 emitcode ("cpl", "a"); /* 2's complement */
4888 emitcode ("inc", "a");
4889 emitcode ("", "%05d$:", (lbl->key + 100));
4891 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4894 /* msb is 0x00 or 0xff depending on the sign */
4897 emitcode ("mov", "c,F0");
4898 emitcode ("subb", "a,acc");
4900 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4902 else /* compiletimeSign */
4904 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4909 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4911 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4917 /*-----------------------------------------------------------------*/
4918 /* genMod - generates code for division */
4919 /*-----------------------------------------------------------------*/
4923 operand *left = IC_LEFT (ic);
4924 operand *right = IC_RIGHT (ic);
4925 operand *result = IC_RESULT (ic);
4927 D(emitcode ("; genMod",""));
4929 /* assign the asmops */
4930 aopOp (left, ic, FALSE);
4931 aopOp (right, ic, FALSE);
4932 aopOp (result, ic, TRUE);
4934 /* special cases first */
4936 if (AOP_TYPE (left) == AOP_CRY &&
4937 AOP_TYPE (right) == AOP_CRY)
4939 genModbits (left, right, result);
4943 /* if both are of size == 1 */
4944 if (AOP_SIZE (left) == 1 &&
4945 AOP_SIZE (right) == 1)
4947 genModOneByte (left, right, result);
4951 /* should have been converted to function call */
4955 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4956 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4957 freeAsmop (result, NULL, ic, TRUE);
4960 /*-----------------------------------------------------------------*/
4961 /* genIfxJump :- will create a jump depending on the ifx */
4962 /*-----------------------------------------------------------------*/
4964 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4967 symbol *tlbl = newiTempLabel (NULL);
4970 D(emitcode ("; genIfxJump",""));
4972 /* if true label then we jump if condition
4976 jlbl = IC_TRUE (ic);
4977 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4978 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4982 /* false label is present */
4983 jlbl = IC_FALSE (ic);
4984 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4985 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4987 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4988 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4990 emitcode (inst, "%05d$", tlbl->key + 100);
4991 freeForBranchAsmop (result);
4992 freeForBranchAsmop (right);
4993 freeForBranchAsmop (left);
4994 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4995 emitcode ("", "%05d$:", tlbl->key + 100);
4997 /* mark the icode as generated */
5001 /*-----------------------------------------------------------------*/
5002 /* genCmp :- greater or less than comparison */
5003 /*-----------------------------------------------------------------*/
5005 genCmp (operand * left, operand * right,
5006 operand * result, iCode * ifx, int sign, iCode *ic)
5008 int size, offset = 0;
5009 unsigned long lit = 0L;
5012 D(emitcode ("; genCmp",""));
5014 /* if left & right are bit variables */
5015 if (AOP_TYPE (left) == AOP_CRY &&
5016 AOP_TYPE (right) == AOP_CRY)
5018 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5019 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5023 /* subtract right from left if at the
5024 end the carry flag is set then we know that
5025 left is greater than right */
5026 size = max (AOP_SIZE (left), AOP_SIZE (right));
5028 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5029 if ((size == 1) && !sign &&
5030 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5032 symbol *lbl = newiTempLabel (NULL);
5033 emitcode ("cjne", "%s,%s,%05d$",
5034 aopGet (AOP (left), offset, FALSE, FALSE),
5035 aopGet (AOP (right), offset, FALSE, FALSE),
5037 emitcode ("", "%05d$:", lbl->key + 100);
5041 if (AOP_TYPE (right) == AOP_LIT)
5043 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5044 /* optimize if(x < 0) or if(x >= 0) */
5053 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5054 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5056 genIfxJump (ifx, "acc.7", left, right, result);
5057 freeAsmop (right, NULL, ic, TRUE);
5058 freeAsmop (left, NULL, ic, TRUE);
5063 emitcode ("rlc", "a");
5071 bool pushedB = FALSE;
5072 rightInB = aopGetUsesAcc(AOP (right), offset);
5076 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5078 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5079 if (sign && size == 0)
5081 emitcode ("xrl", "a,#0x80");
5082 if (AOP_TYPE (right) == AOP_LIT)
5084 unsigned long lit = (unsigned long)
5085 floatFromVal (AOP (right)->aopu.aop_lit);
5086 emitcode ("subb", "a,#0x%02x",
5087 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5095 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5097 emitcode ("xrl", "b,#0x80");
5098 emitcode ("subb", "a,b");
5104 emitcode ("subb", "a,b");
5106 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5116 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5117 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5118 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5124 /* if the result is used in the next
5125 ifx conditional branch then generate
5126 code a little differently */
5128 genIfxJump (ifx, "c", NULL, NULL, result);
5131 /* leave the result in acc */
5135 /*-----------------------------------------------------------------*/
5136 /* genCmpGt :- greater than comparison */
5137 /*-----------------------------------------------------------------*/
5139 genCmpGt (iCode * ic, iCode * ifx)
5141 operand *left, *right, *result;
5142 sym_link *letype, *retype;
5145 D(emitcode ("; genCmpGt",""));
5147 left = IC_LEFT (ic);
5148 right = IC_RIGHT (ic);
5149 result = IC_RESULT (ic);
5151 letype = getSpec (operandType (left));
5152 retype = getSpec (operandType (right));
5153 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5154 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5155 /* assign the amsops */
5156 aopOp (left, ic, FALSE);
5157 aopOp (right, ic, FALSE);
5158 aopOp (result, ic, TRUE);
5160 genCmp (right, left, result, ifx, sign, ic);
5162 freeAsmop (result, NULL, ic, TRUE);
5165 /*-----------------------------------------------------------------*/
5166 /* genCmpLt - less than comparisons */
5167 /*-----------------------------------------------------------------*/
5169 genCmpLt (iCode * ic, iCode * ifx)
5171 operand *left, *right, *result;
5172 sym_link *letype, *retype;
5175 D(emitcode ("; genCmpLt",""));
5177 left = IC_LEFT (ic);
5178 right = IC_RIGHT (ic);
5179 result = IC_RESULT (ic);
5181 letype = getSpec (operandType (left));
5182 retype = getSpec (operandType (right));
5183 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5184 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5185 /* assign the amsops */
5186 aopOp (left, ic, FALSE);
5187 aopOp (right, ic, FALSE);
5188 aopOp (result, ic, TRUE);
5190 genCmp (left, right, result, ifx, sign,ic);
5192 freeAsmop (result, NULL, ic, TRUE);
5195 /*-----------------------------------------------------------------*/
5196 /* gencjneshort - compare and jump if not equal */
5197 /*-----------------------------------------------------------------*/
5199 gencjneshort (operand * left, operand * right, symbol * lbl)
5201 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5203 unsigned long lit = 0L;
5205 /* if the left side is a literal or
5206 if the right is in a pointer register and left
5208 if ((AOP_TYPE (left) == AOP_LIT) ||
5209 (AOP_TYPE (left) == AOP_IMMD) ||
5210 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5217 if (AOP_TYPE (right) == AOP_LIT)
5218 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5220 /* if the right side is a literal then anything goes */
5221 if (AOP_TYPE (right) == AOP_LIT &&
5222 AOP_TYPE (left) != AOP_DIR &&
5223 AOP_TYPE (left) != AOP_IMMD)
5227 emitcode ("cjne", "%s,%s,%05d$",
5228 aopGet (AOP (left), offset, FALSE, FALSE),
5229 aopGet (AOP (right), offset, FALSE, FALSE),
5235 /* if the right side is in a register or in direct space or
5236 if the left is a pointer register & right is not */
5237 else if (AOP_TYPE (right) == AOP_REG ||
5238 AOP_TYPE (right) == AOP_DIR ||
5239 AOP_TYPE (right) == AOP_LIT ||
5240 AOP_TYPE (right) == AOP_IMMD ||
5241 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5242 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5246 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5247 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5248 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5249 emitcode ("jnz", "%05d$", lbl->key + 100);
5251 emitcode ("cjne", "a,%s,%05d$",
5252 aopGet (AOP (right), offset, FALSE, TRUE),
5259 /* right is a pointer reg need both a & b */
5263 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5264 wassertl(!BINUSE, "B was in use");
5265 l = aopGet (AOP (left), offset, FALSE, FALSE);
5266 if (strcmp (l, "b"))
5267 emitcode ("mov", "b,%s", l);
5268 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5269 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5275 /*-----------------------------------------------------------------*/
5276 /* gencjne - compare and jump if not equal */
5277 /*-----------------------------------------------------------------*/
5279 gencjne (operand * left, operand * right, symbol * lbl)
5281 symbol *tlbl = newiTempLabel (NULL);
5283 gencjneshort (left, right, lbl);
5285 emitcode ("mov", "a,%s", one);
5286 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5287 emitcode ("", "%05d$:", lbl->key + 100);
5288 emitcode ("clr", "a");
5289 emitcode ("", "%05d$:", tlbl->key + 100);
5292 /*-----------------------------------------------------------------*/
5293 /* genCmpEq - generates code for equal to */
5294 /*-----------------------------------------------------------------*/
5296 genCmpEq (iCode * ic, iCode * ifx)
5298 operand *left, *right, *result;
5300 D(emitcode ("; genCmpEq",""));
5302 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5303 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5304 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5306 /* if literal, literal on the right or
5307 if the right is in a pointer register and left
5309 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5310 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5312 operand *t = IC_RIGHT (ic);
5313 IC_RIGHT (ic) = IC_LEFT (ic);
5317 if (ifx && !AOP_SIZE (result))
5320 /* if they are both bit variables */
5321 if (AOP_TYPE (left) == AOP_CRY &&
5322 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5324 if (AOP_TYPE (right) == AOP_LIT)
5326 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5329 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5330 emitcode ("cpl", "c");
5334 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5338 emitcode ("clr", "c");
5340 /* AOP_TYPE(right) == AOP_CRY */
5344 symbol *lbl = newiTempLabel (NULL);
5345 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5346 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5347 emitcode ("cpl", "c");
5348 emitcode ("", "%05d$:", (lbl->key + 100));
5350 /* if true label then we jump if condition
5352 tlbl = newiTempLabel (NULL);
5355 emitcode ("jnc", "%05d$", tlbl->key + 100);
5356 freeForBranchAsmop (result);
5357 freeForBranchAsmop (right);
5358 freeForBranchAsmop (left);
5359 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5363 emitcode ("jc", "%05d$", tlbl->key + 100);
5364 freeForBranchAsmop (result);
5365 freeForBranchAsmop (right);
5366 freeForBranchAsmop (left);
5367 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5369 emitcode ("", "%05d$:", tlbl->key + 100);
5373 tlbl = newiTempLabel (NULL);
5374 gencjneshort (left, right, tlbl);
5377 freeForBranchAsmop (result);
5378 freeForBranchAsmop (right);
5379 freeForBranchAsmop (left);
5380 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5381 emitcode ("", "%05d$:", tlbl->key + 100);
5385 symbol *lbl = newiTempLabel (NULL);
5386 emitcode ("sjmp", "%05d$", lbl->key + 100);
5387 emitcode ("", "%05d$:", tlbl->key + 100);
5388 freeForBranchAsmop (result);
5389 freeForBranchAsmop (right);
5390 freeForBranchAsmop (left);
5391 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5392 emitcode ("", "%05d$:", lbl->key + 100);
5395 /* mark the icode as generated */
5400 /* if they are both bit variables */
5401 if (AOP_TYPE (left) == AOP_CRY &&
5402 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5404 if (AOP_TYPE (right) == AOP_LIT)
5406 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5409 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5410 emitcode ("cpl", "c");
5414 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5418 emitcode ("clr", "c");
5420 /* AOP_TYPE(right) == AOP_CRY */
5424 symbol *lbl = newiTempLabel (NULL);
5425 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5426 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5427 emitcode ("cpl", "c");
5428 emitcode ("", "%05d$:", (lbl->key + 100));
5431 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5438 genIfxJump (ifx, "c", left, right, result);
5441 /* if the result is used in an arithmetic operation
5442 then put the result in place */
5447 gencjne (left, right, newiTempLabel (NULL));
5448 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5450 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5455 genIfxJump (ifx, "a", left, right, result);
5458 /* if the result is used in an arithmetic operation
5459 then put the result in place */
5460 if (AOP_TYPE (result) != AOP_CRY)
5462 /* leave the result in acc */
5466 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5467 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5468 freeAsmop (result, NULL, ic, TRUE);
5471 /*-----------------------------------------------------------------*/
5472 /* ifxForOp - returns the icode containing the ifx for operand */
5473 /*-----------------------------------------------------------------*/
5475 ifxForOp (operand * op, iCode * ic)
5477 /* if true symbol then needs to be assigned */
5478 if (IS_TRUE_SYMOP (op))
5481 /* if this has register type condition and
5482 the next instruction is ifx with the same operand
5483 and live to of the operand is upto the ifx only then */
5485 ic->next->op == IFX &&
5486 IC_COND (ic->next)->key == op->key &&
5487 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5493 /*-----------------------------------------------------------------*/
5494 /* hasInc - operand is incremented before any other use */
5495 /*-----------------------------------------------------------------*/
5497 hasInc (operand *op, iCode *ic,int osize)
5499 sym_link *type = operandType(op);
5500 sym_link *retype = getSpec (type);
5501 iCode *lic = ic->next;
5504 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5505 if (!IS_SYMOP(op)) return NULL;
5507 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5508 if (IS_AGGREGATE(type->next)) return NULL;
5509 if (osize != (isize = getSize(type->next))) return NULL;
5512 /* if operand of the form op = op + <sizeof *op> */
5513 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5514 isOperandEqual(IC_RESULT(lic),op) &&
5515 isOperandLiteral(IC_RIGHT(lic)) &&
5516 operandLitValue(IC_RIGHT(lic)) == isize) {
5519 /* if the operand used or deffed */
5520 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5523 /* if GOTO or IFX */
5524 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5530 /*-----------------------------------------------------------------*/
5531 /* genAndOp - for && operation */
5532 /*-----------------------------------------------------------------*/
5534 genAndOp (iCode * ic)
5536 operand *left, *right, *result;
5539 D(emitcode ("; genAndOp",""));
5541 /* note here that && operations that are in an
5542 if statement are taken away by backPatchLabels
5543 only those used in arthmetic operations remain */
5544 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5545 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5546 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5548 /* if both are bit variables */
5549 if (AOP_TYPE (left) == AOP_CRY &&
5550 AOP_TYPE (right) == AOP_CRY)
5552 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5553 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5558 tlbl = newiTempLabel (NULL);
5560 emitcode ("jz", "%05d$", tlbl->key + 100);
5562 emitcode ("", "%05d$:", tlbl->key + 100);
5566 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5567 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5568 freeAsmop (result, NULL, ic, TRUE);
5572 /*-----------------------------------------------------------------*/
5573 /* genOrOp - for || operation */
5574 /*-----------------------------------------------------------------*/
5576 genOrOp (iCode * ic)
5578 operand *left, *right, *result;
5581 D(emitcode ("; genOrOp",""));
5583 /* note here that || operations that are in an
5584 if statement are taken away by backPatchLabels
5585 only those used in arthmetic operations remain */
5586 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5587 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5588 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5590 /* if both are bit variables */
5591 if (AOP_TYPE (left) == AOP_CRY &&
5592 AOP_TYPE (right) == AOP_CRY)
5594 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5595 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5600 tlbl = newiTempLabel (NULL);
5602 emitcode ("jnz", "%05d$", tlbl->key + 100);
5604 emitcode ("", "%05d$:", tlbl->key + 100);
5608 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5609 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5610 freeAsmop (result, NULL, ic, TRUE);
5613 /*-----------------------------------------------------------------*/
5614 /* isLiteralBit - test if lit == 2^n */
5615 /*-----------------------------------------------------------------*/
5617 isLiteralBit (unsigned long lit)
5619 unsigned long pw[32] =
5620 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5621 0x100L, 0x200L, 0x400L, 0x800L,
5622 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5623 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5624 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5625 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5626 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5629 for (idx = 0; idx < 32; idx++)
5635 /*-----------------------------------------------------------------*/
5636 /* continueIfTrue - */
5637 /*-----------------------------------------------------------------*/
5639 continueIfTrue (iCode * ic)
5642 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5646 /*-----------------------------------------------------------------*/
5648 /*-----------------------------------------------------------------*/
5650 jumpIfTrue (iCode * ic)
5653 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5657 /*-----------------------------------------------------------------*/
5658 /* jmpTrueOrFalse - */
5659 /*-----------------------------------------------------------------*/
5661 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5663 // ugly but optimized by peephole
5666 symbol *nlbl = newiTempLabel (NULL);
5667 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5668 emitcode ("", "%05d$:", tlbl->key + 100);
5669 freeForBranchAsmop (result);
5670 freeForBranchAsmop (right);
5671 freeForBranchAsmop (left);
5672 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5673 emitcode ("", "%05d$:", nlbl->key + 100);
5677 freeForBranchAsmop (result);
5678 freeForBranchAsmop (right);
5679 freeForBranchAsmop (left);
5680 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5681 emitcode ("", "%05d$:", tlbl->key + 100);
5686 /*-----------------------------------------------------------------*/
5687 /* genAnd - code for and */
5688 /*-----------------------------------------------------------------*/
5690 genAnd (iCode * ic, iCode * ifx)
5692 operand *left, *right, *result;
5693 int size, offset = 0;
5694 unsigned long lit = 0L;
5698 D(emitcode ("; genAnd",""));
5700 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5701 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5702 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5705 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5707 AOP_TYPE (left), AOP_TYPE (right));
5708 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5710 AOP_SIZE (left), AOP_SIZE (right));
5713 /* if left is a literal & right is not then exchange them */
5714 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5715 AOP_NEEDSACC (left))
5717 operand *tmp = right;
5722 /* if result = right then exchange left and right */
5723 if (sameRegs (AOP (result), AOP (right)))
5725 operand *tmp = right;
5730 /* if right is bit then exchange them */
5731 if (AOP_TYPE (right) == AOP_CRY &&
5732 AOP_TYPE (left) != AOP_CRY)
5734 operand *tmp = right;
5738 if (AOP_TYPE (right) == AOP_LIT)
5739 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5741 size = AOP_SIZE (result);
5744 // result = bit & yy;
5745 if (AOP_TYPE (left) == AOP_CRY)
5747 // c = bit & literal;
5748 if (AOP_TYPE (right) == AOP_LIT)
5752 if (size && sameRegs (AOP (result), AOP (left)))
5755 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5760 if (size && (AOP_TYPE (result) == AOP_CRY))
5762 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5765 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5770 emitcode ("clr", "c");
5775 if (AOP_TYPE (right) == AOP_CRY)
5778 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5779 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5784 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5786 emitcode ("rrc", "a");
5787 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5795 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5796 genIfxJump (ifx, "c", left, right, result);
5800 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5801 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5802 if ((AOP_TYPE (right) == AOP_LIT) &&
5803 (AOP_TYPE (result) == AOP_CRY) &&
5804 (AOP_TYPE (left) != AOP_CRY))
5806 int posbit = isLiteralBit (lit);
5811 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5815 switch (posbit & 0x07)
5817 case 0: emitcode ("rrc", "a");
5819 case 7: emitcode ("rlc", "a");
5821 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
5830 SNPRINTF (buffer, sizeof(buffer),
5831 "acc.%d", posbit & 0x07);
5832 genIfxJump (ifx, buffer, left, right, result);
5835 {// what is this case? just found it in ds390/gen.c
5836 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5843 symbol *tlbl = newiTempLabel (NULL);
5844 int sizel = AOP_SIZE (left);
5846 emitcode ("setb", "c");
5849 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5851 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5853 if ((posbit = isLiteralBit (bytelit)) != 0)
5854 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5857 if (bytelit != 0x0FFL)
5858 emitcode ("anl", "a,%s",
5859 aopGet (AOP (right), offset, FALSE, TRUE));
5860 emitcode ("jnz", "%05d$", tlbl->key + 100);
5865 // bit = left & literal
5868 emitcode ("clr", "c");
5869 emitcode ("", "%05d$:", tlbl->key + 100);
5871 // if(left & literal)
5875 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5877 emitcode ("", "%05d$:", tlbl->key + 100);
5885 /* if left is same as result */
5886 if (sameRegs (AOP (result), AOP (left)))
5888 for (; size--; offset++)
5890 if (AOP_TYPE (right) == AOP_LIT)
5892 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5893 if (bytelit == 0x0FF)
5895 /* dummy read of volatile operand */
5896 if (isOperandVolatile (left, FALSE))
5897 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5901 else if (bytelit == 0)
5903 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5905 else if (IS_AOP_PREG (result))
5907 MOVA (aopGet (AOP (left), offset, FALSE, TRUE));
5908 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5909 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5912 emitcode ("anl", "%s,%s",
5913 aopGet (AOP (left), offset, FALSE, TRUE),
5914 aopGet (AOP (right), offset, FALSE, FALSE));
5918 if (AOP_TYPE (left) == AOP_ACC)
5919 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5922 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5923 if (IS_AOP_PREG (result))
5925 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5926 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5929 emitcode ("anl", "%s,a",
5930 aopGet (AOP (left), offset, FALSE, TRUE));
5937 // left & result in different registers
5938 if (AOP_TYPE (result) == AOP_CRY)
5941 // if(size), result in bit
5942 // if(!size && ifx), conditional oper: if(left & right)
5943 symbol *tlbl = newiTempLabel (NULL);
5944 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5946 emitcode ("setb", "c");
5949 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5950 emitcode ("anl", "a,%s",
5951 aopGet (AOP (right), offset, FALSE, FALSE));
5953 if (AOP_TYPE(left)==AOP_ACC) {
5954 bool pushedB = pushB ();
5955 emitcode("mov", "b,a");
5956 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5957 emitcode("anl", "a,b");
5960 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5961 emitcode ("anl", "a,%s",
5962 aopGet (AOP (left), offset, FALSE, FALSE));
5965 emitcode ("jnz", "%05d$", tlbl->key + 100);
5971 emitcode ("", "%05d$:", tlbl->key + 100);
5975 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5977 emitcode ("", "%05d$:", tlbl->key + 100);
5981 for (; (size--); offset++)
5984 // result = left & right
5985 if (AOP_TYPE (right) == AOP_LIT)
5987 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5988 if (bytelit == 0x0FF)
5990 aopPut (AOP (result),
5991 aopGet (AOP (left), offset, FALSE, FALSE),
5993 isOperandVolatile (result, FALSE));
5996 else if (bytelit == 0)
5998 /* dummy read of volatile operand */
5999 if (isOperandVolatile (left, FALSE))
6000 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6001 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
6005 // faster than result <- left, anl result,right
6006 // and better if result is SFR
6007 if (AOP_TYPE (left) == AOP_ACC)
6008 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6011 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6012 emitcode ("anl", "a,%s",
6013 aopGet (AOP (left), offset, FALSE, FALSE));
6015 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6021 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6022 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6023 freeAsmop (result, NULL, ic, TRUE);
6026 /*-----------------------------------------------------------------*/
6027 /* genOr - code for or */
6028 /*-----------------------------------------------------------------*/
6030 genOr (iCode * ic, iCode * ifx)
6032 operand *left, *right, *result;
6033 int size, offset = 0;
6034 unsigned long lit = 0L;
6037 D(emitcode ("; genOr",""));
6039 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6040 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6041 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6044 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6046 AOP_TYPE (left), AOP_TYPE (right));
6047 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6049 AOP_SIZE (left), AOP_SIZE (right));
6052 /* if left is a literal & right is not then exchange them */
6053 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6054 AOP_NEEDSACC (left))
6056 operand *tmp = right;
6061 /* if result = right then exchange them */
6062 if (sameRegs (AOP (result), AOP (right)))
6064 operand *tmp = right;
6069 /* if right is bit then exchange them */
6070 if (AOP_TYPE (right) == AOP_CRY &&
6071 AOP_TYPE (left) != AOP_CRY)
6073 operand *tmp = right;
6077 if (AOP_TYPE (right) == AOP_LIT)
6078 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6080 size = AOP_SIZE (result);
6084 if (AOP_TYPE (left) == AOP_CRY)
6086 if (AOP_TYPE (right) == AOP_LIT)
6088 // c = bit | literal;
6091 // lit != 0 => result = 1
6092 if (AOP_TYPE (result) == AOP_CRY)
6095 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6097 continueIfTrue (ifx);
6100 emitcode ("setb", "c");
6104 // lit == 0 => result = left
6105 if (size && sameRegs (AOP (result), AOP (left)))
6107 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6112 if (AOP_TYPE (right) == AOP_CRY)
6115 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6116 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6121 symbol *tlbl = newiTempLabel (NULL);
6122 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6123 emitcode ("setb", "c");
6124 emitcode ("jb", "%s,%05d$",
6125 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6127 emitcode ("jnz", "%05d$", tlbl->key + 100);
6128 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6130 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6136 emitcode ("", "%05d$:", tlbl->key + 100);
6145 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6146 genIfxJump (ifx, "c", left, right, result);
6150 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6151 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6152 if ((AOP_TYPE (right) == AOP_LIT) &&
6153 (AOP_TYPE (result) == AOP_CRY) &&
6154 (AOP_TYPE (left) != AOP_CRY))
6160 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6162 continueIfTrue (ifx);
6167 // lit = 0, result = boolean(left)
6169 emitcode ("setb", "c");
6173 symbol *tlbl = newiTempLabel (NULL);
6174 emitcode ("jnz", "%05d$", tlbl->key + 100);
6176 emitcode ("", "%05d$:", tlbl->key + 100);
6180 genIfxJump (ifx, "a", left, right, result);
6188 /* if left is same as result */
6189 if (sameRegs (AOP (result), AOP (left)))
6191 for (; size--; offset++)
6193 if (AOP_TYPE (right) == AOP_LIT)
6195 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6198 /* dummy read of volatile operand */
6199 if (isOperandVolatile (left, FALSE))
6200 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6204 else if (bytelit == 0x0FF)
6206 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6208 else if (IS_AOP_PREG (left))
6210 MOVA (aopGet (AOP (left), offset, FALSE, TRUE));
6211 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6212 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6216 emitcode ("orl", "%s,%s",
6217 aopGet (AOP (left), offset, FALSE, TRUE),
6218 aopGet (AOP (right), offset, FALSE, FALSE));
6223 if (AOP_TYPE (left) == AOP_ACC)
6224 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6227 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6228 if (IS_AOP_PREG (left))
6230 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6231 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6235 emitcode ("orl", "%s,a",
6236 aopGet (AOP (left), offset, FALSE, TRUE));
6244 // left & result in different registers
6245 if (AOP_TYPE (result) == AOP_CRY)
6248 // if(size), result in bit
6249 // if(!size && ifx), conditional oper: if(left | right)
6250 symbol *tlbl = newiTempLabel (NULL);
6251 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6253 emitcode ("setb", "c");
6256 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6257 emitcode ("orl", "a,%s",
6258 aopGet (AOP (right), offset, FALSE, FALSE));
6260 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6261 emitcode ("orl", "a,%s",
6262 aopGet (AOP (left), offset, FALSE, FALSE));
6264 emitcode ("jnz", "%05d$", tlbl->key + 100);
6270 emitcode ("", "%05d$:", tlbl->key + 100);
6274 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6276 emitcode ("", "%05d$:", tlbl->key + 100);
6280 for (; (size--); offset++)
6283 // result = left | right
6284 if (AOP_TYPE (right) == AOP_LIT)
6286 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6289 aopPut (AOP (result),
6290 aopGet (AOP (left), offset, FALSE, FALSE),
6292 isOperandVolatile (result, FALSE));
6295 else if (bytelit == 0x0FF)
6297 /* dummy read of volatile operand */
6298 if (isOperandVolatile (left, FALSE))
6299 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6300 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6304 // faster than result <- left, anl result,right
6305 // and better if result is SFR
6306 if (AOP_TYPE (left) == AOP_ACC)
6307 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6310 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6311 emitcode ("orl", "a,%s",
6312 aopGet (AOP (left), offset, FALSE, FALSE));
6314 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6320 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6321 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6322 freeAsmop (result, NULL, ic, TRUE);
6325 /*-----------------------------------------------------------------*/
6326 /* genXor - code for xclusive or */
6327 /*-----------------------------------------------------------------*/
6329 genXor (iCode * ic, iCode * ifx)
6331 operand *left, *right, *result;
6332 int size, offset = 0;
6333 unsigned long lit = 0L;
6336 D(emitcode ("; genXor",""));
6338 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6339 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6340 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6343 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6345 AOP_TYPE (left), AOP_TYPE (right));
6346 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6348 AOP_SIZE (left), AOP_SIZE (right));
6351 /* if left is a literal & right is not ||
6352 if left needs acc & right does not */
6353 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6354 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6356 operand *tmp = right;
6361 /* if result = right then exchange them */
6362 if (sameRegs (AOP (result), AOP (right)))
6364 operand *tmp = right;
6369 /* if right is bit then exchange them */
6370 if (AOP_TYPE (right) == AOP_CRY &&
6371 AOP_TYPE (left) != AOP_CRY)
6373 operand *tmp = right;
6377 if (AOP_TYPE (right) == AOP_LIT)
6378 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6380 size = AOP_SIZE (result);
6384 if (AOP_TYPE (left) == AOP_CRY)
6386 if (AOP_TYPE (right) == AOP_LIT)
6388 // c = bit & literal;
6391 // lit>>1 != 0 => result = 1
6392 if (AOP_TYPE (result) == AOP_CRY)
6395 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6397 continueIfTrue (ifx);
6400 emitcode ("setb", "c");
6407 // lit == 0, result = left
6408 if (size && sameRegs (AOP (result), AOP (left)))
6410 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6414 // lit == 1, result = not(left)
6415 if (size && sameRegs (AOP (result), AOP (left)))
6417 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6422 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6423 emitcode ("cpl", "c");
6432 symbol *tlbl = newiTempLabel (NULL);
6433 if (AOP_TYPE (right) == AOP_CRY)
6436 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6440 int sizer = AOP_SIZE (right);
6442 // if val>>1 != 0, result = 1
6443 emitcode ("setb", "c");
6446 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6448 // test the msb of the lsb
6449 emitcode ("anl", "a,#0xfe");
6450 emitcode ("jnz", "%05d$", tlbl->key + 100);
6454 emitcode ("rrc", "a");
6456 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6457 emitcode ("cpl", "c");
6458 emitcode ("", "%05d$:", (tlbl->key + 100));
6465 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6466 genIfxJump (ifx, "c", left, right, result);
6470 /* if left is same as result */
6471 if (sameRegs (AOP (result), AOP (left)))
6473 for (; size--; offset++)
6475 if (AOP_TYPE (right) == AOP_LIT)
6477 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6480 /* dummy read of volatile operand */
6481 if (isOperandVolatile (left, FALSE))
6482 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6486 else if (IS_AOP_PREG (left))
6488 MOVA (aopGet (AOP (left), offset, FALSE, TRUE));
6489 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6490 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6494 emitcode ("xrl", "%s,%s",
6495 aopGet (AOP (left), offset, FALSE, TRUE),
6496 aopGet (AOP (right), offset, FALSE, FALSE));
6501 if (AOP_TYPE (left) == AOP_ACC)
6502 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6505 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6506 if (IS_AOP_PREG (left))
6508 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6509 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6512 emitcode ("xrl", "%s,a",
6513 aopGet (AOP (left), offset, FALSE, TRUE));
6520 // left & result in different registers
6521 if (AOP_TYPE (result) == AOP_CRY)
6524 // if(size), result in bit
6525 // if(!size && ifx), conditional oper: if(left ^ right)
6526 symbol *tlbl = newiTempLabel (NULL);
6527 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6529 emitcode ("setb", "c");
6532 if ((AOP_TYPE (right) == AOP_LIT) &&
6533 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6535 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6539 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6540 emitcode ("xrl", "a,%s",
6541 aopGet (AOP (right), offset, FALSE, FALSE));
6543 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6544 emitcode ("xrl", "a,%s",
6545 aopGet (AOP (left), offset, FALSE, FALSE));
6548 emitcode ("jnz", "%05d$", tlbl->key + 100);
6554 emitcode ("", "%05d$:", tlbl->key + 100);
6558 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6562 for (; (size--); offset++)
6565 // result = left & right
6566 if (AOP_TYPE (right) == AOP_LIT)
6568 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6571 aopPut (AOP (result),
6572 aopGet (AOP (left), offset, FALSE, FALSE),
6574 isOperandVolatile (result, FALSE));
6578 // faster than result <- left, anl result,right
6579 // and better if result is SFR
6580 if (AOP_TYPE (left) == AOP_ACC)
6581 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6584 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6585 emitcode ("xrl", "a,%s",
6586 aopGet (AOP (left), offset, FALSE, TRUE));
6588 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6594 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6595 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6596 freeAsmop (result, NULL, ic, TRUE);
6599 /*-----------------------------------------------------------------*/
6600 /* genInline - write the inline code out */
6601 /*-----------------------------------------------------------------*/
6603 genInline (iCode * ic)
6605 char *buffer, *bp, *bp1;
6607 D(emitcode ("; genInline",""));
6609 _G.inLine += (!options.asmpeep);
6611 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6612 strcpy (buffer, IC_INLINE (ic));
6614 /* emit each line as a code */
6625 /* Add \n for labels, not dirs such as c:\mydir */
6626 if ( (*bp == ':') && (isspace(bp[1])) )
6640 /* emitcode("",buffer); */
6641 _G.inLine -= (!options.asmpeep);
6644 /*-----------------------------------------------------------------*/
6645 /* genRRC - rotate right with carry */
6646 /*-----------------------------------------------------------------*/
6650 operand *left, *result;
6651 int size, offset = 0;
6654 D(emitcode ("; genRRC",""));
6656 /* rotate right with carry */
6657 left = IC_LEFT (ic);
6658 result = IC_RESULT (ic);
6659 aopOp (left, ic, FALSE);
6660 aopOp (result, ic, FALSE);
6662 /* move it to the result */
6663 size = AOP_SIZE (result);
6665 if (size == 1) { /* special case for 1 byte */
6666 l = aopGet (AOP (left), offset, FALSE, FALSE);
6668 emitcode ("rr", "a");
6671 /* no need to clear carry, bit7 will be written later */
6674 l = aopGet (AOP (left), offset, FALSE, FALSE);
6676 emitcode ("rrc", "a");
6677 if (AOP_SIZE (result) > 1)
6678 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6680 /* now we need to put the carry into the
6681 highest order byte of the result */
6682 if (AOP_SIZE (result) > 1)
6684 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6687 emitcode ("mov", "acc.7,c");
6689 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6690 freeAsmop (left, NULL, ic, TRUE);
6691 freeAsmop (result, NULL, ic, TRUE);
6694 /*-----------------------------------------------------------------*/
6695 /* genRLC - generate code for rotate left with carry */
6696 /*-----------------------------------------------------------------*/
6700 operand *left, *result;
6701 int size, offset = 0;
6704 D(emitcode ("; genRLC",""));
6706 /* rotate right with carry */
6707 left = IC_LEFT (ic);
6708 result = IC_RESULT (ic);
6709 aopOp (left, ic, FALSE);
6710 aopOp (result, ic, FALSE);
6712 /* move it to the result */
6713 size = AOP_SIZE (result);
6717 l = aopGet (AOP (left), offset, FALSE, FALSE);
6719 if (size == 0) { /* special case for 1 byte */
6723 emitcode("rlc","a"); /* bit0 will be written later */
6724 if (AOP_SIZE (result) > 1)
6725 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6728 l = aopGet (AOP (left), offset, FALSE, FALSE);
6730 emitcode ("rlc", "a");
6731 if (AOP_SIZE (result) > 1)
6732 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6735 /* now we need to put the carry into the
6736 highest order byte of the result */
6737 if (AOP_SIZE (result) > 1)
6739 l = aopGet (AOP (result), 0, FALSE, FALSE);
6742 emitcode ("mov", "acc.0,c");
6744 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6745 freeAsmop (left, NULL, ic, TRUE);
6746 freeAsmop (result, NULL, ic, TRUE);
6749 /*-----------------------------------------------------------------*/
6750 /* genGetHbit - generates code get highest order bit */
6751 /*-----------------------------------------------------------------*/
6753 genGetHbit (iCode * ic)
6755 operand *left, *result;
6757 D(emitcode ("; genGetHbit",""));
6759 left = IC_LEFT (ic);
6760 result = IC_RESULT (ic);
6761 aopOp (left, ic, FALSE);
6762 aopOp (result, ic, FALSE);
6764 /* get the highest order byte into a */
6765 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6766 if (AOP_TYPE (result) == AOP_CRY)
6768 emitcode ("rlc", "a");
6773 emitcode ("rl", "a");
6774 emitcode ("anl", "a,#0x01");
6779 freeAsmop (left, NULL, ic, TRUE);
6780 freeAsmop (result, NULL, ic, TRUE);
6783 /*-----------------------------------------------------------------*/
6784 /* genSwap - generates code to swap nibbles or bytes */
6785 /*-----------------------------------------------------------------*/
6787 genSwap (iCode * ic)
6789 operand *left, *result;
6791 D(emitcode ("; genSwap",""));
6793 left = IC_LEFT (ic);
6794 result = IC_RESULT (ic);
6795 aopOp (left, ic, FALSE);
6796 aopOp (result, ic, FALSE);
6798 switch (AOP_SIZE (left))
6800 case 1: /* swap nibbles in byte */
6801 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6802 emitcode ("swap", "a");
6803 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6805 case 2: /* swap bytes in word */
6806 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6808 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6809 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6810 0, isOperandVolatile (result, FALSE));
6811 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6813 else if (operandsEqu (left, result))
6816 bool pushedB = FALSE, leftInB = FALSE;
6818 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6819 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6822 emitcode ("mov", "b,a");
6826 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6827 0, isOperandVolatile (result, FALSE));
6828 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6835 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6836 0, isOperandVolatile (result, FALSE));
6837 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6838 1, isOperandVolatile (result, FALSE));
6842 wassertl(FALSE, "unsupported SWAP operand size");
6845 freeAsmop (left, NULL, ic, TRUE);
6846 freeAsmop (result, NULL, ic, TRUE);
6850 /*-----------------------------------------------------------------*/
6851 /* AccRol - rotate left accumulator by known count */
6852 /*-----------------------------------------------------------------*/
6854 AccRol (int shCount)
6856 shCount &= 0x0007; // shCount : 0..7
6863 emitcode ("rl", "a");
6866 emitcode ("rl", "a");
6867 emitcode ("rl", "a");
6870 emitcode ("swap", "a");
6871 emitcode ("rr", "a");
6874 emitcode ("swap", "a");
6877 emitcode ("swap", "a");
6878 emitcode ("rl", "a");
6881 emitcode ("rr", "a");
6882 emitcode ("rr", "a");
6885 emitcode ("rr", "a");
6890 /*-----------------------------------------------------------------*/
6891 /* AccLsh - left shift accumulator by known count */
6892 /*-----------------------------------------------------------------*/
6894 AccLsh (int shCount)
6899 emitcode ("add", "a,acc");
6900 else if (shCount == 2)
6902 emitcode ("add", "a,acc");
6903 emitcode ("add", "a,acc");
6907 /* rotate left accumulator */
6909 /* and kill the lower order bits */
6910 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6915 /*-----------------------------------------------------------------*/
6916 /* AccRsh - right shift accumulator by known count */
6917 /*-----------------------------------------------------------------*/
6919 AccRsh (int shCount)
6926 emitcode ("rrc", "a");
6930 /* rotate right accumulator */
6931 AccRol (8 - shCount);
6932 /* and kill the higher order bits */
6933 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6938 /*-----------------------------------------------------------------*/
6939 /* AccSRsh - signed right shift accumulator by known count */
6940 /*-----------------------------------------------------------------*/
6942 AccSRsh (int shCount)
6949 emitcode ("mov", "c,acc.7");
6950 emitcode ("rrc", "a");
6952 else if (shCount == 2)
6954 emitcode ("mov", "c,acc.7");
6955 emitcode ("rrc", "a");
6956 emitcode ("mov", "c,acc.7");
6957 emitcode ("rrc", "a");
6961 tlbl = newiTempLabel (NULL);
6962 /* rotate right accumulator */
6963 AccRol (8 - shCount);
6964 /* and kill the higher order bits */
6965 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6966 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6967 emitcode ("orl", "a,#0x%02x",
6968 (unsigned char) ~SRMask[shCount]);
6969 emitcode ("", "%05d$:", tlbl->key + 100);
6974 /*-----------------------------------------------------------------*/
6975 /* shiftR1Left2Result - shift right one byte from left to result */
6976 /*-----------------------------------------------------------------*/
6978 shiftR1Left2Result (operand * left, int offl,
6979 operand * result, int offr,
6980 int shCount, int sign)
6982 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6983 /* shift right accumulator */
6988 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6991 /*-----------------------------------------------------------------*/
6992 /* shiftL1Left2Result - shift left one byte from left to result */
6993 /*-----------------------------------------------------------------*/
6995 shiftL1Left2Result (operand * left, int offl,
6996 operand * result, int offr, int shCount)
6999 l = aopGet (AOP (left), offl, FALSE, FALSE);
7001 /* shift left accumulator */
7003 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7006 /*-----------------------------------------------------------------*/
7007 /* movLeft2Result - move byte from left to result */
7008 /*-----------------------------------------------------------------*/
7010 movLeft2Result (operand * left, int offl,
7011 operand * result, int offr, int sign)
7014 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7016 l = aopGet (AOP (left), offl, FALSE, FALSE);
7018 if (*l == '@' && (IS_AOP_PREG (result)))
7020 emitcode ("mov", "a,%s", l);
7021 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7026 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
7029 /* MSB sign in acc.7 ! */
7030 if (getDataSize (left) == offl + 1)
7032 emitcode ("mov", "a,%s", l);
7033 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7040 /*-----------------------------------------------------------------*/
7041 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7042 /*-----------------------------------------------------------------*/
7046 emitcode ("rrc", "a");
7047 emitcode ("xch", "a,%s", x);
7048 emitcode ("rrc", "a");
7049 emitcode ("xch", "a,%s", x);
7052 /*-----------------------------------------------------------------*/
7053 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7054 /*-----------------------------------------------------------------*/
7058 emitcode ("xch", "a,%s", x);
7059 emitcode ("rlc", "a");
7060 emitcode ("xch", "a,%s", x);
7061 emitcode ("rlc", "a");
7064 /*-----------------------------------------------------------------*/
7065 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7066 /*-----------------------------------------------------------------*/
7070 emitcode ("xch", "a,%s", x);
7071 emitcode ("add", "a,acc");
7072 emitcode ("xch", "a,%s", x);
7073 emitcode ("rlc", "a");
7076 /*-----------------------------------------------------------------*/
7077 /* AccAXLsh - left shift a:x by known count (0..7) */
7078 /*-----------------------------------------------------------------*/
7080 AccAXLsh (char *x, int shCount)
7095 case 5: // AAAAABBB:CCCCCDDD
7097 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7099 emitcode ("anl", "a,#0x%02x",
7100 SLMask[shCount]); // BBB00000:CCCCCDDD
7102 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7104 AccRol (shCount); // DDDCCCCC:BBB00000
7106 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7108 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7110 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7112 emitcode ("anl", "a,#0x%02x",
7113 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7115 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7117 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7120 case 6: // AAAAAABB:CCCCCCDD
7121 emitcode ("anl", "a,#0x%02x",
7122 SRMask[shCount]); // 000000BB:CCCCCCDD
7123 emitcode ("mov", "c,acc.0"); // c = B
7124 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7126 AccAXRrl1 (x); // BCCCCCCD:D000000B
7127 AccAXRrl1 (x); // BBCCCCCC:DD000000
7129 emitcode("rrc","a");
7130 emitcode("xch","a,%s", x);
7131 emitcode("rrc","a");
7132 emitcode("mov","c,acc.0"); //<< get correct bit
7133 emitcode("xch","a,%s", x);
7135 emitcode("rrc","a");
7136 emitcode("xch","a,%s", x);
7137 emitcode("rrc","a");
7138 emitcode("xch","a,%s", x);
7141 case 7: // a:x <<= 7
7143 emitcode ("anl", "a,#0x%02x",
7144 SRMask[shCount]); // 0000000B:CCCCCCCD
7146 emitcode ("mov", "c,acc.0"); // c = B
7148 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7150 AccAXRrl1 (x); // BCCCCCCC:D0000000
7158 /*-----------------------------------------------------------------*/
7159 /* AccAXRsh - right shift a:x known count (0..7) */
7160 /*-----------------------------------------------------------------*/
7162 AccAXRsh (char *x, int shCount)
7170 AccAXRrl1 (x); // 0->a:x
7175 AccAXRrl1 (x); // 0->a:x
7178 AccAXRrl1 (x); // 0->a:x
7183 case 5: // AAAAABBB:CCCCCDDD = a:x
7185 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7187 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7189 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7191 emitcode ("anl", "a,#0x%02x",
7192 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7194 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7196 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7198 emitcode ("anl", "a,#0x%02x",
7199 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7201 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7203 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7205 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7208 case 6: // AABBBBBB:CCDDDDDD
7210 emitcode ("mov", "c,acc.7");
7211 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7213 emitcode ("mov", "c,acc.7");
7214 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7216 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7218 emitcode ("anl", "a,#0x%02x",
7219 SRMask[shCount]); // 000000AA:BBBBBBCC
7222 case 7: // ABBBBBBB:CDDDDDDD
7224 emitcode ("mov", "c,acc.7"); // c = A
7226 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7228 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7230 emitcode ("anl", "a,#0x%02x",
7231 SRMask[shCount]); // 0000000A:BBBBBBBC
7239 /*-----------------------------------------------------------------*/
7240 /* AccAXRshS - right shift signed a:x known count (0..7) */
7241 /*-----------------------------------------------------------------*/
7243 AccAXRshS (char *x, int shCount)
7251 emitcode ("mov", "c,acc.7");
7252 AccAXRrl1 (x); // s->a:x
7256 emitcode ("mov", "c,acc.7");
7257 AccAXRrl1 (x); // s->a:x
7259 emitcode ("mov", "c,acc.7");
7260 AccAXRrl1 (x); // s->a:x
7265 case 5: // AAAAABBB:CCCCCDDD = a:x
7267 tlbl = newiTempLabel (NULL);
7268 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7270 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7272 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7274 emitcode ("anl", "a,#0x%02x",
7275 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7277 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7279 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7281 emitcode ("anl", "a,#0x%02x",
7282 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7284 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7286 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7288 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7290 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7291 emitcode ("orl", "a,#0x%02x",
7292 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7294 emitcode ("", "%05d$:", tlbl->key + 100);
7295 break; // SSSSAAAA:BBBCCCCC
7297 case 6: // AABBBBBB:CCDDDDDD
7299 tlbl = newiTempLabel (NULL);
7300 emitcode ("mov", "c,acc.7");
7301 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7303 emitcode ("mov", "c,acc.7");
7304 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7306 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7308 emitcode ("anl", "a,#0x%02x",
7309 SRMask[shCount]); // 000000AA:BBBBBBCC
7311 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7312 emitcode ("orl", "a,#0x%02x",
7313 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7315 emitcode ("", "%05d$:", tlbl->key + 100);
7317 case 7: // ABBBBBBB:CDDDDDDD
7319 tlbl = newiTempLabel (NULL);
7320 emitcode ("mov", "c,acc.7"); // c = A
7322 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7324 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7326 emitcode ("anl", "a,#0x%02x",
7327 SRMask[shCount]); // 0000000A:BBBBBBBC
7329 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7330 emitcode ("orl", "a,#0x%02x",
7331 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7333 emitcode ("", "%05d$:", tlbl->key + 100);
7340 /*-----------------------------------------------------------------*/
7341 /* shiftL2Left2Result - shift left two bytes from left to result */
7342 /*-----------------------------------------------------------------*/
7344 shiftL2Left2Result (operand * left, int offl,
7345 operand * result, int offr, int shCount)
7347 if (sameRegs (AOP (result), AOP (left)) &&
7348 ((offl + MSB16) == offr))
7350 /* don't crash result[offr] */
7351 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7352 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7356 movLeft2Result (left, offl, result, offr, 0);
7357 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7359 /* ax << shCount (x = lsb(result)) */
7360 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7361 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7365 /*-----------------------------------------------------------------*/
7366 /* shiftR2Left2Result - shift right two bytes from left to result */
7367 /*-----------------------------------------------------------------*/
7369 shiftR2Left2Result (operand * left, int offl,
7370 operand * result, int offr,
7371 int shCount, int sign)
7373 if (sameRegs (AOP (result), AOP (left)) &&
7374 ((offl + MSB16) == offr))
7376 /* don't crash result[offr] */
7377 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7378 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7382 movLeft2Result (left, offl, result, offr, 0);
7383 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7385 /* a:x >> shCount (x = lsb(result)) */
7387 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7389 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7390 if (getDataSize (result) > 1)
7391 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7394 /*-----------------------------------------------------------------*/
7395 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7396 /*-----------------------------------------------------------------*/
7398 shiftLLeftOrResult (operand * left, int offl,
7399 operand * result, int offr, int shCount)
7401 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7402 /* shift left accumulator */
7404 /* or with result */
7405 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7406 /* back to result */
7407 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7410 /*-----------------------------------------------------------------*/
7411 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7412 /*-----------------------------------------------------------------*/
7414 shiftRLeftOrResult (operand * left, int offl,
7415 operand * result, int offr, int shCount)
7417 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7418 /* shift right accumulator */
7420 /* or with result */
7421 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7422 /* back to result */
7423 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7426 /*-----------------------------------------------------------------*/
7427 /* genlshOne - left shift a one byte quantity by known count */
7428 /*-----------------------------------------------------------------*/
7430 genlshOne (operand * result, operand * left, int shCount)
7432 D(emitcode ("; genlshOne",""));
7434 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7437 /*-----------------------------------------------------------------*/
7438 /* genlshTwo - left shift two bytes by known amount != 0 */
7439 /*-----------------------------------------------------------------*/
7441 genlshTwo (operand * result, operand * left, int shCount)
7445 D(emitcode ("; genlshTwo",""));
7447 size = getDataSize (result);
7449 /* if shCount >= 8 */
7457 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7459 movLeft2Result (left, LSB, result, MSB16, 0);
7461 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7464 /* 1 <= shCount <= 7 */
7468 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7470 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7474 /*-----------------------------------------------------------------*/
7475 /* shiftLLong - shift left one long from left to result */
7476 /* offl = LSB or MSB16 */
7477 /*-----------------------------------------------------------------*/
7479 shiftLLong (operand * left, operand * result, int offr)
7482 int size = AOP_SIZE (result);
7484 if (size >= LSB + offr)
7486 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7488 emitcode ("add", "a,acc");
7489 if (sameRegs (AOP (left), AOP (result)) &&
7490 size >= MSB16 + offr && offr != LSB)
7491 emitcode ("xch", "a,%s",
7492 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7494 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7497 if (size >= MSB16 + offr)
7499 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7501 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7504 emitcode ("rlc", "a");
7505 if (sameRegs (AOP (left), AOP (result)) &&
7506 size >= MSB24 + offr && offr != LSB)
7507 emitcode ("xch", "a,%s",
7508 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7510 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7513 if (size >= MSB24 + offr)
7515 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7517 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7520 emitcode ("rlc", "a");
7521 if (sameRegs (AOP (left), AOP (result)) &&
7522 size >= MSB32 + offr && offr != LSB)
7523 emitcode ("xch", "a,%s",
7524 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7526 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7529 if (size > MSB32 + offr)
7531 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7533 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7536 emitcode ("rlc", "a");
7537 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7540 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7543 /*-----------------------------------------------------------------*/
7544 /* genlshFour - shift four byte by a known amount != 0 */
7545 /*-----------------------------------------------------------------*/
7547 genlshFour (operand * result, operand * left, int shCount)
7551 D(emitcode ("; genlshFour",""));
7553 size = AOP_SIZE (result);
7555 /* if shifting more that 3 bytes */
7560 /* lowest order of left goes to the highest
7561 order of the destination */
7562 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7564 movLeft2Result (left, LSB, result, MSB32, 0);
7565 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7566 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7567 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7571 /* more than two bytes */
7572 else if (shCount >= 16)
7574 /* lower order two bytes goes to higher order two bytes */
7576 /* if some more remaining */
7578 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7581 movLeft2Result (left, MSB16, result, MSB32, 0);
7582 movLeft2Result (left, LSB, result, MSB24, 0);
7584 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7585 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7589 /* if more than 1 byte */
7590 else if (shCount >= 8)
7592 /* lower order three bytes goes to higher order three bytes */
7597 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7599 movLeft2Result (left, LSB, result, MSB16, 0);
7605 movLeft2Result (left, MSB24, result, MSB32, 0);
7606 movLeft2Result (left, MSB16, result, MSB24, 0);
7607 movLeft2Result (left, LSB, result, MSB16, 0);
7608 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7610 else if (shCount == 1)
7611 shiftLLong (left, result, MSB16);
7614 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7615 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7616 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7617 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7622 /* 1 <= shCount <= 7 */
7623 else if (shCount <= 2)
7625 shiftLLong (left, result, LSB);
7627 shiftLLong (result, result, LSB);
7629 /* 3 <= shCount <= 7, optimize */
7632 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7633 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7634 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7638 /*-----------------------------------------------------------------*/
7639 /* genLeftShiftLiteral - left shifting by known count */
7640 /*-----------------------------------------------------------------*/
7642 genLeftShiftLiteral (operand * left,
7647 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7650 D(emitcode ("; genLeftShiftLiteral",""));
7652 freeAsmop (right, NULL, ic, TRUE);
7654 aopOp (left, ic, FALSE);
7655 aopOp (result, ic, FALSE);
7657 size = getSize (operandType (result));
7660 emitcode ("; shift left ", "result %d, left %d", size,
7664 /* I suppose that the left size >= result size */
7669 movLeft2Result (left, size, result, size, 0);
7673 else if (shCount >= (size * 8))
7675 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7681 genlshOne (result, left, shCount);
7685 genlshTwo (result, left, shCount);
7689 genlshFour (result, left, shCount);
7692 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7693 "*** ack! mystery literal shift!\n");
7697 freeAsmop (left, NULL, ic, TRUE);
7698 freeAsmop (result, NULL, ic, TRUE);
7701 /*-----------------------------------------------------------------*/
7702 /* genLeftShift - generates code for left shifting */
7703 /*-----------------------------------------------------------------*/
7705 genLeftShift (iCode * ic)
7707 operand *left, *right, *result;
7710 symbol *tlbl, *tlbl1;
7713 D(emitcode ("; genLeftShift",""));
7715 right = IC_RIGHT (ic);
7716 left = IC_LEFT (ic);
7717 result = IC_RESULT (ic);
7719 aopOp (right, ic, FALSE);
7721 /* if the shift count is known then do it
7722 as efficiently as possible */
7723 if (AOP_TYPE (right) == AOP_LIT)
7725 genLeftShiftLiteral (left, right, result, ic);
7729 /* shift count is unknown then we have to form
7730 a loop get the loop count in B : Note: we take
7731 only the lower order byte since shifting
7732 more that 32 bits make no sense anyway, ( the
7733 largest size of an object can be only 32 bits ) */
7736 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7737 emitcode ("inc", "b");
7738 freeAsmop (right, NULL, ic, TRUE);
7739 aopOp (left, ic, FALSE);
7740 aopOp (result, ic, FALSE);
7742 /* now move the left to the result if they are not the same */
7743 if (!sameRegs (AOP (left), AOP (result)) &&
7744 AOP_SIZE (result) > 1)
7747 size = AOP_SIZE (result);
7751 l = aopGet (AOP (left), offset, FALSE, TRUE);
7752 if (*l == '@' && (IS_AOP_PREG (result)))
7755 emitcode ("mov", "a,%s", l);
7756 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7759 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7764 tlbl = newiTempLabel (NULL);
7765 size = AOP_SIZE (result);
7767 tlbl1 = newiTempLabel (NULL);
7769 /* if it is only one byte then */
7772 symbol *tlbl1 = newiTempLabel (NULL);
7774 l = aopGet (AOP (left), 0, FALSE, FALSE);
7776 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7777 emitcode ("", "%05d$:", tlbl->key + 100);
7778 emitcode ("add", "a,acc");
7779 emitcode ("", "%05d$:", tlbl1->key + 100);
7780 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7782 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7786 reAdjustPreg (AOP (result));
7788 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7789 emitcode ("", "%05d$:", tlbl->key + 100);
7790 l = aopGet (AOP (result), offset, FALSE, FALSE);
7792 emitcode ("add", "a,acc");
7793 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7796 l = aopGet (AOP (result), offset, FALSE, FALSE);
7798 emitcode ("rlc", "a");
7799 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7801 reAdjustPreg (AOP (result));
7803 emitcode ("", "%05d$:", tlbl1->key + 100);
7804 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7807 freeAsmop (left, NULL, ic, TRUE);
7808 freeAsmop (result, NULL, ic, TRUE);
7811 /*-----------------------------------------------------------------*/
7812 /* genrshOne - right shift a one byte quantity by known count */
7813 /*-----------------------------------------------------------------*/
7815 genrshOne (operand * result, operand * left,
7816 int shCount, int sign)
7818 D(emitcode ("; genrshOne",""));
7820 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7823 /*-----------------------------------------------------------------*/
7824 /* genrshTwo - right shift two bytes by known amount != 0 */
7825 /*-----------------------------------------------------------------*/
7827 genrshTwo (operand * result, operand * left,
7828 int shCount, int sign)
7830 D(emitcode ("; genrshTwo",""));
7832 /* if shCount >= 8 */
7837 shiftR1Left2Result (left, MSB16, result, LSB,
7840 movLeft2Result (left, MSB16, result, LSB, sign);
7841 addSign (result, MSB16, sign);
7844 /* 1 <= shCount <= 7 */
7846 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7849 /*-----------------------------------------------------------------*/
7850 /* shiftRLong - shift right one long from left to result */
7851 /* offl = LSB or MSB16 */
7852 /*-----------------------------------------------------------------*/
7854 shiftRLong (operand * left, int offl,
7855 operand * result, int sign)
7857 int isSameRegs=sameRegs(AOP(left),AOP(result));
7859 if (isSameRegs && offl>1) {
7860 // we are in big trouble, but this shouldn't happen
7861 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7864 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7869 emitcode ("rlc", "a");
7870 emitcode ("subb", "a,acc");
7872 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7874 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7875 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7878 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7883 emitcode ("clr", "c");
7885 emitcode ("mov", "c,acc.7");
7888 emitcode ("rrc", "a");
7890 if (isSameRegs && offl==MSB16) {
7891 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7893 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7894 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7897 emitcode ("rrc", "a");
7898 if (isSameRegs && offl==1) {
7899 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7901 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7902 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7904 emitcode ("rrc", "a");
7905 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7909 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7910 emitcode ("rrc", "a");
7911 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7915 /*-----------------------------------------------------------------*/
7916 /* genrshFour - shift four byte by a known amount != 0 */
7917 /*-----------------------------------------------------------------*/
7919 genrshFour (operand * result, operand * left,
7920 int shCount, int sign)
7922 D(emitcode ("; genrshFour",""));
7924 /* if shifting more that 3 bytes */
7929 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7931 movLeft2Result (left, MSB32, result, LSB, sign);
7932 addSign (result, MSB16, sign);
7934 else if (shCount >= 16)
7938 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7941 movLeft2Result (left, MSB24, result, LSB, 0);
7942 movLeft2Result (left, MSB32, result, MSB16, sign);
7944 addSign (result, MSB24, sign);
7946 else if (shCount >= 8)
7950 shiftRLong (left, MSB16, result, sign);
7951 else if (shCount == 0)
7953 movLeft2Result (left, MSB16, result, LSB, 0);
7954 movLeft2Result (left, MSB24, result, MSB16, 0);
7955 movLeft2Result (left, MSB32, result, MSB24, sign);
7956 addSign (result, MSB32, sign);
7960 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7961 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7962 /* the last shift is signed */
7963 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7964 addSign (result, MSB32, sign);
7968 { /* 1 <= shCount <= 7 */
7971 shiftRLong (left, LSB, result, sign);
7973 shiftRLong (result, LSB, result, sign);
7977 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7978 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7979 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7984 /*-----------------------------------------------------------------*/
7985 /* genRightShiftLiteral - right shifting by known count */
7986 /*-----------------------------------------------------------------*/
7988 genRightShiftLiteral (operand * left,
7994 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7997 D(emitcode ("; genRightShiftLiteral",""));
7999 freeAsmop (right, NULL, ic, TRUE);
8001 aopOp (left, ic, FALSE);
8002 aopOp (result, ic, FALSE);
8005 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8009 size = getDataSize (left);
8010 /* test the LEFT size !!! */
8012 /* I suppose that the left size >= result size */
8015 size = getDataSize (result);
8017 movLeft2Result (left, size, result, size, 0);
8020 else if (shCount >= (size * 8))
8023 /* get sign in acc.7 */
8024 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
8026 addSign (result, LSB, sign);
8033 genrshOne (result, left, shCount, sign);
8037 genrshTwo (result, left, shCount, sign);
8041 genrshFour (result, left, shCount, sign);
8047 freeAsmop (left, NULL, ic, TRUE);
8048 freeAsmop (result, NULL, ic, TRUE);
8051 /*-----------------------------------------------------------------*/
8052 /* genSignedRightShift - right shift of signed number */
8053 /*-----------------------------------------------------------------*/
8055 genSignedRightShift (iCode * ic)
8057 operand *right, *left, *result;
8060 symbol *tlbl, *tlbl1;
8063 D(emitcode ("; genSignedRightShift",""));
8065 /* we do it the hard way put the shift count in b
8066 and loop thru preserving the sign */
8068 right = IC_RIGHT (ic);
8069 left = IC_LEFT (ic);
8070 result = IC_RESULT (ic);
8072 aopOp (right, ic, FALSE);
8075 if (AOP_TYPE (right) == AOP_LIT)
8077 genRightShiftLiteral (left, right, result, ic, 1);
8080 /* shift count is unknown then we have to form
8081 a loop get the loop count in B : Note: we take
8082 only the lower order byte since shifting
8083 more that 32 bits make no sense anyway, ( the
8084 largest size of an object can be only 32 bits ) */
8087 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8088 emitcode ("inc", "b");
8089 freeAsmop (right, NULL, ic, TRUE);
8090 aopOp (left, ic, FALSE);
8091 aopOp (result, ic, FALSE);
8093 /* now move the left to the result if they are not the
8095 if (!sameRegs (AOP (left), AOP (result)) &&
8096 AOP_SIZE (result) > 1)
8099 size = AOP_SIZE (result);
8103 l = aopGet (AOP (left), offset, FALSE, TRUE);
8104 if (*l == '@' && IS_AOP_PREG (result))
8107 emitcode ("mov", "a,%s", l);
8108 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8111 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8116 /* mov the highest order bit to OVR */
8117 tlbl = newiTempLabel (NULL);
8118 tlbl1 = newiTempLabel (NULL);
8120 size = AOP_SIZE (result);
8122 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
8123 emitcode ("rlc", "a");
8124 emitcode ("mov", "ov,c");
8125 /* if it is only one byte then */
8128 l = aopGet (AOP (left), 0, FALSE, FALSE);
8130 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8131 emitcode ("", "%05d$:", tlbl->key + 100);
8132 emitcode ("mov", "c,ov");
8133 emitcode ("rrc", "a");
8134 emitcode ("", "%05d$:", tlbl1->key + 100);
8135 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8137 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8141 reAdjustPreg (AOP (result));
8142 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8143 emitcode ("", "%05d$:", tlbl->key + 100);
8144 emitcode ("mov", "c,ov");
8147 l = aopGet (AOP (result), offset, FALSE, FALSE);
8149 emitcode ("rrc", "a");
8150 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8152 reAdjustPreg (AOP (result));
8153 emitcode ("", "%05d$:", tlbl1->key + 100);
8154 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8158 freeAsmop (left, NULL, ic, TRUE);
8159 freeAsmop (result, NULL, ic, TRUE);
8162 /*-----------------------------------------------------------------*/
8163 /* genRightShift - generate code for right shifting */
8164 /*-----------------------------------------------------------------*/
8166 genRightShift (iCode * ic)
8168 operand *right, *left, *result;
8172 symbol *tlbl, *tlbl1;
8175 D(emitcode ("; genRightShift",""));
8177 /* if signed then we do it the hard way preserve the
8178 sign bit moving it inwards */
8179 letype = getSpec (operandType (IC_LEFT (ic)));
8181 if (!SPEC_USIGN (letype))
8183 genSignedRightShift (ic);
8187 /* signed & unsigned types are treated the same : i.e. the
8188 signed is NOT propagated inwards : quoting from the
8189 ANSI - standard : "for E1 >> E2, is equivalent to division
8190 by 2**E2 if unsigned or if it has a non-negative value,
8191 otherwise the result is implementation defined ", MY definition
8192 is that the sign does not get propagated */
8194 right = IC_RIGHT (ic);
8195 left = IC_LEFT (ic);
8196 result = IC_RESULT (ic);
8198 aopOp (right, ic, FALSE);
8200 /* if the shift count is known then do it
8201 as efficiently as possible */
8202 if (AOP_TYPE (right) == AOP_LIT)
8204 genRightShiftLiteral (left, right, result, ic, 0);
8208 /* shift count is unknown then we have to form
8209 a loop get the loop count in B : Note: we take
8210 only the lower order byte since shifting
8211 more that 32 bits make no sense anyway, ( the
8212 largest size of an object can be only 32 bits ) */
8215 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8216 emitcode ("inc", "b");
8217 freeAsmop (right, NULL, ic, TRUE);
8218 aopOp (left, ic, FALSE);
8219 aopOp (result, ic, FALSE);
8221 /* now move the left to the result if they are not the
8223 if (!sameRegs (AOP (left), AOP (result)) &&
8224 AOP_SIZE (result) > 1)
8227 size = AOP_SIZE (result);
8231 l = aopGet (AOP (left), offset, FALSE, TRUE);
8232 if (*l == '@' && IS_AOP_PREG (result))
8235 emitcode ("mov", "a,%s", l);
8236 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8239 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8244 tlbl = newiTempLabel (NULL);
8245 tlbl1 = newiTempLabel (NULL);
8246 size = AOP_SIZE (result);
8249 /* if it is only one byte then */
8252 l = aopGet (AOP (left), 0, FALSE, FALSE);
8254 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8255 emitcode ("", "%05d$:", tlbl->key + 100);
8257 emitcode ("rrc", "a");
8258 emitcode ("", "%05d$:", tlbl1->key + 100);
8259 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8261 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8265 reAdjustPreg (AOP (result));
8266 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8267 emitcode ("", "%05d$:", tlbl->key + 100);
8271 l = aopGet (AOP (result), offset, FALSE, FALSE);
8273 emitcode ("rrc", "a");
8274 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8276 reAdjustPreg (AOP (result));
8278 emitcode ("", "%05d$:", tlbl1->key + 100);
8279 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8283 freeAsmop (left, NULL, ic, TRUE);
8284 freeAsmop (result, NULL, ic, TRUE);
8287 /*-----------------------------------------------------------------*/
8288 /* emitPtrByteGet - emits code to get a byte into A through a */
8289 /* pointer register (R0, R1, or DPTR). The */
8290 /* original value of A can be preserved in B. */
8291 /*-----------------------------------------------------------------*/
8293 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8300 emitcode ("mov", "b,a");
8301 emitcode ("mov", "a,@%s", rname);
8306 emitcode ("mov", "b,a");
8307 emitcode ("movx", "a,@%s", rname);
8312 emitcode ("mov", "b,a");
8313 emitcode ("movx", "a,@dptr");
8318 emitcode ("mov", "b,a");
8319 emitcode ("clr", "a");
8320 emitcode ("movc", "a,@a+dptr");
8326 emitcode ("push", "b");
8327 emitcode ("push", "acc");
8329 emitcode ("lcall", "__gptrget");
8331 emitcode ("pop", "b");
8336 /*-----------------------------------------------------------------*/
8337 /* emitPtrByteSet - emits code to set a byte from src through a */
8338 /* pointer register (R0, R1, or DPTR). */
8339 /*-----------------------------------------------------------------*/
8341 emitPtrByteSet (char *rname, int p_type, char *src)
8350 emitcode ("mov", "@%s,a", rname);
8353 emitcode ("mov", "@%s,%s", rname, src);
8358 emitcode ("movx", "@%s,a", rname);
8363 emitcode ("movx", "@dptr,a");
8368 emitcode ("lcall", "__gptrput");
8373 /*-----------------------------------------------------------------*/
8374 /* genUnpackBits - generates code for unpacking bits */
8375 /*-----------------------------------------------------------------*/
8377 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8379 int offset = 0; /* result byte offset */
8380 int rsize; /* result size */
8381 int rlen = 0; /* remaining bitfield length */
8382 sym_link *etype; /* bitfield type information */
8383 int blen; /* bitfield length */
8384 int bstr; /* bitfield starting bit within byte */
8387 D(emitcode ("; genUnpackBits",""));
8389 etype = getSpec (operandType (result));
8390 rsize = getSize (operandType (result));
8391 blen = SPEC_BLEN (etype);
8392 bstr = SPEC_BSTR (etype);
8394 if (ifx && blen <= 8)
8396 emitPtrByteGet (rname, ptype, FALSE);
8399 SNPRINTF (buffer, sizeof(buffer),
8401 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8406 emitcode ("anl", "a,#0x%02x",
8407 (((unsigned char) -1) >> (8 - blen)) << bstr);
8408 genIfxJump (ifx, "a", NULL, NULL, NULL);
8414 /* If the bitfield length is less than a byte */
8417 emitPtrByteGet (rname, ptype, FALSE);
8419 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8420 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8424 /* Bit field did not fit in a byte. Copy all
8425 but the partial byte at the end. */
8426 for (rlen=blen;rlen>=8;rlen-=8)
8428 emitPtrByteGet (rname, ptype, FALSE);
8429 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8431 emitcode ("inc", "%s", rname);
8434 /* Handle the partial byte at the end */
8437 emitPtrByteGet (rname, ptype, FALSE);
8438 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8439 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8447 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8452 /*-----------------------------------------------------------------*/
8453 /* genDataPointerGet - generates code when ptr offset is known */
8454 /*-----------------------------------------------------------------*/
8456 genDataPointerGet (operand * left,
8462 int size, offset = 0;
8464 D(emitcode ("; genDataPointerGet",""));
8466 aopOp (result, ic, TRUE);
8468 /* get the string representation of the name */
8469 l = aopGet (AOP (left), 0, FALSE, TRUE);
8470 size = AOP_SIZE (result);
8474 sprintf (buffer, "(%s + %d)", l + 1, offset);
8476 sprintf (buffer, "%s", l + 1);
8477 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8480 freeAsmop (left, NULL, ic, TRUE);
8481 freeAsmop (result, NULL, ic, TRUE);
8484 /*-----------------------------------------------------------------*/
8485 /* genNearPointerGet - emitcode for near pointer fetch */
8486 /*-----------------------------------------------------------------*/
8488 genNearPointerGet (operand * left,
8497 sym_link *rtype, *retype;
8498 sym_link *ltype = operandType (left);
8501 D(emitcode ("; genNearPointerGet",""));
8503 rtype = operandType (result);
8504 retype = getSpec (rtype);
8506 aopOp (left, ic, FALSE);
8508 /* if left is rematerialisable and
8509 result is not bitfield variable type and
8510 the left is pointer to data space i.e
8511 lower 128 bytes of space */
8512 if (AOP_TYPE (left) == AOP_IMMD &&
8513 !IS_BITFIELD (retype) &&
8514 DCL_TYPE (ltype) == POINTER)
8516 genDataPointerGet (left, result, ic);
8520 /* if the value is already in a pointer register
8521 then don't need anything more */
8522 if (!AOP_INPREG (AOP (left)))
8524 if (IS_AOP_PREG (left))
8526 // Aha, it is a pointer, just in disguise.
8527 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8530 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8531 __FILE__, __LINE__);
8536 emitcode ("mov", "a%s,%s", rname + 1, rname);
8537 rname++; // skip the '@'.
8542 /* otherwise get a free pointer register */
8544 preg = getFreePtr (ic, &aop, FALSE);
8545 emitcode ("mov", "%s,%s",
8547 aopGet (AOP (left), 0, FALSE, TRUE));
8552 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8554 //aopOp (result, ic, FALSE);
8555 aopOp (result, ic, result?TRUE:FALSE);
8557 /* if bitfield then unpack the bits */
8558 if (IS_BITFIELD (retype))
8559 genUnpackBits (result, rname, POINTER, ifx);
8562 /* we have can just get the values */
8563 int size = AOP_SIZE (result);
8568 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8571 emitcode ("mov", "a,@%s", rname);
8573 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8577 sprintf (buffer, "@%s", rname);
8578 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8582 emitcode ("inc", "%s", rname);
8586 /* now some housekeeping stuff */
8587 if (aop) /* we had to allocate for this iCode */
8589 if (pi) { /* post increment present */
8590 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8592 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8596 /* we did not allocate which means left
8597 already in a pointer register, then
8598 if size > 0 && this could be used again
8599 we have to point it back to where it
8601 if ((AOP_SIZE (result) > 1 &&
8602 !OP_SYMBOL (left)->remat &&
8603 (OP_SYMBOL (left)->liveTo > ic->seq ||
8607 int size = AOP_SIZE (result) - 1;
8609 emitcode ("dec", "%s", rname);
8613 if (ifx && !ifx->generated)
8615 genIfxJump (ifx, "a", left, NULL, result);
8619 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8620 freeAsmop (left, NULL, ic, TRUE);
8621 if (pi) pi->generated = 1;
8624 /*-----------------------------------------------------------------*/
8625 /* genPagedPointerGet - emitcode for paged pointer fetch */
8626 /*-----------------------------------------------------------------*/
8628 genPagedPointerGet (operand * left,
8637 sym_link *rtype, *retype;
8639 D(emitcode ("; genPagedPointerGet",""));
8641 rtype = operandType (result);
8642 retype = getSpec (rtype);
8644 aopOp (left, ic, FALSE);
8646 /* if the value is already in a pointer register
8647 then don't need anything more */
8648 if (!AOP_INPREG (AOP (left)))
8650 /* otherwise get a free pointer register */
8652 preg = getFreePtr (ic, &aop, FALSE);
8653 emitcode ("mov", "%s,%s",
8655 aopGet (AOP (left), 0, FALSE, TRUE));
8659 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8661 aopOp (result, ic, FALSE);
8663 /* if bitfield then unpack the bits */
8664 if (IS_BITFIELD (retype))
8665 genUnpackBits (result, rname, PPOINTER, ifx);
8668 /* we have can just get the values */
8669 int size = AOP_SIZE (result);
8675 emitcode ("movx", "a,@%s", rname);
8677 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8682 emitcode ("inc", "%s", rname);
8686 /* now some housekeeping stuff */
8687 if (aop) /* we had to allocate for this iCode */
8689 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8690 freeAsmop (NULL, aop, ic, TRUE);
8694 /* we did not allocate which means left
8695 already in a pointer register, then
8696 if size > 0 && this could be used again
8697 we have to point it back to where it
8699 if ((AOP_SIZE (result) > 1 &&
8700 !OP_SYMBOL (left)->remat &&
8701 (OP_SYMBOL (left)->liveTo > ic->seq ||
8705 int size = AOP_SIZE (result) - 1;
8707 emitcode ("dec", "%s", rname);
8711 if (ifx && !ifx->generated)
8713 genIfxJump (ifx, "a", left, NULL, result);
8717 freeAsmop (left, NULL, ic, TRUE);
8718 freeAsmop (result, NULL, ic, TRUE);
8719 if (pi) pi->generated = 1;
8723 /*--------------------------------------------------------------------*/
8724 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8725 /*--------------------------------------------------------------------*/
8727 loadDptrFromOperand (operand *op, bool loadBToo)
8729 if (AOP_TYPE (op) != AOP_STR)
8731 /* if this is rematerializable */
8732 if (AOP_TYPE (op) == AOP_IMMD)
8734 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8737 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8738 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8741 wassertl(FALSE, "need pointerCode");
8742 emitcode ("", "; mov b,???");
8743 /* genPointerGet and genPointerSet originally did different
8744 ** things for this case. Both seem wrong.
8745 ** from genPointerGet:
8746 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8747 ** from genPointerSet:
8748 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8753 else if (AOP_TYPE (op) == AOP_DPTR)
8757 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8758 emitcode ("push", "acc");
8759 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8760 emitcode ("push", "acc");
8761 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8762 emitcode ("pop", "dph");
8763 emitcode ("pop", "dpl");
8767 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8768 emitcode ("push", "acc");
8769 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8770 emitcode ("pop", "dpl");
8774 { /* we need to get it byte by byte */
8775 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8776 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8778 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8783 /*-----------------------------------------------------------------*/
8784 /* genFarPointerGet - gget value from far space */
8785 /*-----------------------------------------------------------------*/
8787 genFarPointerGet (operand * left,
8788 operand * result, iCode * ic, iCode * pi, iCode * ifx)
8791 sym_link *retype = getSpec (operandType (result));
8793 D(emitcode ("; genFarPointerGet",""));
8795 aopOp (left, ic, FALSE);
8796 loadDptrFromOperand (left, FALSE);
8798 /* so dptr now contains the address */
8799 aopOp (result, ic, FALSE);
8801 /* if bit then unpack */
8802 if (IS_BITFIELD (retype))
8803 genUnpackBits (result, "dptr", FPOINTER, ifx);
8806 size = AOP_SIZE (result);
8811 emitcode ("movx", "a,@dptr");
8813 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8815 emitcode ("inc", "dptr");
8819 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8821 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8822 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8826 if (ifx && !ifx->generated)
8828 genIfxJump (ifx, "a", left, NULL, result);
8831 freeAsmop (left, NULL, ic, TRUE);
8832 freeAsmop (result, NULL, ic, TRUE);
8835 /*-----------------------------------------------------------------*/
8836 /* genCodePointerGet - gget value from code space */
8837 /*-----------------------------------------------------------------*/
8839 genCodePointerGet (operand * left,
8840 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8843 sym_link *retype = getSpec (operandType (result));
8845 D(emitcode ("; genCodePointerGet",""));
8847 aopOp (left, ic, FALSE);
8848 loadDptrFromOperand (left, FALSE);
8850 /* so dptr now contains the address */
8851 aopOp (result, ic, FALSE);
8853 /* if bit then unpack */
8854 if (IS_BITFIELD (retype))
8855 genUnpackBits (result, "dptr", CPOINTER, ifx);
8858 size = AOP_SIZE (result);
8865 emitcode ("clr", "a");
8866 emitcode ("movc", "a,@a+dptr");
8868 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8869 emitcode ("inc", "dptr");
8873 emitcode ("mov", "a,#0x%02x", offset);
8874 emitcode ("movc", "a,@a+dptr");
8876 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8881 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8883 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8884 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8888 if (ifx && !ifx->generated)
8890 genIfxJump (ifx, "a", left, NULL, result);
8893 freeAsmop (left, NULL, ic, TRUE);
8894 freeAsmop (result, NULL, ic, TRUE);
8897 /*-----------------------------------------------------------------*/
8898 /* genGenPointerGet - gget value from generic pointer space */
8899 /*-----------------------------------------------------------------*/
8901 genGenPointerGet (operand * left,
8902 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8905 sym_link *retype = getSpec (operandType (result));
8907 D(emitcode ("; genGenPointerGet",""));
8909 aopOp (left, ic, FALSE);
8910 loadDptrFromOperand (left, TRUE);
8912 /* so dptr know contains the address */
8913 aopOp (result, ic, FALSE);
8915 /* if bit then unpack */
8916 if (IS_BITFIELD (retype))
8917 genUnpackBits (result, "dptr", GPOINTER, ifx);
8920 size = AOP_SIZE (result);
8925 emitcode ("lcall", "__gptrget");
8927 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8929 emitcode ("inc", "dptr");
8933 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8935 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8936 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8940 if (ifx && !ifx->generated)
8942 genIfxJump (ifx, "a", left, NULL, result);
8946 freeAsmop (left, NULL, ic, TRUE);
8947 freeAsmop (result, NULL, ic, TRUE);
8950 /*-----------------------------------------------------------------*/
8951 /* genPointerGet - generate code for pointer get */
8952 /*-----------------------------------------------------------------*/
8954 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
8956 operand *left, *result;
8957 sym_link *type, *etype;
8960 D(emitcode ("; genPointerGet",""));
8962 left = IC_LEFT (ic);
8963 result = IC_RESULT (ic);
8965 if (getSize (operandType (result))>1)
8968 /* depending on the type of pointer we need to
8969 move it to the correct pointer register */
8970 type = operandType (left);
8971 etype = getSpec (type);
8972 /* if left is of type of pointer then it is simple */
8973 if (IS_PTR (type) && !IS_FUNC (type->next))
8974 p_type = DCL_TYPE (type);
8977 /* we have to go by the storage class */
8978 p_type = PTR_TYPE (SPEC_OCLS (etype));
8981 /* special case when cast remat */
8982 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8983 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8984 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8985 type = operandType (left);
8986 p_type = DCL_TYPE (type);
8988 /* now that we have the pointer type we assign
8989 the pointer values */
8995 genNearPointerGet (left, result, ic, pi, ifx);
8999 genPagedPointerGet (left, result, ic, pi, ifx);
9003 genFarPointerGet (left, result, ic, pi, ifx);
9007 genCodePointerGet (left, result, ic, pi, ifx);
9011 genGenPointerGet (left, result, ic, pi, ifx);
9019 /*-----------------------------------------------------------------*/
9020 /* genPackBits - generates code for packed bit storage */
9021 /*-----------------------------------------------------------------*/
9023 genPackBits (sym_link * etype,
9025 char *rname, int p_type)
9027 int offset = 0; /* source byte offset */
9028 int rlen = 0; /* remaining bitfield length */
9029 int blen; /* bitfield length */
9030 int bstr; /* bitfield starting bit within byte */
9031 int litval; /* source literal value (if AOP_LIT) */
9032 unsigned char mask; /* bitmask within current byte */
9034 D(emitcode ("; genPackBits",""));
9036 blen = SPEC_BLEN (etype);
9037 bstr = SPEC_BSTR (etype);
9039 /* If the bitfield length is less than a byte */
9042 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9043 (unsigned char) (0xFF >> (8 - bstr)));
9045 if (AOP_TYPE (right) == AOP_LIT)
9047 /* Case with a bitfield length <8 and literal source
9049 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9051 litval &= (~mask) & 0xff;
9052 emitPtrByteGet (rname, p_type, FALSE);
9053 if ((mask|litval)!=0xff)
9054 emitcode ("anl","a,#0x%02x", mask);
9056 emitcode ("orl","a,#0x%02x", litval);
9060 if ((blen==1) && (p_type!=GPOINTER))
9062 /* Case with a bitfield length == 1 and no generic pointer
9064 if (AOP_TYPE (right) == AOP_CRY)
9065 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9068 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9069 emitcode ("rrc","a");
9071 emitPtrByteGet (rname, p_type, FALSE);
9072 emitcode ("mov","acc.%d,c",bstr);
9077 /* Case with a bitfield length < 8 and arbitrary source
9079 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9080 /* shift and mask source value */
9082 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9085 /* transfer A to B and get next byte */
9086 emitPtrByteGet (rname, p_type, TRUE);
9088 emitcode ("anl", "a,#0x%02x", mask);
9089 emitcode ("orl", "a,b");
9090 if (p_type == GPOINTER)
9091 emitcode ("pop", "b");
9097 emitPtrByteSet (rname, p_type, "a");
9101 /* Bit length is greater than 7 bits. In this case, copy */
9102 /* all except the partial byte at the end */
9103 for (rlen=blen;rlen>=8;rlen-=8)
9105 emitPtrByteSet (rname, p_type,
9106 aopGet (AOP (right), offset++, FALSE, TRUE) );
9108 emitcode ("inc", "%s", rname);
9111 /* If there was a partial byte at the end */
9114 mask = (((unsigned char) -1 << rlen) & 0xff);
9116 if (AOP_TYPE (right) == AOP_LIT)
9118 /* Case with partial byte and literal source
9120 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9121 litval >>= (blen-rlen);
9122 litval &= (~mask) & 0xff;
9123 emitPtrByteGet (rname, p_type, FALSE);
9124 if ((mask|litval)!=0xff)
9125 emitcode ("anl","a,#0x%02x", mask);
9127 emitcode ("orl","a,#0x%02x", litval);
9132 /* Case with partial byte and arbitrary source
9134 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9135 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9138 /* transfer A to B and get next byte */
9139 emitPtrByteGet (rname, p_type, TRUE);
9141 emitcode ("anl", "a,#0x%02x", mask);
9142 emitcode ("orl", "a,b");
9143 if (p_type == GPOINTER)
9144 emitcode ("pop", "b");
9148 emitPtrByteSet (rname, p_type, "a");
9154 /*-----------------------------------------------------------------*/
9155 /* genDataPointerSet - remat pointer to data space */
9156 /*-----------------------------------------------------------------*/
9158 genDataPointerSet (operand * right,
9162 int size, offset = 0;
9163 char *l, buffer[256];
9165 D(emitcode ("; genDataPointerSet",""));
9167 aopOp (right, ic, FALSE);
9169 l = aopGet (AOP (result), 0, FALSE, TRUE);
9170 size = AOP_SIZE (right);
9174 sprintf (buffer, "(%s + %d)", l + 1, offset);
9176 sprintf (buffer, "%s", l + 1);
9177 emitcode ("mov", "%s,%s", buffer,
9178 aopGet (AOP (right), offset++, FALSE, FALSE));
9181 freeAsmop (right, NULL, ic, TRUE);
9182 freeAsmop (result, NULL, ic, TRUE);
9185 /*-----------------------------------------------------------------*/
9186 /* genNearPointerSet - emitcode for near pointer put */
9187 /*-----------------------------------------------------------------*/
9189 genNearPointerSet (operand * right,
9197 sym_link *retype, *letype;
9198 sym_link *ptype = operandType (result);
9200 D(emitcode ("; genNearPointerSet",""));
9202 retype = getSpec (operandType (right));
9203 letype = getSpec (ptype);
9204 aopOp (result, ic, FALSE);
9206 /* if the result is rematerializable &
9207 in data space & not a bit variable */
9208 if (AOP_TYPE (result) == AOP_IMMD &&
9209 DCL_TYPE (ptype) == POINTER &&
9210 !IS_BITVAR (retype) &&
9211 !IS_BITVAR (letype))
9213 genDataPointerSet (right, result, ic);
9217 /* if the value is already in a pointer register
9218 then don't need anything more */
9219 if (!AOP_INPREG (AOP (result)))
9222 //AOP_TYPE (result) == AOP_STK
9226 // Aha, it is a pointer, just in disguise.
9227 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9230 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9231 __FILE__, __LINE__);
9236 emitcode ("mov", "a%s,%s", rname + 1, rname);
9237 rname++; // skip the '@'.
9242 /* otherwise get a free pointer register */
9244 preg = getFreePtr (ic, &aop, FALSE);
9245 emitcode ("mov", "%s,%s",
9247 aopGet (AOP (result), 0, FALSE, TRUE));
9253 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9256 aopOp (right, ic, FALSE);
9258 /* if bitfield then unpack the bits */
9259 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9260 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9263 /* we have can just get the values */
9264 int size = AOP_SIZE (right);
9269 l = aopGet (AOP (right), offset, FALSE, TRUE);
9273 emitcode ("mov", "@%s,a", rname);
9276 emitcode ("mov", "@%s,%s", rname, l);
9278 emitcode ("inc", "%s", rname);
9283 /* now some housekeeping stuff */
9284 if (aop) /* we had to allocate for this iCode */
9287 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9288 freeAsmop (NULL, aop, ic, TRUE);
9292 /* we did not allocate which means left
9293 already in a pointer register, then
9294 if size > 0 && this could be used again
9295 we have to point it back to where it
9297 if ((AOP_SIZE (right) > 1 &&
9298 !OP_SYMBOL (result)->remat &&
9299 (OP_SYMBOL (result)->liveTo > ic->seq ||
9303 int size = AOP_SIZE (right) - 1;
9305 emitcode ("dec", "%s", rname);
9310 if (pi) pi->generated = 1;
9311 freeAsmop (result, NULL, ic, TRUE);
9312 freeAsmop (right, NULL, ic, TRUE);
9315 /*-----------------------------------------------------------------*/
9316 /* genPagedPointerSet - emitcode for Paged pointer put */
9317 /*-----------------------------------------------------------------*/
9319 genPagedPointerSet (operand * right,
9327 sym_link *retype, *letype;
9329 D(emitcode ("; genPagedPointerSet",""));
9331 retype = getSpec (operandType (right));
9332 letype = getSpec (operandType (result));
9334 aopOp (result, ic, FALSE);
9336 /* if the value is already in a pointer register
9337 then don't need anything more */
9338 if (!AOP_INPREG (AOP (result)))
9340 /* otherwise get a free pointer register */
9342 preg = getFreePtr (ic, &aop, FALSE);
9343 emitcode ("mov", "%s,%s",
9345 aopGet (AOP (result), 0, FALSE, TRUE));
9349 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9351 aopOp (right, ic, FALSE);
9353 /* if bitfield then unpack the bits */
9354 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9355 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9358 /* we have can just get the values */
9359 int size = AOP_SIZE (right);
9364 l = aopGet (AOP (right), offset, FALSE, TRUE);
9367 emitcode ("movx", "@%s,a", rname);
9370 emitcode ("inc", "%s", rname);
9376 /* now some housekeeping stuff */
9377 if (aop) /* we had to allocate for this iCode */
9380 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9381 freeAsmop (NULL, aop, ic, TRUE);
9385 /* we did not allocate which means left
9386 already in a pointer register, then
9387 if size > 0 && this could be used again
9388 we have to point it back to where it
9390 if (AOP_SIZE (right) > 1 &&
9391 !OP_SYMBOL (result)->remat &&
9392 (OP_SYMBOL (result)->liveTo > ic->seq ||
9395 int size = AOP_SIZE (right) - 1;
9397 emitcode ("dec", "%s", rname);
9402 if (pi) pi->generated = 1;
9403 freeAsmop (result, NULL, ic, TRUE);
9404 freeAsmop (right, NULL, ic, TRUE);
9409 /*-----------------------------------------------------------------*/
9410 /* genFarPointerSet - set value from far space */
9411 /*-----------------------------------------------------------------*/
9413 genFarPointerSet (operand * right,
9414 operand * result, iCode * ic, iCode * pi)
9417 sym_link *retype = getSpec (operandType (right));
9418 sym_link *letype = getSpec (operandType (result));
9420 D(emitcode ("; genFarPointerSet",""));
9422 aopOp (result, ic, FALSE);
9423 loadDptrFromOperand (result, FALSE);
9425 /* so dptr know contains the address */
9426 aopOp (right, ic, FALSE);
9428 /* if bit then unpack */
9429 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9430 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9433 size = AOP_SIZE (right);
9438 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9440 emitcode ("movx", "@dptr,a");
9442 emitcode ("inc", "dptr");
9445 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9446 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9447 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9450 freeAsmop (result, NULL, ic, TRUE);
9451 freeAsmop (right, NULL, ic, TRUE);
9454 /*-----------------------------------------------------------------*/
9455 /* genGenPointerSet - set value from generic pointer space */
9456 /*-----------------------------------------------------------------*/
9458 genGenPointerSet (operand * right,
9459 operand * result, iCode * ic, iCode * pi)
9462 sym_link *retype = getSpec (operandType (right));
9463 sym_link *letype = getSpec (operandType (result));
9465 D(emitcode ("; genGenPointerSet",""));
9467 aopOp (result, ic, FALSE);
9468 loadDptrFromOperand (result, TRUE);
9470 /* so dptr know contains the address */
9471 aopOp (right, ic, FALSE);
9473 /* if bit then unpack */
9474 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9475 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9478 size = AOP_SIZE (right);
9483 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9485 emitcode ("lcall", "__gptrput");
9487 emitcode ("inc", "dptr");
9491 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9492 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9493 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9496 freeAsmop (result, NULL, ic, TRUE);
9497 freeAsmop (right, NULL, ic, TRUE);
9500 /*-----------------------------------------------------------------*/
9501 /* genPointerSet - stores the value into a pointer location */
9502 /*-----------------------------------------------------------------*/
9504 genPointerSet (iCode * ic, iCode *pi)
9506 operand *right, *result;
9507 sym_link *type, *etype;
9510 D(emitcode ("; genPointerSet",""));
9512 right = IC_RIGHT (ic);
9513 result = IC_RESULT (ic);
9515 /* depending on the type of pointer we need to
9516 move it to the correct pointer register */
9517 type = operandType (result);
9518 etype = getSpec (type);
9519 /* if left is of type of pointer then it is simple */
9520 if (IS_PTR (type) && !IS_FUNC (type->next))
9522 p_type = DCL_TYPE (type);
9526 /* we have to go by the storage class */
9527 p_type = PTR_TYPE (SPEC_OCLS (etype));
9530 /* special case when cast remat */
9531 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9532 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9533 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9534 type = operandType (result);
9535 p_type = DCL_TYPE (type);
9537 /* now that we have the pointer type we assign
9538 the pointer values */
9544 genNearPointerSet (right, result, ic, pi);
9548 genPagedPointerSet (right, result, ic, pi);
9552 genFarPointerSet (right, result, ic, pi);
9556 genGenPointerSet (right, result, ic, pi);
9560 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9561 "genPointerSet: illegal pointer type");
9566 /*-----------------------------------------------------------------*/
9567 /* genIfx - generate code for Ifx statement */
9568 /*-----------------------------------------------------------------*/
9570 genIfx (iCode * ic, iCode * popIc)
9572 operand *cond = IC_COND (ic);
9575 D(emitcode ("; genIfx",""));
9577 aopOp (cond, ic, FALSE);
9579 /* get the value into acc */
9580 if (AOP_TYPE (cond) != AOP_CRY)
9584 /* the result is now in the accumulator */
9585 freeAsmop (cond, NULL, ic, TRUE);
9587 /* if there was something to be popped then do it */
9591 /* if the condition is a bit variable */
9592 if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
9593 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9594 else if (isbit && !IS_ITEMP (cond))
9595 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9597 genIfxJump (ic, "a", NULL, NULL, NULL);
9602 /*-----------------------------------------------------------------*/
9603 /* genAddrOf - generates code for address of */
9604 /*-----------------------------------------------------------------*/
9606 genAddrOf (iCode * ic)
9608 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9611 D(emitcode ("; genAddrOf",""));
9613 aopOp (IC_RESULT (ic), ic, FALSE);
9615 /* if the operand is on the stack then we
9616 need to get the stack offset of this
9620 /* if it has an offset then we need to compute
9624 emitcode ("mov", "a,%s", SYM_BP (sym));
9625 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9626 ((char) (sym->stack - _G.nRegsSaved)) :
9627 ((char) sym->stack)) & 0xff);
9628 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9632 /* we can just move _bp */
9633 aopPut (AOP (IC_RESULT (ic)), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9635 /* fill the result with zero */
9636 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9641 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9647 /* object not on stack then we need the name */
9648 size = AOP_SIZE (IC_RESULT (ic));
9653 char s[SDCC_NAME_MAX];
9655 sprintf (s, "#(%s >> %d)",
9659 sprintf (s, "#%s", sym->rname);
9660 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9664 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9668 /*-----------------------------------------------------------------*/
9669 /* genFarFarAssign - assignment when both are in far space */
9670 /*-----------------------------------------------------------------*/
9672 genFarFarAssign (operand * result, operand * right, iCode * ic)
9674 int size = AOP_SIZE (right);
9678 D(emitcode ("; genFarFarAssign",""));
9680 /* first push the right side on to the stack */
9683 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9685 emitcode ("push", "acc");
9688 freeAsmop (right, NULL, ic, FALSE);
9689 /* now assign DPTR to result */
9690 aopOp (result, ic, FALSE);
9691 size = AOP_SIZE (result);
9694 emitcode ("pop", "acc");
9695 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9697 freeAsmop (result, NULL, ic, FALSE);
9701 /*-----------------------------------------------------------------*/
9702 /* genAssign - generate code for assignment */
9703 /*-----------------------------------------------------------------*/
9705 genAssign (iCode * ic)
9707 operand *result, *right;
9709 unsigned long lit = 0L;
9711 D(emitcode("; genAssign",""));
9713 result = IC_RESULT (ic);
9714 right = IC_RIGHT (ic);
9716 /* if they are the same */
9717 if (operandsEqu (result, right) &&
9718 !isOperandVolatile (result, FALSE) &&
9719 !isOperandVolatile (right, FALSE))
9722 aopOp (right, ic, FALSE);
9724 /* special case both in far space */
9725 if (AOP_TYPE (right) == AOP_DPTR &&
9726 IS_TRUE_SYMOP (result) &&
9727 isOperandInFarSpace (result))
9730 genFarFarAssign (result, right, ic);
9734 aopOp (result, ic, TRUE);
9736 /* if they are the same registers */
9737 if (sameRegs (AOP (right), AOP (result)) &&
9738 !isOperandVolatile (result, FALSE) &&
9739 !isOperandVolatile (right, FALSE))
9742 /* if the result is a bit */
9743 if (AOP_TYPE (result) == AOP_CRY)
9746 /* if the right size is a literal then
9747 we know what the value is */
9748 if (AOP_TYPE (right) == AOP_LIT)
9750 if (((int) operandLitValue (right)))
9751 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9753 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9757 /* the right is also a bit variable */
9758 if (AOP_TYPE (right) == AOP_CRY)
9760 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9761 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9767 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9771 /* bit variables done */
9773 size = AOP_SIZE (result);
9775 if (AOP_TYPE (right) == AOP_LIT)
9776 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9778 (AOP_TYPE (result) != AOP_REG) &&
9779 (AOP_TYPE (right) == AOP_LIT) &&
9780 !IS_FLOAT (operandType (right)) &&
9783 while ((size) && (lit))
9785 aopPut (AOP (result),
9786 aopGet (AOP (right), offset, FALSE, FALSE),
9788 isOperandVolatile (result, FALSE));
9793 emitcode ("clr", "a");
9796 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
9804 aopPut (AOP (result),
9805 aopGet (AOP (right), offset, FALSE, FALSE),
9807 isOperandVolatile (result, FALSE));
9813 freeAsmop (right, NULL, ic, TRUE);
9814 freeAsmop (result, NULL, ic, TRUE);
9817 /*-----------------------------------------------------------------*/
9818 /* genJumpTab - generates code for jump table */
9819 /*-----------------------------------------------------------------*/
9821 genJumpTab (iCode * ic)
9823 symbol *jtab,*jtablo,*jtabhi;
9827 D(emitcode ("; genJumpTab",""));
9829 count = elementsInSet( IC_JTLABELS (ic) );
9833 /* this algorithm needs 9 cycles and 7 + 3*n bytes
9834 if the switch argument is in a register.
9835 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9836 /* (MB) What if peephole converts ljmp to sjmp or ret ???
9837 How will multiply by three be updated ???*/
9838 aopOp (IC_JTCOND (ic), ic, FALSE);
9839 /* get the condition into accumulator */
9840 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9842 /* multiply by three */
9843 emitcode ("add", "a,acc");
9844 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9845 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9847 jtab = newiTempLabel (NULL);
9848 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9849 emitcode ("jmp", "@a+dptr");
9850 emitcode ("", "%05d$:", jtab->key + 100);
9851 /* now generate the jump labels */
9852 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9853 jtab = setNextItem (IC_JTLABELS (ic)))
9854 emitcode ("ljmp", "%05d$", jtab->key + 100);
9858 /* this algorithm needs 14 cycles and 13 + 2*n bytes
9859 if the switch argument is in a register.
9860 For n>6 this algorithm may be more compact */
9861 jtablo = newiTempLabel (NULL);
9862 jtabhi = newiTempLabel (NULL);
9864 /* get the condition into accumulator.
9865 Using b as temporary storage, if register push/pop is needed */
9866 aopOp (IC_JTCOND (ic), ic, FALSE);
9867 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9868 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9869 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9871 // (MB) what if B is in use???
9872 wassertl(!BINUSE, "B was in use");
9873 emitcode ("mov", "b,%s", l);
9876 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9880 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9881 emitcode ("movc", "a,@a+pc");
9882 emitcode ("push", "acc");
9885 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9886 emitcode ("movc", "a,@a+pc");
9887 emitcode ("push", "acc");
9891 /* this scales up to n<=255, but needs two more bytes
9893 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9894 emitcode ("movc", "a,@a+dptr");
9895 emitcode ("push", "acc");
9898 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9899 emitcode ("movc", "a,@a+dptr");
9900 emitcode ("push", "acc");
9903 emitcode ("ret", "");
9905 /* now generate jump table, LSB */
9906 emitcode ("", "%05d$:", jtablo->key + 100);
9907 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9908 jtab = setNextItem (IC_JTLABELS (ic)))
9909 emitcode (".db", "%05d$", jtab->key + 100);
9911 /* now generate jump table, MSB */
9912 emitcode ("", "%05d$:", jtabhi->key + 100);
9913 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9914 jtab = setNextItem (IC_JTLABELS (ic)))
9915 emitcode (".db", "%05d$>>8", jtab->key + 100);
9919 /*-----------------------------------------------------------------*/
9920 /* genCast - gen code for casting */
9921 /*-----------------------------------------------------------------*/
9923 genCast (iCode * ic)
9925 operand *result = IC_RESULT (ic);
9926 sym_link *ctype = operandType (IC_LEFT (ic));
9927 sym_link *rtype = operandType (IC_RIGHT (ic));
9928 operand *right = IC_RIGHT (ic);
9931 D(emitcode("; genCast",""));
9933 /* if they are equivalent then do nothing */
9934 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9937 aopOp (right, ic, FALSE);
9938 aopOp (result, ic, FALSE);
9940 /* if the result is a bit (and not a bitfield) */
9941 // if (AOP_TYPE (result) == AOP_CRY)
9942 if (IS_BITVAR (OP_SYMBOL (result)->type)
9943 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9945 /* if the right size is a literal then
9946 we know what the value is */
9947 if (AOP_TYPE (right) == AOP_LIT)
9949 if (((int) operandLitValue (right)))
9950 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9952 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9957 /* the right is also a bit variable */
9958 if (AOP_TYPE (right) == AOP_CRY)
9960 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9961 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9967 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9972 /* if they are the same size : or less */
9973 if (AOP_SIZE (result) <= AOP_SIZE (right))
9976 /* if they are in the same place */
9977 if (sameRegs (AOP (right), AOP (result)))
9980 /* if they in different places then copy */
9981 size = AOP_SIZE (result);
9985 aopPut (AOP (result),
9986 aopGet (AOP (right), offset, FALSE, FALSE),
9988 isOperandVolatile (result, FALSE));
9995 /* if the result is of type pointer */
10000 sym_link *type = operandType (right);
10001 sym_link *etype = getSpec (type);
10003 /* pointer to generic pointer */
10004 if (IS_GENPTR (ctype))
10007 p_type = DCL_TYPE (type);
10010 if (SPEC_SCLS(etype)==S_REGISTER) {
10011 // let's assume it is a generic pointer
10014 /* we have to go by the storage class */
10015 p_type = PTR_TYPE (SPEC_OCLS (etype));
10019 /* the first two bytes are known */
10020 size = GPTRSIZE - 1;
10024 aopPut (AOP (result),
10025 aopGet (AOP (right), offset, FALSE, FALSE),
10027 isOperandVolatile (result, FALSE));
10030 /* the last byte depending on type */
10032 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10037 // pointerTypeToGPByte will have bitched.
10041 sprintf(gpValStr, "#0x%d", gpVal);
10042 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10047 /* just copy the pointers */
10048 size = AOP_SIZE (result);
10052 aopPut (AOP (result),
10053 aopGet (AOP (right), offset, FALSE, FALSE),
10055 isOperandVolatile (result, FALSE));
10061 /* so we now know that the size of destination is greater
10062 than the size of the source */
10063 /* we move to result for the size of source */
10064 size = AOP_SIZE (right);
10068 aopPut (AOP (result),
10069 aopGet (AOP (right), offset, FALSE, FALSE),
10071 isOperandVolatile (result, FALSE));
10075 /* now depending on the sign of the source && destination */
10076 size = AOP_SIZE (result) - AOP_SIZE (right);
10077 /* if unsigned or not an integral type */
10078 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10081 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
10085 /* we need to extend the sign :{ */
10086 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10089 emitcode ("rlc", "a");
10090 emitcode ("subb", "a,acc");
10092 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
10095 /* we are done hurray !!!! */
10098 freeAsmop (right, NULL, ic, TRUE);
10099 freeAsmop (result, NULL, ic, TRUE);
10103 /*-----------------------------------------------------------------*/
10104 /* genDjnz - generate decrement & jump if not zero instrucion */
10105 /*-----------------------------------------------------------------*/
10107 genDjnz (iCode * ic, iCode * ifx)
10109 symbol *lbl, *lbl1;
10113 D(emitcode ("; genDjnz",""));
10115 /* if the if condition has a false label
10116 then we cannot save */
10117 if (IC_FALSE (ifx))
10120 /* if the minus is not of the form
10122 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10123 !IS_OP_LITERAL (IC_RIGHT (ic)))
10126 if (operandLitValue (IC_RIGHT (ic)) != 1)
10129 /* if the size of this greater than one then no
10131 if (getSize (operandType (IC_RESULT (ic))) > 1)
10134 /* otherwise we can save BIG */
10135 lbl = newiTempLabel (NULL);
10136 lbl1 = newiTempLabel (NULL);
10138 aopOp (IC_RESULT (ic), ic, FALSE);
10140 if (AOP_NEEDSACC(IC_RESULT(ic)))
10142 /* If the result is accessed indirectly via
10143 * the accumulator, we must explicitly write
10144 * it back after the decrement.
10146 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
10148 if (strcmp(rByte, "a"))
10150 /* Something is hopelessly wrong */
10151 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10152 __FILE__, __LINE__);
10153 /* We can just give up; the generated code will be inefficient,
10154 * but what the hey.
10156 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10159 emitcode ("dec", "%s", rByte);
10160 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10161 emitcode ("jnz", "%05d$", lbl->key + 100);
10163 else if (IS_AOP_PREG (IC_RESULT (ic)))
10165 emitcode ("dec", "%s",
10166 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10167 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10168 emitcode ("jnz", "%05d$", lbl->key + 100);
10172 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
10175 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10176 emitcode ("", "%05d$:", lbl->key + 100);
10177 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10178 emitcode ("", "%05d$:", lbl1->key + 100);
10180 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10181 ifx->generated = 1;
10185 /*-----------------------------------------------------------------*/
10186 /* genReceive - generate code for a receive iCode */
10187 /*-----------------------------------------------------------------*/
10189 genReceive (iCode * ic)
10191 int size = getSize (operandType (IC_RESULT (ic)));
10193 D(emitcode ("; genReceive",""));
10195 if (ic->argreg == 1) { /* first parameter */
10196 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10197 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10198 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10201 int receivingA = 0;
10204 for (offset = 0; offset<size; offset++)
10205 if (!strcmp (fReturn[offset], "a"))
10210 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10212 for (offset = size-1; offset>0; offset--)
10213 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10214 emitcode("mov","a,%s", fReturn[0]);
10216 aopOp (IC_RESULT (ic), ic, FALSE);
10218 aopPut (AOP (IC_RESULT (ic)), "a", offset,
10219 isOperandVolatile (IC_RESULT (ic), FALSE));
10220 for (offset = 1; offset<size; offset++)
10221 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
10222 isOperandVolatile (IC_RESULT (ic), FALSE));
10228 if (getTempRegs(tempRegs, size, ic))
10230 for (offset = 0; offset<size; offset++)
10231 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10232 aopOp (IC_RESULT (ic), ic, FALSE);
10233 for (offset = 0; offset<size; offset++)
10234 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
10235 isOperandVolatile (IC_RESULT (ic), FALSE));
10240 offset = fReturnSizeMCS51 - size;
10242 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10243 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10246 aopOp (IC_RESULT (ic), ic, FALSE);
10247 size = AOP_SIZE (IC_RESULT (ic));
10250 emitcode ("pop", "acc");
10251 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10256 aopOp (IC_RESULT (ic), ic, FALSE);
10258 assignResultValue (IC_RESULT (ic));
10260 } else { /* second receive onwards */
10262 aopOp (IC_RESULT (ic), ic, FALSE);
10263 rb1off = ic->argreg;
10265 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10270 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10273 /*-----------------------------------------------------------------*/
10274 /* genDummyRead - generate code for dummy read of volatiles */
10275 /*-----------------------------------------------------------------*/
10277 genDummyRead (iCode * ic)
10282 D(emitcode("; genDummyRead",""));
10284 op = IC_RIGHT (ic);
10285 if (op && IS_SYMOP (op))
10287 aopOp (op, ic, FALSE);
10289 /* if the result is a bit */
10290 if (AOP_TYPE (op) == AOP_CRY)
10291 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10294 /* bit variables done */
10296 size = AOP_SIZE (op);
10300 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10305 freeAsmop (op, NULL, ic, TRUE);
10309 if (op && IS_SYMOP (op))
10311 aopOp (op, ic, FALSE);
10313 /* if the result is a bit */
10314 if (AOP_TYPE (op) == AOP_CRY)
10315 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10318 /* bit variables done */
10320 size = AOP_SIZE (op);
10324 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10329 freeAsmop (op, NULL, ic, TRUE);
10333 /*-----------------------------------------------------------------*/
10334 /* genCritical - generate code for start of a critical sequence */
10335 /*-----------------------------------------------------------------*/
10337 genCritical (iCode *ic)
10339 symbol *tlbl = newiTempLabel (NULL);
10341 D(emitcode("; genCritical",""));
10343 if (IC_RESULT (ic))
10345 aopOp (IC_RESULT (ic), ic, TRUE);
10346 aopPut (AOP (IC_RESULT (ic)), one, 0, 0);
10347 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10348 aopPut (AOP (IC_RESULT (ic)), zero, 0, 0);
10349 emitcode ("", "%05d$:", (tlbl->key + 100));
10350 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10354 emitcode ("setb", "c");
10355 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10356 emitcode ("clr", "c");
10357 emitcode ("", "%05d$:", (tlbl->key + 100));
10358 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10362 /*-----------------------------------------------------------------*/
10363 /* genEndCritical - generate code for end of a critical sequence */
10364 /*-----------------------------------------------------------------*/
10366 genEndCritical (iCode *ic)
10368 D(emitcode("; genEndCritical",""));
10372 aopOp (IC_RIGHT (ic), ic, FALSE);
10373 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10375 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10376 emitcode ("mov", "ea,c");
10380 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10381 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
10382 emitcode ("rrc", "a");
10383 emitcode ("mov", "ea,c");
10385 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10389 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10390 emitcode ("mov", "ea,c");
10394 /*-----------------------------------------------------------------*/
10395 /* gen51Code - generate code for 8051 based controllers */
10396 /*-----------------------------------------------------------------*/
10398 gen51Code (iCode * lic)
10402 /* int cseq = 0; */
10404 _G.currentFunc = NULL;
10405 lineHead = lineCurr = NULL;
10407 /* print the allocation information */
10408 if (allocInfo && currFunc)
10409 printAllocInfo (currFunc, codeOutFile);
10410 /* if debug information required */
10411 if (options.debug && currFunc)
10413 debugFile->writeFunction (currFunc, lic);
10415 /* stack pointer name */
10416 if (options.useXstack)
10422 for (ic = lic; ic; ic = ic->next)
10424 _G.current_iCode = ic;
10426 if (ic->lineno && cln != ic->lineno)
10430 debugFile->writeCLine (ic);
10432 if (!options.noCcodeInAsm) {
10433 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10434 printCLine(ic->filename, ic->lineno));
10439 if (ic->seqPoint && ic->seqPoint != cseq)
10441 emitcode ("", "; sequence point %d", ic->seqPoint);
10442 cseq = ic->seqPoint;
10445 if (options.iCodeInAsm) {
10446 char regsInUse[80];
10449 for (i=0; i<8; i++) {
10450 sprintf (®sInUse[i],
10451 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10454 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10456 /* if the result is marked as
10457 spilt and rematerializable or code for
10458 this has already been generated then
10460 if (resultRemat (ic) || ic->generated)
10463 /* depending on the operation */
10483 /* IPOP happens only when trying to restore a
10484 spilt live range, if there is an ifx statement
10485 following this pop then the if statement might
10486 be using some of the registers being popped which
10487 would destory the contents of the register so
10488 we need to check for this condition and handle it */
10490 ic->next->op == IFX &&
10491 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10492 genIfx (ic->next, ic);
10510 genEndFunction (ic);
10530 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10547 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10551 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10558 /* note these two are xlated by algebraic equivalence
10559 during parsing SDCC.y */
10560 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10561 "got '>=' or '<=' shouldn't have come here");
10565 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10577 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10581 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10585 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10609 genRightShift (ic);
10612 case GET_VALUE_AT_ADDRESS:
10614 hasInc (IC_LEFT (ic), ic,
10615 getSize (operandType (IC_RESULT (ic)))),
10616 ifxForOp (IC_RESULT (ic), ic) );
10620 if (POINTER_SET (ic))
10621 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10647 addSet (&_G.sendSet, ic);
10650 case DUMMY_READ_VOLATILE:
10659 genEndCritical (ic);
10671 _G.current_iCode = NULL;
10673 /* now we are ready to call the
10674 peep hole optimizer */
10675 if (!options.nopeep)
10676 peepHole (&lineHead);
10678 /* now do the actual printing */
10679 printLine (lineHead, codeOutFile);