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;
3061 int accIsFree = sym->recvSize < 4;
3064 _G.currentFunc = NULL;
3065 if (IFFUNC_ISNAKED(sym->type))
3067 emitcode(";", "naked function: no epilogue.");
3068 if (options.debug && currFunc)
3069 debugFile->writeEndFunction (currFunc, ic, 0);
3073 if (IFFUNC_ISCRITICAL (sym->type))
3075 emitcode ("pop", "psw"); /* restore ea via c in psw */
3076 emitcode ("mov", "ea,c");
3079 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))// && !options.useXstack)
3081 emitcode ("mov", "sp,_bp");
3083 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3085 if (options.useXstack)
3087 emitcode ("pop", "_bp");
3088 emitcode ("xch", "a,_bpx");
3089 emitcode ("mov", "r0,a");
3090 emitcode ("dec", "r0");
3091 emitcode ("movx", "a,@r0");
3092 emitcode ("xch", "a,_bpx");
3093 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3097 emitcode ("pop", "_bp");
3101 /* restore the register bank */
3102 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3104 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3105 || !options.useXstack)
3107 /* Special case of ISR using non-zero bank with useXstack
3110 emitcode ("pop", "psw");
3114 if (IFFUNC_ISISR (sym->type))
3117 /* now we need to restore the registers */
3118 /* if this isr has no bank i.e. is going to
3119 run with bank 0 , then we need to save more
3121 if (!FUNC_REGBANK (sym->type))
3123 /* if this function does not call any other
3124 function then we can be economical and
3125 save only those registers that are used */
3126 if (!IFFUNC_HASFCALL(sym->type))
3130 /* if any registers used */
3133 /* save the registers used */
3134 for (i = sym->regsUsed->size; i >= 0; i--)
3136 if (bitVectBitValue (sym->regsUsed, i))
3137 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3143 if (options.parms_in_bank1) {
3145 for (i = 7 ; i >= 0 ; i-- ) {
3146 emitcode ("pop","%s",rb1regs[i]);
3149 /* this function has a function call cannot
3150 determines register usage so we will have to pop the
3152 unsaveRBank (0, ic, FALSE);
3157 /* This ISR uses a non-zero bank.
3159 * Restore any register banks saved by genFunction
3162 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3165 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3167 if (savedBanks & (1 << ix))
3169 unsaveRBank(ix, NULL, FALSE);
3173 if (options.useXstack)
3175 /* Restore bank AFTER calling unsaveRBank,
3176 * since it can trash r0.
3178 emitcode ("pop", "psw");
3182 if (!inExcludeList ("dph"))
3183 emitcode ("pop", "dph");
3184 if (!inExcludeList ("dpl"))
3185 emitcode ("pop", "dpl");
3186 if (!inExcludeList ("b"))
3187 emitcode ("pop", "b");
3188 if (!inExcludeList ("acc"))
3189 emitcode ("pop", "acc");
3191 /* if debug then send end of function */
3192 if (options.debug && currFunc)
3194 debugFile->writeEndFunction (currFunc, ic, 1);
3197 emitcode ("reti", "");
3201 if (IFFUNC_CALLEESAVES(sym->type))
3205 /* if any registers used */
3208 /* save the registers used */
3209 for (i = sym->regsUsed->size; i >= 0; i--)
3211 if (bitVectBitValue (sym->regsUsed, i) ||
3212 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3213 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3216 else if (mcs51_ptrRegReq)
3218 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3219 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3224 /* if debug then send end of function */
3225 if (options.debug && currFunc)
3227 debugFile->writeEndFunction (currFunc, ic, 1);
3230 emitcode ("ret", "");
3233 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3236 /* If this was an interrupt handler using bank 0 that called another */
3237 /* function, then all registers must be saved; nothing to optimized. */
3238 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3239 && !FUNC_REGBANK(sym->type))
3242 /* There are no push/pops to optimize if not callee-saves or ISR */
3243 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3246 /* If there were stack parameters, we cannot optimize without also */
3247 /* fixing all of the stack offsets; this is too dificult to consider. */
3248 if (FUNC_HASSTACKPARM(sym->type))
3251 /* Compute the registers actually used */
3252 regsUsed = newBitVect (mcs51_nRegs);
3253 regsUsedPrologue = newBitVect (mcs51_nRegs);
3256 if (lnp->ic && lnp->ic->op == FUNCTION)
3257 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3259 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3261 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3262 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3269 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3270 && !bitVectBitValue (regsUsed, CND_IDX))
3272 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3273 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3274 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3275 bitVectUnSetBit (regsUsed, CND_IDX);
3278 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3280 /* If this was an interrupt handler that called another function */
3281 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3282 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3284 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3285 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3286 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3287 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3288 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3291 /* Remove the unneeded push/pops */
3292 regsUnneeded = newBitVect (mcs51_nRegs);
3295 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3297 if (!strncmp(lnp->line, "push", 4))
3299 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3300 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3302 connectLine (lnp->prev, lnp->next);
3303 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3306 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3308 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3309 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3311 connectLine (lnp->prev, lnp->next);
3312 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3319 for (idx = 0; idx < regsUnneeded->size; idx++)
3320 if (bitVectBitValue (regsUnneeded, idx))
3321 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3323 freeBitVect (regsUnneeded);
3324 freeBitVect (regsUsed);
3325 freeBitVect (regsUsedPrologue);
3328 /*-----------------------------------------------------------------*/
3329 /* genRet - generate code for return statement */
3330 /*-----------------------------------------------------------------*/
3334 int size, offset = 0, pushed = 0;
3336 D(emitcode ("; genRet",""));
3338 /* if we have no return value then
3339 just generate the "ret" */
3343 /* we have something to return then
3344 move the return value into place */
3345 aopOp (IC_LEFT (ic), ic, FALSE);
3346 size = AOP_SIZE (IC_LEFT (ic));
3351 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3354 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3356 emitcode ("push", "%s", l);
3361 l = aopGet (AOP (IC_LEFT (ic)), offset,
3363 if (strcmp (fReturn[offset], l))
3364 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3373 if (strcmp (fReturn[pushed], "a"))
3374 emitcode ("pop", fReturn[pushed]);
3376 emitcode ("pop", "acc");
3379 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3382 /* generate a jump to the return label
3383 if the next is not the return statement */
3384 if (!(ic->next && ic->next->op == LABEL &&
3385 IC_LABEL (ic->next) == returnLabel))
3387 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3391 /*-----------------------------------------------------------------*/
3392 /* genLabel - generates a label */
3393 /*-----------------------------------------------------------------*/
3395 genLabel (iCode * ic)
3397 /* special case never generate */
3398 if (IC_LABEL (ic) == entryLabel)
3401 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3404 /*-----------------------------------------------------------------*/
3405 /* genGoto - generates a ljmp */
3406 /*-----------------------------------------------------------------*/
3408 genGoto (iCode * ic)
3410 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3413 /*-----------------------------------------------------------------*/
3414 /* findLabelBackwards: walks back through the iCode chain looking */
3415 /* for the given label. Returns number of iCode instructions */
3416 /* between that label and given ic. */
3417 /* Returns zero if label not found. */
3418 /*-----------------------------------------------------------------*/
3420 findLabelBackwards (iCode * ic, int key)
3429 /* If we have any pushes or pops, we cannot predict the distance.
3430 I don't like this at all, this should be dealt with in the
3432 if (ic->op == IPUSH || ic->op == IPOP) {
3436 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3445 /*-----------------------------------------------------------------*/
3446 /* genPlusIncr :- does addition with increment if possible */
3447 /*-----------------------------------------------------------------*/
3449 genPlusIncr (iCode * ic)
3451 unsigned int icount;
3452 unsigned int size = getDataSize (IC_RESULT (ic));
3454 /* will try to generate an increment */
3455 /* if the right side is not a literal
3457 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3460 /* if the literal value of the right hand side
3461 is greater than 4 then it is not worth it */
3462 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3465 D(emitcode ("; genPlusIncr",""));
3467 /* if increment >=16 bits in register or direct space */
3468 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3469 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3477 /* If the next instruction is a goto and the goto target
3478 * is < 10 instructions previous to this, we can generate
3479 * jumps straight to that target.
3481 if (ic->next && ic->next->op == GOTO
3482 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3483 && labelRange <= 10)
3485 emitcode (";", "tail increment optimized");
3486 tlbl = IC_LABEL (ic->next);
3491 tlbl = newiTempLabel (NULL);
3494 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3495 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3496 IS_AOP_PREG (IC_RESULT (ic)))
3497 emitcode ("cjne", "%s,#0x00,%05d$",
3498 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3502 emitcode ("clr", "a");
3503 emitcode ("cjne", "a,%s,%05d$",
3504 aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE),
3508 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3511 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3512 IS_AOP_PREG (IC_RESULT (ic)))
3513 emitcode ("cjne", "%s,#0x00,%05d$",
3514 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3517 emitcode ("cjne", "a,%s,%05d$",
3518 aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE),
3521 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3525 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3526 IS_AOP_PREG (IC_RESULT (ic)))
3527 emitcode ("cjne", "%s,#0x00,%05d$",
3528 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3532 emitcode ("cjne", "a,%s,%05d$",
3533 aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE),
3536 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3541 emitcode ("", "%05d$:", tlbl->key + 100);
3546 /* if the sizes are greater than 1 then we cannot */
3547 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3548 AOP_SIZE (IC_LEFT (ic)) > 1)
3551 /* we can if the aops of the left & result match or
3552 if they are in registers and the registers are the
3554 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3559 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3560 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
3561 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
3567 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
3576 /*-----------------------------------------------------------------*/
3577 /* outBitAcc - output a bit in acc */
3578 /*-----------------------------------------------------------------*/
3580 outBitAcc (operand * result)
3582 symbol *tlbl = newiTempLabel (NULL);
3583 /* if the result is a bit */
3584 if (AOP_TYPE (result) == AOP_CRY)
3586 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
3590 emitcode ("jz", "%05d$", tlbl->key + 100);
3591 emitcode ("mov", "a,%s", one);
3592 emitcode ("", "%05d$:", tlbl->key + 100);
3597 /*-----------------------------------------------------------------*/
3598 /* genPlusBits - generates code for addition of two bits */
3599 /*-----------------------------------------------------------------*/
3601 genPlusBits (iCode * ic)
3603 D(emitcode ("; genPlusBits",""));
3605 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3607 symbol *lbl = newiTempLabel (NULL);
3608 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3609 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3610 emitcode ("cpl", "c");
3611 emitcode ("", "%05d$:", (lbl->key + 100));
3612 outBitC (IC_RESULT (ic));
3616 emitcode ("clr", "a");
3617 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3618 emitcode ("rlc", "a");
3619 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3620 emitcode ("addc", "a,#0x00");
3621 outAcc (IC_RESULT (ic));
3626 /* This is the original version of this code.
3628 * This is being kept around for reference,
3629 * because I am not entirely sure I got it right...
3632 adjustArithmeticResult (iCode * ic)
3634 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3635 AOP_SIZE (IC_LEFT (ic)) == 3 &&
3636 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3637 aopPut (AOP (IC_RESULT (ic)),
3638 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
3640 isOperandVolatile (IC_RESULT (ic), FALSE));
3642 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3643 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
3644 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3645 aopPut (AOP (IC_RESULT (ic)),
3646 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
3648 isOperandVolatile (IC_RESULT (ic), FALSE));
3650 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
3651 AOP_SIZE (IC_LEFT (ic)) < 3 &&
3652 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
3653 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3654 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3657 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3658 aopPut (AOP (IC_RESULT (ic)), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
3662 /* This is the pure and virtuous version of this code.
3663 * I'm pretty certain it's right, but not enough to toss the old
3667 adjustArithmeticResult (iCode * ic)
3669 if (opIsGptr (IC_RESULT (ic)) &&
3670 opIsGptr (IC_LEFT (ic)) &&
3671 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3673 aopPut (AOP (IC_RESULT (ic)),
3674 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3676 isOperandVolatile (IC_RESULT (ic), FALSE));
3679 if (opIsGptr (IC_RESULT (ic)) &&
3680 opIsGptr (IC_RIGHT (ic)) &&
3681 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3683 aopPut (AOP (IC_RESULT (ic)),
3684 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
3686 isOperandVolatile (IC_RESULT (ic), FALSE));
3689 if (opIsGptr (IC_RESULT (ic)) &&
3690 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3691 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3692 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3693 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3696 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3697 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3702 /*-----------------------------------------------------------------*/
3703 /* genPlus - generates code for addition */
3704 /*-----------------------------------------------------------------*/
3706 genPlus (iCode * ic)
3708 int size, offset = 0;
3711 asmop *leftOp, *rightOp;
3714 /* special cases :- */
3716 D(emitcode ("; genPlus",""));
3718 aopOp (IC_LEFT (ic), ic, FALSE);
3719 aopOp (IC_RIGHT (ic), ic, FALSE);
3720 aopOp (IC_RESULT (ic), ic, TRUE);
3722 /* if literal, literal on the right or
3723 if left requires ACC or right is already
3725 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3726 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3727 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3729 operand *t = IC_RIGHT (ic);
3730 IC_RIGHT (ic) = IC_LEFT (ic);
3734 /* if both left & right are in bit
3736 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3737 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3743 /* if left in bit space & right literal */
3744 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3745 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3747 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3748 /* if result in bit space */
3749 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3751 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3752 emitcode ("cpl", "c");
3753 outBitC (IC_RESULT (ic));
3757 size = getDataSize (IC_RESULT (ic));
3760 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3761 emitcode ("addc", "a,#00");
3762 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
3768 /* if I can do an increment instead
3769 of add then GOOD for ME */
3770 if (genPlusIncr (ic) == TRUE)
3773 size = getDataSize (IC_RESULT (ic));
3774 leftOp = AOP(IC_LEFT(ic));
3775 rightOp = AOP(IC_RIGHT(ic));
3778 /* if this is an add for an array access
3779 at a 256 byte boundary */
3781 && AOP_TYPE (op) == AOP_IMMD
3783 && IS_SPEC (OP_SYM_ETYPE (op))
3784 && SPEC_ABSA (OP_SYM_ETYPE (op))
3785 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
3788 D(emitcode ("; genPlus aligned array",""));
3789 aopPut (AOP (IC_RESULT (ic)),
3790 aopGet (rightOp, 0, FALSE, FALSE),
3792 isOperandVolatile (IC_RESULT (ic), FALSE));
3794 if( 1 == getDataSize (IC_RIGHT (ic)) )
3796 aopPut (AOP (IC_RESULT (ic)),
3797 aopGet (leftOp, 1, FALSE, FALSE),
3799 isOperandVolatile (IC_RESULT (ic), FALSE));
3803 MOVA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE, FALSE));
3804 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
3805 aopPut (AOP (IC_RESULT (ic)), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
3810 /* if the lower bytes of a literal are zero skip the addition */
3811 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
3813 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
3814 (skip_bytes+1 < size))
3819 D(emitcode ("; genPlus shortcut",""));
3824 if( offset >= skip_bytes )
3826 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
3829 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3831 emitcode("xch", "a,b");
3832 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3833 emitcode (add, "a,b");
3836 else if (aopGetUsesAcc (leftOp, offset))
3838 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
3839 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
3843 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
3844 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
3846 aopPut (AOP (IC_RESULT (ic)), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
3847 add = "addc"; /* further adds must propagate carry */
3851 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
3852 isOperandVolatile (IC_RESULT (ic), FALSE))
3855 aopPut (AOP (IC_RESULT (ic)),
3856 aopGet (leftOp, offset, FALSE, FALSE),
3858 isOperandVolatile (IC_RESULT (ic), FALSE));
3864 adjustArithmeticResult (ic);
3867 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3868 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3869 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3872 /*-----------------------------------------------------------------*/
3873 /* genMinusDec :- does subtraction with deccrement if possible */
3874 /*-----------------------------------------------------------------*/
3876 genMinusDec (iCode * ic)
3878 unsigned int icount;
3879 unsigned int size = getDataSize (IC_RESULT (ic));
3881 /* will try to generate an increment */
3882 /* if the right side is not a literal
3884 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3887 /* if the literal value of the right hand side
3888 is greater than 4 then it is not worth it */
3889 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3892 D(emitcode ("; genMinusDec",""));
3894 /* if decrement >=16 bits in register or direct space */
3895 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
3896 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3904 /* If the next instruction is a goto and the goto target
3905 * is <= 10 instructions previous to this, we can generate
3906 * jumps straight to that target.
3908 if (ic->next && ic->next->op == GOTO
3909 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3910 && labelRange <= 10)
3912 emitcode (";", "tail decrement optimized");
3913 tlbl = IC_LABEL (ic->next);
3918 tlbl = newiTempLabel (NULL);
3922 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3923 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3924 IS_AOP_PREG (IC_RESULT (ic)))
3925 emitcode ("cjne", "%s,#0xff,%05d$"
3926 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3930 emitcode ("mov", "a,#0xff");
3931 emitcode ("cjne", "a,%s,%05d$"
3932 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3935 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3938 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3939 IS_AOP_PREG (IC_RESULT (ic)))
3940 emitcode ("cjne", "%s,#0xff,%05d$"
3941 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3945 emitcode ("cjne", "a,%s,%05d$"
3946 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3949 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3953 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3954 IS_AOP_PREG (IC_RESULT (ic)))
3955 emitcode ("cjne", "%s,#0xff,%05d$"
3956 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3960 emitcode ("cjne", "a,%s,%05d$"
3961 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3964 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3968 emitcode ("", "%05d$:", tlbl->key + 100);
3973 /* if the sizes are greater than 1 then we cannot */
3974 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3975 AOP_SIZE (IC_LEFT (ic)) > 1)
3978 /* we can if the aops of the left & result match or
3979 if they are in registers and the registers are the
3981 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3985 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3993 /*-----------------------------------------------------------------*/
3994 /* addSign - complete with sign */
3995 /*-----------------------------------------------------------------*/
3997 addSign (operand * result, int offset, int sign)
3999 int size = (getDataSize (result) - offset);
4004 emitcode ("rlc", "a");
4005 emitcode ("subb", "a,acc");
4007 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4011 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4015 /*-----------------------------------------------------------------*/
4016 /* genMinusBits - generates code for subtraction of two bits */
4017 /*-----------------------------------------------------------------*/
4019 genMinusBits (iCode * ic)
4021 symbol *lbl = newiTempLabel (NULL);
4023 D(emitcode ("; genMinusBits",""));
4025 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4027 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4028 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4029 emitcode ("cpl", "c");
4030 emitcode ("", "%05d$:", (lbl->key + 100));
4031 outBitC (IC_RESULT (ic));
4035 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4036 emitcode ("subb", "a,acc");
4037 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4038 emitcode ("inc", "a");
4039 emitcode ("", "%05d$:", (lbl->key + 100));
4040 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4041 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4045 /*-----------------------------------------------------------------*/
4046 /* genMinus - generates code for subtraction */
4047 /*-----------------------------------------------------------------*/
4049 genMinus (iCode * ic)
4051 int size, offset = 0;
4053 D(emitcode ("; genMinus",""));
4055 aopOp (IC_LEFT (ic), ic, FALSE);
4056 aopOp (IC_RIGHT (ic), ic, FALSE);
4057 aopOp (IC_RESULT (ic), ic, TRUE);
4059 /* special cases :- */
4060 /* if both left & right are in bit space */
4061 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4062 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4068 /* if I can do an decrement instead
4069 of subtract then GOOD for ME */
4070 if (genMinusDec (ic) == TRUE)
4073 size = getDataSize (IC_RESULT (ic));
4075 /* if literal, add a,#-lit, else normal subb */
4076 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4078 unsigned long lit = 0L;
4080 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4085 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
4086 /* first add without previous c */
4088 if (!size && lit== (unsigned long) -1) {
4089 emitcode ("dec", "a");
4091 emitcode ("add", "a,#0x%02x",
4092 (unsigned int) (lit & 0x0FFL));
4095 emitcode ("addc", "a,#0x%02x",
4096 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4098 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4103 asmop *leftOp, *rightOp;
4105 leftOp = AOP(IC_LEFT(ic));
4106 rightOp = AOP(IC_RIGHT(ic));
4110 if (aopGetUsesAcc(rightOp, offset)) {
4111 if (aopGetUsesAcc(leftOp, offset)) {
4114 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4116 emitcode ("mov", "b,a");
4119 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4120 emitcode ("subb", "a,b");
4123 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4124 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4126 emitcode( "setb", "c");
4128 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4129 emitcode("cpl", "a");
4132 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4135 emitcode ("subb", "a,%s",
4136 aopGet(rightOp, offset, FALSE, TRUE));
4139 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4144 adjustArithmeticResult (ic);
4147 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4148 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4149 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4153 /*-----------------------------------------------------------------*/
4154 /* genMultbits :- multiplication of bits */
4155 /*-----------------------------------------------------------------*/
4157 genMultbits (operand * left,
4161 D(emitcode ("; genMultbits",""));
4163 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4164 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4168 /*-----------------------------------------------------------------*/
4169 /* genMultOneByte : 8*8=8/16 bit multiplication */
4170 /*-----------------------------------------------------------------*/
4172 genMultOneByte (operand * left,
4177 int size = AOP_SIZE (result);
4178 bool runtimeSign, compiletimeSign;
4179 bool lUnsigned, rUnsigned, pushedB;
4181 D(emitcode ("; genMultOneByte",""));
4183 if (size < 1 || size > 2)
4185 /* this should never happen */
4186 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4187 AOP_SIZE(result), __FILE__, lineno);
4191 /* (if two literals: the value is computed before) */
4192 /* if one literal, literal on the right */
4193 if (AOP_TYPE (left) == AOP_LIT)
4198 /* emitcode (";", "swapped left and right"); */
4200 /* if no literal, unsigned on the right: shorter code */
4201 if ( AOP_TYPE (right) != AOP_LIT
4202 && SPEC_USIGN (getSpec (operandType (left))))
4209 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4210 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4214 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4215 no need to take care about the signedness! */
4216 || (lUnsigned && rUnsigned))
4218 /* just an unsigned 8 * 8 = 8 multiply
4220 /* emitcode (";","unsigned"); */
4221 /* TODO: check for accumulator clash between left & right aops? */
4223 if (AOP_TYPE (right) == AOP_LIT)
4225 /* moving to accumulator first helps peepholes */
4226 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4227 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4231 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4232 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4235 emitcode ("mul", "ab");
4236 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4238 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4244 /* we have to do a signed multiply */
4245 /* emitcode (";", "signed"); */
4247 /* now sign adjust for both left & right */
4249 /* let's see what's needed: */
4250 /* apply negative sign during runtime */
4251 runtimeSign = FALSE;
4252 /* negative sign from literals */
4253 compiletimeSign = FALSE;
4257 if (AOP_TYPE(left) == AOP_LIT)
4259 /* signed literal */
4260 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4262 compiletimeSign = TRUE;
4265 /* signed but not literal */
4271 if (AOP_TYPE(right) == AOP_LIT)
4273 /* signed literal */
4274 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4276 compiletimeSign ^= TRUE;
4279 /* signed but not literal */
4283 /* initialize F0, which stores the runtime sign */
4286 if (compiletimeSign)
4287 emitcode ("setb", "F0"); /* set sign flag */
4289 emitcode ("clr", "F0"); /* reset sign flag */
4292 /* save the signs of the operands */
4293 if (AOP_TYPE(right) == AOP_LIT)
4295 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4297 if (!rUnsigned && val < 0)
4298 emitcode ("mov", "b,#0x%02x", -val);
4300 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4302 else /* ! literal */
4304 if (rUnsigned) /* emitcode (";", "signed"); */
4306 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4309 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4310 lbl = newiTempLabel (NULL);
4311 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4312 emitcode ("cpl", "F0"); /* complement sign flag */
4313 emitcode ("cpl", "a"); /* 2's complement */
4314 emitcode ("inc", "a");
4315 emitcode ("", "%05d$:", (lbl->key + 100));
4316 emitcode ("mov", "b,a");
4320 if (AOP_TYPE(left) == AOP_LIT)
4322 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4324 if (!lUnsigned && val < 0)
4325 emitcode ("mov", "a,#0x%02x", -val);
4327 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4329 else /* ! literal */
4331 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4335 lbl = newiTempLabel (NULL);
4336 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4337 emitcode ("cpl", "F0"); /* complement sign flag */
4338 emitcode ("cpl", "a"); /* 2's complement */
4339 emitcode ("inc", "a");
4340 emitcode ("", "%05d$:", (lbl->key + 100));
4344 /* now the multiplication */
4345 emitcode ("mul", "ab");
4346 if (runtimeSign || compiletimeSign)
4348 lbl = newiTempLabel (NULL);
4350 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4351 emitcode ("cpl", "a"); /* lsb 2's complement */
4353 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4356 emitcode ("add", "a,#1"); /* this sets carry flag */
4357 emitcode ("xch", "a,b");
4358 emitcode ("cpl", "a"); /* msb 2's complement */
4359 emitcode ("addc", "a,#0");
4360 emitcode ("xch", "a,b");
4362 emitcode ("", "%05d$:", (lbl->key + 100));
4364 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4366 aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
4371 /*-----------------------------------------------------------------*/
4372 /* genMult - generates code for multiplication */
4373 /*-----------------------------------------------------------------*/
4375 genMult (iCode * ic)
4377 operand *left = IC_LEFT (ic);
4378 operand *right = IC_RIGHT (ic);
4379 operand *result = IC_RESULT (ic);
4381 D(emitcode ("; genMult",""));
4383 /* assign the amsops */
4384 aopOp (left, ic, FALSE);
4385 aopOp (right, ic, FALSE);
4386 aopOp (result, ic, TRUE);
4388 /* special cases first */
4390 if (AOP_TYPE (left) == AOP_CRY &&
4391 AOP_TYPE (right) == AOP_CRY)
4393 genMultbits (left, right, result);
4397 /* if both are of size == 1 */
4398 #if 0 // one of them can be a sloc shared with the result
4399 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4401 if (getSize(operandType(left)) == 1 &&
4402 getSize(operandType(right)) == 1)
4405 genMultOneByte (left, right, result);
4409 /* should have been converted to function call */
4410 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4411 getSize(OP_SYMBOL(right)->type));
4415 freeAsmop (result, NULL, ic, TRUE);
4416 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4417 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4420 /*-----------------------------------------------------------------*/
4421 /* genDivbits :- division of bits */
4422 /*-----------------------------------------------------------------*/
4424 genDivbits (operand * left,
4431 D(emitcode ("; genDivbits",""));
4435 /* the result must be bit */
4436 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4437 l = aopGet (AOP (left), 0, FALSE, FALSE);
4441 emitcode ("div", "ab");
4442 emitcode ("rrc", "a");
4446 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4449 /*-----------------------------------------------------------------*/
4450 /* genDivOneByte : 8 bit division */
4451 /*-----------------------------------------------------------------*/
4453 genDivOneByte (operand * left,
4457 bool lUnsigned, rUnsigned, pushedB;
4458 bool runtimeSign, compiletimeSign;
4462 D(emitcode ("; genDivOneByte",""));
4464 /* Why is it necessary that genDivOneByte() can return an int result?
4467 volatile unsigned char uc;
4468 volatile signed char sc1, sc2;
4481 In all cases a one byte result would overflow, the following cast to int
4482 would return the wrong result.
4484 Two possible solution:
4485 a) cast operands to int, if ((unsigned) / (signed)) or
4486 ((signed) / (signed))
4487 b) return an 16 bit signed int; this is what we're doing here!
4490 size = AOP_SIZE (result) - 1;
4492 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4493 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4497 /* signed or unsigned */
4498 if (lUnsigned && rUnsigned)
4500 /* unsigned is easy */
4501 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4502 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4503 emitcode ("div", "ab");
4504 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4506 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4512 /* signed is a little bit more difficult */
4514 /* now sign adjust for both left & right */
4516 /* let's see what's needed: */
4517 /* apply negative sign during runtime */
4518 runtimeSign = FALSE;
4519 /* negative sign from literals */
4520 compiletimeSign = FALSE;
4524 if (AOP_TYPE(left) == AOP_LIT)
4526 /* signed literal */
4527 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4529 compiletimeSign = TRUE;
4532 /* signed but not literal */
4538 if (AOP_TYPE(right) == AOP_LIT)
4540 /* signed literal */
4541 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4543 compiletimeSign ^= TRUE;
4546 /* signed but not literal */
4550 /* initialize F0, which stores the runtime sign */
4553 if (compiletimeSign)
4554 emitcode ("setb", "F0"); /* set sign flag */
4556 emitcode ("clr", "F0"); /* reset sign flag */
4559 /* save the signs of the operands */
4560 if (AOP_TYPE(right) == AOP_LIT)
4562 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4564 if (!rUnsigned && val < 0)
4565 emitcode ("mov", "b,#0x%02x", -val);
4567 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4569 else /* ! literal */
4572 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4575 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4576 lbl = newiTempLabel (NULL);
4577 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4578 emitcode ("cpl", "F0"); /* complement sign flag */
4579 emitcode ("cpl", "a"); /* 2's complement */
4580 emitcode ("inc", "a");
4581 emitcode ("", "%05d$:", (lbl->key + 100));
4582 emitcode ("mov", "b,a");
4586 if (AOP_TYPE(left) == AOP_LIT)
4588 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4590 if (!lUnsigned && val < 0)
4591 emitcode ("mov", "a,#0x%02x", -val);
4593 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4595 else /* ! literal */
4597 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4601 lbl = newiTempLabel (NULL);
4602 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4603 emitcode ("cpl", "F0"); /* complement sign flag */
4604 emitcode ("cpl", "a"); /* 2's complement */
4605 emitcode ("inc", "a");
4606 emitcode ("", "%05d$:", (lbl->key + 100));
4610 /* now the division */
4611 emitcode ("div", "ab");
4613 if (runtimeSign || compiletimeSign)
4615 lbl = newiTempLabel (NULL);
4617 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4618 emitcode ("cpl", "a"); /* lsb 2's complement */
4619 emitcode ("inc", "a");
4620 emitcode ("", "%05d$:", (lbl->key + 100));
4622 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4625 /* msb is 0x00 or 0xff depending on the sign */
4628 emitcode ("mov", "c,F0");
4629 emitcode ("subb", "a,acc");
4631 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4633 else /* compiletimeSign */
4635 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4640 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4642 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4648 /*-----------------------------------------------------------------*/
4649 /* genDiv - generates code for division */
4650 /*-----------------------------------------------------------------*/
4654 operand *left = IC_LEFT (ic);
4655 operand *right = IC_RIGHT (ic);
4656 operand *result = IC_RESULT (ic);
4658 D(emitcode ("; genDiv",""));
4660 /* assign the amsops */
4661 aopOp (left, ic, FALSE);
4662 aopOp (right, ic, FALSE);
4663 aopOp (result, ic, TRUE);
4665 /* special cases first */
4667 if (AOP_TYPE (left) == AOP_CRY &&
4668 AOP_TYPE (right) == AOP_CRY)
4670 genDivbits (left, right, result);
4674 /* if both are of size == 1 */
4675 if (AOP_SIZE (left) == 1 &&
4676 AOP_SIZE (right) == 1)
4678 genDivOneByte (left, right, result);
4682 /* should have been converted to function call */
4685 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4686 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4687 freeAsmop (result, NULL, ic, TRUE);
4690 /*-----------------------------------------------------------------*/
4691 /* genModbits :- modulus of bits */
4692 /*-----------------------------------------------------------------*/
4694 genModbits (operand * left,
4701 D(emitcode ("; genModbits",""));
4705 /* the result must be bit */
4706 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4707 l = aopGet (AOP (left), 0, FALSE, FALSE);
4711 emitcode ("div", "ab");
4712 emitcode ("mov", "a,b");
4713 emitcode ("rrc", "a");
4717 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
4720 /*-----------------------------------------------------------------*/
4721 /* genModOneByte : 8 bit modulus */
4722 /*-----------------------------------------------------------------*/
4724 genModOneByte (operand * left,
4728 bool lUnsigned, rUnsigned, pushedB;
4729 bool runtimeSign, compiletimeSign;
4733 D(emitcode ("; genModOneByte",""));
4735 size = AOP_SIZE (result) - 1;
4737 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4738 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4740 /* if right is a literal, check it for 2^n */
4741 if (AOP_TYPE(right) == AOP_LIT)
4743 unsigned char val = abs((int) operandLitValue(right));
4744 symbol *lbl2 = NULL;
4748 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
4757 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4758 "modulus of unsigned char by 2^n literal shouldn't be processed here");
4759 /* because iCode should have been changed to genAnd */
4760 /* see file "SDCCopt.c", function "convertToFcall()" */
4762 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4763 emitcode ("mov", "c,acc.7");
4764 emitcode ("anl", "a,#0x%02x", val - 1);
4765 lbl = newiTempLabel (NULL);
4766 emitcode ("jz", "%05d$", (lbl->key + 100));
4767 emitcode ("jnc", "%05d$", (lbl->key + 100));
4768 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
4774 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4776 aopPut (AOP (result), "#0xff", offs2++, isOperandVolatile (result, FALSE));
4777 lbl2 = newiTempLabel (NULL);
4778 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
4780 emitcode ("", "%05d$:", (lbl->key + 100));
4781 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4783 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4786 emitcode ("", "%05d$:", (lbl2->key + 100));
4797 /* signed or unsigned */
4798 if (lUnsigned && rUnsigned)
4800 /* unsigned is easy */
4801 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4802 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4803 emitcode ("div", "ab");
4804 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4806 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4812 /* signed is a little bit more difficult */
4814 /* now sign adjust for both left & right */
4816 /* modulus: sign of the right operand has no influence on the result! */
4817 if (AOP_TYPE(right) == AOP_LIT)
4819 signed char val = (char) operandLitValue(right);
4821 if (!rUnsigned && val < 0)
4822 emitcode ("mov", "b,#0x%02x", -val);
4824 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4826 else /* not literal */
4829 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
4832 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4833 lbl = newiTempLabel (NULL);
4834 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4835 emitcode ("cpl", "a"); /* 2's complement */
4836 emitcode ("inc", "a");
4837 emitcode ("", "%05d$:", (lbl->key + 100));
4838 emitcode ("mov", "b,a");
4842 /* let's see what's needed: */
4843 /* apply negative sign during runtime */
4844 runtimeSign = FALSE;
4845 /* negative sign from literals */
4846 compiletimeSign = FALSE;
4848 /* sign adjust left side */
4849 if (AOP_TYPE(left) == AOP_LIT)
4851 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4853 if (!lUnsigned && val < 0)
4855 compiletimeSign = TRUE; /* set sign flag */
4856 emitcode ("mov", "a,#0x%02x", -val);
4859 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4861 else /* ! literal */
4863 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
4868 emitcode ("clr", "F0"); /* clear sign flag */
4870 lbl = newiTempLabel (NULL);
4871 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4872 emitcode ("setb", "F0"); /* set sign flag */
4873 emitcode ("cpl", "a"); /* 2's complement */
4874 emitcode ("inc", "a");
4875 emitcode ("", "%05d$:", (lbl->key + 100));
4879 /* now the modulus */
4880 emitcode ("div", "ab");
4882 if (runtimeSign || compiletimeSign)
4884 emitcode ("mov", "a,b");
4885 lbl = newiTempLabel (NULL);
4887 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4888 emitcode ("cpl", "a"); /* 2's complement */
4889 emitcode ("inc", "a");
4890 emitcode ("", "%05d$:", (lbl->key + 100));
4892 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
4895 /* msb is 0x00 or 0xff depending on the sign */
4898 emitcode ("mov", "c,F0");
4899 emitcode ("subb", "a,acc");
4901 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
4903 else /* compiletimeSign */
4905 aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
4910 aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
4912 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
4918 /*-----------------------------------------------------------------*/
4919 /* genMod - generates code for division */
4920 /*-----------------------------------------------------------------*/
4924 operand *left = IC_LEFT (ic);
4925 operand *right = IC_RIGHT (ic);
4926 operand *result = IC_RESULT (ic);
4928 D(emitcode ("; genMod",""));
4930 /* assign the asmops */
4931 aopOp (left, ic, FALSE);
4932 aopOp (right, ic, FALSE);
4933 aopOp (result, ic, TRUE);
4935 /* special cases first */
4937 if (AOP_TYPE (left) == AOP_CRY &&
4938 AOP_TYPE (right) == AOP_CRY)
4940 genModbits (left, right, result);
4944 /* if both are of size == 1 */
4945 if (AOP_SIZE (left) == 1 &&
4946 AOP_SIZE (right) == 1)
4948 genModOneByte (left, right, result);
4952 /* should have been converted to function call */
4956 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4957 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4958 freeAsmop (result, NULL, ic, TRUE);
4961 /*-----------------------------------------------------------------*/
4962 /* genIfxJump :- will create a jump depending on the ifx */
4963 /*-----------------------------------------------------------------*/
4965 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
4968 symbol *tlbl = newiTempLabel (NULL);
4971 D(emitcode ("; genIfxJump",""));
4973 /* if true label then we jump if condition
4977 jlbl = IC_TRUE (ic);
4978 inst = ((strcmp (jval, "a") == 0 ? "jz" :
4979 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
4983 /* false label is present */
4984 jlbl = IC_FALSE (ic);
4985 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
4986 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
4988 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
4989 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
4991 emitcode (inst, "%05d$", tlbl->key + 100);
4992 freeForBranchAsmop (result);
4993 freeForBranchAsmop (right);
4994 freeForBranchAsmop (left);
4995 emitcode ("ljmp", "%05d$", jlbl->key + 100);
4996 emitcode ("", "%05d$:", tlbl->key + 100);
4998 /* mark the icode as generated */
5002 /*-----------------------------------------------------------------*/
5003 /* genCmp :- greater or less than comparison */
5004 /*-----------------------------------------------------------------*/
5006 genCmp (operand * left, operand * right,
5007 operand * result, iCode * ifx, int sign, iCode *ic)
5009 int size, offset = 0;
5010 unsigned long lit = 0L;
5013 D(emitcode ("; genCmp",""));
5015 /* if left & right are bit variables */
5016 if (AOP_TYPE (left) == AOP_CRY &&
5017 AOP_TYPE (right) == AOP_CRY)
5019 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5020 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5024 /* subtract right from left if at the
5025 end the carry flag is set then we know that
5026 left is greater than right */
5027 size = max (AOP_SIZE (left), AOP_SIZE (right));
5029 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5030 if ((size == 1) && !sign &&
5031 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5033 symbol *lbl = newiTempLabel (NULL);
5034 emitcode ("cjne", "%s,%s,%05d$",
5035 aopGet (AOP (left), offset, FALSE, FALSE),
5036 aopGet (AOP (right), offset, FALSE, FALSE),
5038 emitcode ("", "%05d$:", lbl->key + 100);
5042 if (AOP_TYPE (right) == AOP_LIT)
5044 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5045 /* optimize if(x < 0) or if(x >= 0) */
5054 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5055 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5057 genIfxJump (ifx, "acc.7", left, right, result);
5058 freeAsmop (right, NULL, ic, TRUE);
5059 freeAsmop (left, NULL, ic, TRUE);
5064 emitcode ("rlc", "a");
5072 bool pushedB = FALSE;
5073 rightInB = aopGetUsesAcc(AOP (right), offset);
5077 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5079 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5080 if (sign && size == 0)
5082 emitcode ("xrl", "a,#0x80");
5083 if (AOP_TYPE (right) == AOP_LIT)
5085 unsigned long lit = (unsigned long)
5086 floatFromVal (AOP (right)->aopu.aop_lit);
5087 emitcode ("subb", "a,#0x%02x",
5088 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5096 emitcode ("mov", "b,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5098 emitcode ("xrl", "b,#0x80");
5099 emitcode ("subb", "a,b");
5105 emitcode ("subb", "a,b");
5107 emitcode ("subb", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5117 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5118 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5119 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5125 /* if the result is used in the next
5126 ifx conditional branch then generate
5127 code a little differently */
5129 genIfxJump (ifx, "c", NULL, NULL, result);
5132 /* leave the result in acc */
5136 /*-----------------------------------------------------------------*/
5137 /* genCmpGt :- greater than comparison */
5138 /*-----------------------------------------------------------------*/
5140 genCmpGt (iCode * ic, iCode * ifx)
5142 operand *left, *right, *result;
5143 sym_link *letype, *retype;
5146 D(emitcode ("; genCmpGt",""));
5148 left = IC_LEFT (ic);
5149 right = IC_RIGHT (ic);
5150 result = IC_RESULT (ic);
5152 letype = getSpec (operandType (left));
5153 retype = getSpec (operandType (right));
5154 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5155 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5156 /* assign the amsops */
5157 aopOp (left, ic, FALSE);
5158 aopOp (right, ic, FALSE);
5159 aopOp (result, ic, TRUE);
5161 genCmp (right, left, result, ifx, sign, ic);
5163 freeAsmop (result, NULL, ic, TRUE);
5166 /*-----------------------------------------------------------------*/
5167 /* genCmpLt - less than comparisons */
5168 /*-----------------------------------------------------------------*/
5170 genCmpLt (iCode * ic, iCode * ifx)
5172 operand *left, *right, *result;
5173 sym_link *letype, *retype;
5176 D(emitcode ("; genCmpLt",""));
5178 left = IC_LEFT (ic);
5179 right = IC_RIGHT (ic);
5180 result = IC_RESULT (ic);
5182 letype = getSpec (operandType (left));
5183 retype = getSpec (operandType (right));
5184 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5185 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5186 /* assign the amsops */
5187 aopOp (left, ic, FALSE);
5188 aopOp (right, ic, FALSE);
5189 aopOp (result, ic, TRUE);
5191 genCmp (left, right, result, ifx, sign,ic);
5193 freeAsmop (result, NULL, ic, TRUE);
5196 /*-----------------------------------------------------------------*/
5197 /* gencjneshort - compare and jump if not equal */
5198 /*-----------------------------------------------------------------*/
5200 gencjneshort (operand * left, operand * right, symbol * lbl)
5202 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5204 unsigned long lit = 0L;
5206 /* if the left side is a literal or
5207 if the right is in a pointer register and left
5209 if ((AOP_TYPE (left) == AOP_LIT) ||
5210 (AOP_TYPE (left) == AOP_IMMD) ||
5211 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5218 if (AOP_TYPE (right) == AOP_LIT)
5219 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5221 /* if the right side is a literal then anything goes */
5222 if (AOP_TYPE (right) == AOP_LIT &&
5223 AOP_TYPE (left) != AOP_DIR &&
5224 AOP_TYPE (left) != AOP_IMMD)
5228 emitcode ("cjne", "%s,%s,%05d$",
5229 aopGet (AOP (left), offset, FALSE, FALSE),
5230 aopGet (AOP (right), offset, FALSE, FALSE),
5236 /* if the right side is in a register or in direct space or
5237 if the left is a pointer register & right is not */
5238 else if (AOP_TYPE (right) == AOP_REG ||
5239 AOP_TYPE (right) == AOP_DIR ||
5240 AOP_TYPE (right) == AOP_LIT ||
5241 AOP_TYPE (right) == AOP_IMMD ||
5242 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5243 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5247 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5248 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5249 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5250 emitcode ("jnz", "%05d$", lbl->key + 100);
5252 emitcode ("cjne", "a,%s,%05d$",
5253 aopGet (AOP (right), offset, FALSE, TRUE),
5260 /* right is a pointer reg need both a & b */
5264 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5265 wassertl(!BINUSE, "B was in use");
5266 l = aopGet (AOP (left), offset, FALSE, FALSE);
5267 if (strcmp (l, "b"))
5268 emitcode ("mov", "b,%s", l);
5269 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5270 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5276 /*-----------------------------------------------------------------*/
5277 /* gencjne - compare and jump if not equal */
5278 /*-----------------------------------------------------------------*/
5280 gencjne (operand * left, operand * right, symbol * lbl)
5282 symbol *tlbl = newiTempLabel (NULL);
5284 gencjneshort (left, right, lbl);
5286 emitcode ("mov", "a,%s", one);
5287 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5288 emitcode ("", "%05d$:", lbl->key + 100);
5289 emitcode ("clr", "a");
5290 emitcode ("", "%05d$:", tlbl->key + 100);
5293 /*-----------------------------------------------------------------*/
5294 /* genCmpEq - generates code for equal to */
5295 /*-----------------------------------------------------------------*/
5297 genCmpEq (iCode * ic, iCode * ifx)
5299 operand *left, *right, *result;
5301 D(emitcode ("; genCmpEq",""));
5303 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5304 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5305 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5307 /* if literal, literal on the right or
5308 if the right is in a pointer register and left
5310 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5311 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5313 operand *t = IC_RIGHT (ic);
5314 IC_RIGHT (ic) = IC_LEFT (ic);
5318 if (ifx && !AOP_SIZE (result))
5321 /* if they are both bit variables */
5322 if (AOP_TYPE (left) == AOP_CRY &&
5323 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5325 if (AOP_TYPE (right) == AOP_LIT)
5327 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5330 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5331 emitcode ("cpl", "c");
5335 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5339 emitcode ("clr", "c");
5341 /* AOP_TYPE(right) == AOP_CRY */
5345 symbol *lbl = newiTempLabel (NULL);
5346 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5347 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5348 emitcode ("cpl", "c");
5349 emitcode ("", "%05d$:", (lbl->key + 100));
5351 /* if true label then we jump if condition
5353 tlbl = newiTempLabel (NULL);
5356 emitcode ("jnc", "%05d$", tlbl->key + 100);
5357 freeForBranchAsmop (result);
5358 freeForBranchAsmop (right);
5359 freeForBranchAsmop (left);
5360 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5364 emitcode ("jc", "%05d$", tlbl->key + 100);
5365 freeForBranchAsmop (result);
5366 freeForBranchAsmop (right);
5367 freeForBranchAsmop (left);
5368 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5370 emitcode ("", "%05d$:", tlbl->key + 100);
5374 tlbl = newiTempLabel (NULL);
5375 gencjneshort (left, right, tlbl);
5378 freeForBranchAsmop (result);
5379 freeForBranchAsmop (right);
5380 freeForBranchAsmop (left);
5381 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5382 emitcode ("", "%05d$:", tlbl->key + 100);
5386 symbol *lbl = newiTempLabel (NULL);
5387 emitcode ("sjmp", "%05d$", lbl->key + 100);
5388 emitcode ("", "%05d$:", tlbl->key + 100);
5389 freeForBranchAsmop (result);
5390 freeForBranchAsmop (right);
5391 freeForBranchAsmop (left);
5392 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5393 emitcode ("", "%05d$:", lbl->key + 100);
5396 /* mark the icode as generated */
5401 /* if they are both bit variables */
5402 if (AOP_TYPE (left) == AOP_CRY &&
5403 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5405 if (AOP_TYPE (right) == AOP_LIT)
5407 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5410 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5411 emitcode ("cpl", "c");
5415 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5419 emitcode ("clr", "c");
5421 /* AOP_TYPE(right) == AOP_CRY */
5425 symbol *lbl = newiTempLabel (NULL);
5426 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5427 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5428 emitcode ("cpl", "c");
5429 emitcode ("", "%05d$:", (lbl->key + 100));
5432 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5439 genIfxJump (ifx, "c", left, right, result);
5442 /* if the result is used in an arithmetic operation
5443 then put the result in place */
5448 gencjne (left, right, newiTempLabel (NULL));
5449 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5451 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
5456 genIfxJump (ifx, "a", left, right, result);
5459 /* if the result is used in an arithmetic operation
5460 then put the result in place */
5461 if (AOP_TYPE (result) != AOP_CRY)
5463 /* leave the result in acc */
5467 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5468 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5469 freeAsmop (result, NULL, ic, TRUE);
5472 /*-----------------------------------------------------------------*/
5473 /* ifxForOp - returns the icode containing the ifx for operand */
5474 /*-----------------------------------------------------------------*/
5476 ifxForOp (operand * op, iCode * ic)
5478 /* if true symbol then needs to be assigned */
5479 if (IS_TRUE_SYMOP (op))
5482 /* if this has register type condition and
5483 the next instruction is ifx with the same operand
5484 and live to of the operand is upto the ifx only then */
5486 ic->next->op == IFX &&
5487 IC_COND (ic->next)->key == op->key &&
5488 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5494 /*-----------------------------------------------------------------*/
5495 /* hasInc - operand is incremented before any other use */
5496 /*-----------------------------------------------------------------*/
5498 hasInc (operand *op, iCode *ic,int osize)
5500 sym_link *type = operandType(op);
5501 sym_link *retype = getSpec (type);
5502 iCode *lic = ic->next;
5505 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5506 if (!IS_SYMOP(op)) return NULL;
5508 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5509 if (IS_AGGREGATE(type->next)) return NULL;
5510 if (osize != (isize = getSize(type->next))) return NULL;
5513 /* if operand of the form op = op + <sizeof *op> */
5514 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5515 isOperandEqual(IC_RESULT(lic),op) &&
5516 isOperandLiteral(IC_RIGHT(lic)) &&
5517 operandLitValue(IC_RIGHT(lic)) == isize) {
5520 /* if the operand used or deffed */
5521 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5524 /* if GOTO or IFX */
5525 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5531 /*-----------------------------------------------------------------*/
5532 /* genAndOp - for && operation */
5533 /*-----------------------------------------------------------------*/
5535 genAndOp (iCode * ic)
5537 operand *left, *right, *result;
5540 D(emitcode ("; genAndOp",""));
5542 /* note here that && operations that are in an
5543 if statement are taken away by backPatchLabels
5544 only those used in arthmetic operations remain */
5545 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5546 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5547 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5549 /* if both are bit variables */
5550 if (AOP_TYPE (left) == AOP_CRY &&
5551 AOP_TYPE (right) == AOP_CRY)
5553 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5554 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5559 tlbl = newiTempLabel (NULL);
5561 emitcode ("jz", "%05d$", tlbl->key + 100);
5563 emitcode ("", "%05d$:", tlbl->key + 100);
5567 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5568 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5569 freeAsmop (result, NULL, ic, TRUE);
5573 /*-----------------------------------------------------------------*/
5574 /* genOrOp - for || operation */
5575 /*-----------------------------------------------------------------*/
5577 genOrOp (iCode * ic)
5579 operand *left, *right, *result;
5582 D(emitcode ("; genOrOp",""));
5584 /* note here that || operations that are in an
5585 if statement are taken away by backPatchLabels
5586 only those used in arthmetic operations remain */
5587 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5588 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5589 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5591 /* if both are bit variables */
5592 if (AOP_TYPE (left) == AOP_CRY &&
5593 AOP_TYPE (right) == AOP_CRY)
5595 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5596 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
5601 tlbl = newiTempLabel (NULL);
5603 emitcode ("jnz", "%05d$", tlbl->key + 100);
5605 emitcode ("", "%05d$:", tlbl->key + 100);
5609 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5610 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5611 freeAsmop (result, NULL, ic, TRUE);
5614 /*-----------------------------------------------------------------*/
5615 /* isLiteralBit - test if lit == 2^n */
5616 /*-----------------------------------------------------------------*/
5618 isLiteralBit (unsigned long lit)
5620 unsigned long pw[32] =
5621 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
5622 0x100L, 0x200L, 0x400L, 0x800L,
5623 0x1000L, 0x2000L, 0x4000L, 0x8000L,
5624 0x10000L, 0x20000L, 0x40000L, 0x80000L,
5625 0x100000L, 0x200000L, 0x400000L, 0x800000L,
5626 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
5627 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
5630 for (idx = 0; idx < 32; idx++)
5636 /*-----------------------------------------------------------------*/
5637 /* continueIfTrue - */
5638 /*-----------------------------------------------------------------*/
5640 continueIfTrue (iCode * ic)
5643 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5647 /*-----------------------------------------------------------------*/
5649 /*-----------------------------------------------------------------*/
5651 jumpIfTrue (iCode * ic)
5654 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5658 /*-----------------------------------------------------------------*/
5659 /* jmpTrueOrFalse - */
5660 /*-----------------------------------------------------------------*/
5662 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
5664 // ugly but optimized by peephole
5667 symbol *nlbl = newiTempLabel (NULL);
5668 emitcode ("sjmp", "%05d$", nlbl->key + 100);
5669 emitcode ("", "%05d$:", tlbl->key + 100);
5670 freeForBranchAsmop (result);
5671 freeForBranchAsmop (right);
5672 freeForBranchAsmop (left);
5673 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
5674 emitcode ("", "%05d$:", nlbl->key + 100);
5678 freeForBranchAsmop (result);
5679 freeForBranchAsmop (right);
5680 freeForBranchAsmop (left);
5681 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
5682 emitcode ("", "%05d$:", tlbl->key + 100);
5687 /*-----------------------------------------------------------------*/
5688 /* genAnd - code for and */
5689 /*-----------------------------------------------------------------*/
5691 genAnd (iCode * ic, iCode * ifx)
5693 operand *left, *right, *result;
5694 int size, offset = 0;
5695 unsigned long lit = 0L;
5699 D(emitcode ("; genAnd",""));
5701 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5702 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5703 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5706 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5708 AOP_TYPE (left), AOP_TYPE (right));
5709 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5711 AOP_SIZE (left), AOP_SIZE (right));
5714 /* if left is a literal & right is not then exchange them */
5715 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5716 AOP_NEEDSACC (left))
5718 operand *tmp = right;
5723 /* if result = right then exchange left and right */
5724 if (sameRegs (AOP (result), AOP (right)))
5726 operand *tmp = right;
5731 /* if right is bit then exchange them */
5732 if (AOP_TYPE (right) == AOP_CRY &&
5733 AOP_TYPE (left) != AOP_CRY)
5735 operand *tmp = right;
5739 if (AOP_TYPE (right) == AOP_LIT)
5740 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5742 size = AOP_SIZE (result);
5745 // result = bit & yy;
5746 if (AOP_TYPE (left) == AOP_CRY)
5748 // c = bit & literal;
5749 if (AOP_TYPE (right) == AOP_LIT)
5753 if (size && sameRegs (AOP (result), AOP (left)))
5756 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5761 if (size && (AOP_TYPE (result) == AOP_CRY))
5763 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
5766 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5771 emitcode ("clr", "c");
5776 if (AOP_TYPE (right) == AOP_CRY)
5779 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5780 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5785 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
5787 emitcode ("rrc", "a");
5788 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5796 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5797 genIfxJump (ifx, "c", left, right, result);
5801 // if(val & 0xZZ) - size = 0, ifx != FALSE -
5802 // bit = val & 0xZZ - size = 1, ifx = FALSE -
5803 if ((AOP_TYPE (right) == AOP_LIT) &&
5804 (AOP_TYPE (result) == AOP_CRY) &&
5805 (AOP_TYPE (left) != AOP_CRY))
5807 int posbit = isLiteralBit (lit);
5812 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
5816 switch (posbit & 0x07)
5818 case 0: emitcode ("rrc", "a");
5820 case 7: emitcode ("rlc", "a");
5822 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
5831 SNPRINTF (buffer, sizeof(buffer),
5832 "acc.%d", posbit & 0x07);
5833 genIfxJump (ifx, buffer, left, right, result);
5836 {// what is this case? just found it in ds390/gen.c
5837 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
5844 symbol *tlbl = newiTempLabel (NULL);
5845 int sizel = AOP_SIZE (left);
5847 emitcode ("setb", "c");
5850 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
5852 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5854 if ((posbit = isLiteralBit (bytelit)) != 0)
5855 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
5858 if (bytelit != 0x0FFL)
5859 emitcode ("anl", "a,%s",
5860 aopGet (AOP (right), offset, FALSE, TRUE));
5861 emitcode ("jnz", "%05d$", tlbl->key + 100);
5866 // bit = left & literal
5869 emitcode ("clr", "c");
5870 emitcode ("", "%05d$:", tlbl->key + 100);
5872 // if(left & literal)
5876 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5878 emitcode ("", "%05d$:", tlbl->key + 100);
5886 /* if left is same as result */
5887 if (sameRegs (AOP (result), AOP (left)))
5889 for (; size--; offset++)
5891 if (AOP_TYPE (right) == AOP_LIT)
5893 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5894 if (bytelit == 0x0FF)
5896 /* dummy read of volatile operand */
5897 if (isOperandVolatile (left, FALSE))
5898 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5902 else if (bytelit == 0)
5904 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
5906 else if (IS_AOP_PREG (result))
5908 MOVA (aopGet (AOP (left), offset, FALSE, TRUE));
5909 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5910 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5913 emitcode ("anl", "%s,%s",
5914 aopGet (AOP (left), offset, FALSE, TRUE),
5915 aopGet (AOP (right), offset, FALSE, FALSE));
5919 if (AOP_TYPE (left) == AOP_ACC)
5920 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5923 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5924 if (IS_AOP_PREG (result))
5926 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5927 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
5930 emitcode ("anl", "%s,a",
5931 aopGet (AOP (left), offset, FALSE, TRUE));
5938 // left & result in different registers
5939 if (AOP_TYPE (result) == AOP_CRY)
5942 // if(size), result in bit
5943 // if(!size && ifx), conditional oper: if(left & right)
5944 symbol *tlbl = newiTempLabel (NULL);
5945 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
5947 emitcode ("setb", "c");
5950 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5951 emitcode ("anl", "a,%s",
5952 aopGet (AOP (right), offset, FALSE, FALSE));
5954 if (AOP_TYPE(left)==AOP_ACC) {
5955 bool pushedB = pushB ();
5956 emitcode("mov", "b,a");
5957 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5958 emitcode("anl", "a,b");
5961 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5962 emitcode ("anl", "a,%s",
5963 aopGet (AOP (left), offset, FALSE, FALSE));
5966 emitcode ("jnz", "%05d$", tlbl->key + 100);
5972 emitcode ("", "%05d$:", tlbl->key + 100);
5976 jmpTrueOrFalse (ifx, tlbl, left, right, result);
5978 emitcode ("", "%05d$:", tlbl->key + 100);
5982 for (; (size--); offset++)
5985 // result = left & right
5986 if (AOP_TYPE (right) == AOP_LIT)
5988 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
5989 if (bytelit == 0x0FF)
5991 aopPut (AOP (result),
5992 aopGet (AOP (left), offset, FALSE, FALSE),
5994 isOperandVolatile (result, FALSE));
5997 else if (bytelit == 0)
5999 /* dummy read of volatile operand */
6000 if (isOperandVolatile (left, FALSE))
6001 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6002 aopPut (AOP (result), zero, offset, isOperandVolatile (result, FALSE));
6006 // faster than result <- left, anl result,right
6007 // and better if result is SFR
6008 if (AOP_TYPE (left) == AOP_ACC)
6009 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6012 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6013 emitcode ("anl", "a,%s",
6014 aopGet (AOP (left), offset, FALSE, FALSE));
6016 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6022 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6023 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6024 freeAsmop (result, NULL, ic, TRUE);
6027 /*-----------------------------------------------------------------*/
6028 /* genOr - code for or */
6029 /*-----------------------------------------------------------------*/
6031 genOr (iCode * ic, iCode * ifx)
6033 operand *left, *right, *result;
6034 int size, offset = 0;
6035 unsigned long lit = 0L;
6038 D(emitcode ("; genOr",""));
6040 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6041 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6042 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6045 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6047 AOP_TYPE (left), AOP_TYPE (right));
6048 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6050 AOP_SIZE (left), AOP_SIZE (right));
6053 /* if left is a literal & right is not then exchange them */
6054 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6055 AOP_NEEDSACC (left))
6057 operand *tmp = right;
6062 /* if result = right then exchange them */
6063 if (sameRegs (AOP (result), AOP (right)))
6065 operand *tmp = right;
6070 /* if right is bit then exchange them */
6071 if (AOP_TYPE (right) == AOP_CRY &&
6072 AOP_TYPE (left) != AOP_CRY)
6074 operand *tmp = right;
6078 if (AOP_TYPE (right) == AOP_LIT)
6079 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6081 size = AOP_SIZE (result);
6085 if (AOP_TYPE (left) == AOP_CRY)
6087 if (AOP_TYPE (right) == AOP_LIT)
6089 // c = bit | literal;
6092 // lit != 0 => result = 1
6093 if (AOP_TYPE (result) == AOP_CRY)
6096 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6098 continueIfTrue (ifx);
6101 emitcode ("setb", "c");
6105 // lit == 0 => result = left
6106 if (size && sameRegs (AOP (result), AOP (left)))
6108 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6113 if (AOP_TYPE (right) == AOP_CRY)
6116 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6117 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6122 symbol *tlbl = newiTempLabel (NULL);
6123 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6124 emitcode ("setb", "c");
6125 emitcode ("jb", "%s,%05d$",
6126 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6128 emitcode ("jnz", "%05d$", tlbl->key + 100);
6129 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6131 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6137 emitcode ("", "%05d$:", tlbl->key + 100);
6146 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6147 genIfxJump (ifx, "c", left, right, result);
6151 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6152 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6153 if ((AOP_TYPE (right) == AOP_LIT) &&
6154 (AOP_TYPE (result) == AOP_CRY) &&
6155 (AOP_TYPE (left) != AOP_CRY))
6161 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6163 continueIfTrue (ifx);
6168 // lit = 0, result = boolean(left)
6170 emitcode ("setb", "c");
6174 symbol *tlbl = newiTempLabel (NULL);
6175 emitcode ("jnz", "%05d$", tlbl->key + 100);
6177 emitcode ("", "%05d$:", tlbl->key + 100);
6181 genIfxJump (ifx, "a", left, right, result);
6189 /* if left is same as result */
6190 if (sameRegs (AOP (result), AOP (left)))
6192 for (; size--; offset++)
6194 if (AOP_TYPE (right) == AOP_LIT)
6196 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6199 /* dummy read of volatile operand */
6200 if (isOperandVolatile (left, FALSE))
6201 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6205 else if (bytelit == 0x0FF)
6207 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6209 else if (IS_AOP_PREG (left))
6211 MOVA (aopGet (AOP (left), offset, FALSE, TRUE));
6212 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6213 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6217 emitcode ("orl", "%s,%s",
6218 aopGet (AOP (left), offset, FALSE, TRUE),
6219 aopGet (AOP (right), offset, FALSE, FALSE));
6224 if (AOP_TYPE (left) == AOP_ACC)
6225 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6228 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6229 if (IS_AOP_PREG (left))
6231 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6232 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6236 emitcode ("orl", "%s,a",
6237 aopGet (AOP (left), offset, FALSE, TRUE));
6245 // left & result in different registers
6246 if (AOP_TYPE (result) == AOP_CRY)
6249 // if(size), result in bit
6250 // if(!size && ifx), conditional oper: if(left | right)
6251 symbol *tlbl = newiTempLabel (NULL);
6252 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6254 emitcode ("setb", "c");
6257 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6258 emitcode ("orl", "a,%s",
6259 aopGet (AOP (right), offset, FALSE, FALSE));
6261 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6262 emitcode ("orl", "a,%s",
6263 aopGet (AOP (left), offset, FALSE, FALSE));
6265 emitcode ("jnz", "%05d$", tlbl->key + 100);
6271 emitcode ("", "%05d$:", tlbl->key + 100);
6275 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6277 emitcode ("", "%05d$:", tlbl->key + 100);
6281 for (; (size--); offset++)
6284 // result = left | right
6285 if (AOP_TYPE (right) == AOP_LIT)
6287 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6290 aopPut (AOP (result),
6291 aopGet (AOP (left), offset, FALSE, FALSE),
6293 isOperandVolatile (result, FALSE));
6296 else if (bytelit == 0x0FF)
6298 /* dummy read of volatile operand */
6299 if (isOperandVolatile (left, FALSE))
6300 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6301 aopPut (AOP (result), "#0xFF", offset, isOperandVolatile (result, FALSE));
6305 // faster than result <- left, anl result,right
6306 // and better if result is SFR
6307 if (AOP_TYPE (left) == AOP_ACC)
6308 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6311 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6312 emitcode ("orl", "a,%s",
6313 aopGet (AOP (left), offset, FALSE, FALSE));
6315 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6321 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6322 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6323 freeAsmop (result, NULL, ic, TRUE);
6326 /*-----------------------------------------------------------------*/
6327 /* genXor - code for xclusive or */
6328 /*-----------------------------------------------------------------*/
6330 genXor (iCode * ic, iCode * ifx)
6332 operand *left, *right, *result;
6333 int size, offset = 0;
6334 unsigned long lit = 0L;
6337 D(emitcode ("; genXor",""));
6339 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6340 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6341 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6344 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6346 AOP_TYPE (left), AOP_TYPE (right));
6347 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6349 AOP_SIZE (left), AOP_SIZE (right));
6352 /* if left is a literal & right is not ||
6353 if left needs acc & right does not */
6354 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6355 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6357 operand *tmp = right;
6362 /* if result = right then exchange them */
6363 if (sameRegs (AOP (result), AOP (right)))
6365 operand *tmp = right;
6370 /* if right is bit then exchange them */
6371 if (AOP_TYPE (right) == AOP_CRY &&
6372 AOP_TYPE (left) != AOP_CRY)
6374 operand *tmp = right;
6378 if (AOP_TYPE (right) == AOP_LIT)
6379 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6381 size = AOP_SIZE (result);
6385 if (AOP_TYPE (left) == AOP_CRY)
6387 if (AOP_TYPE (right) == AOP_LIT)
6389 // c = bit & literal;
6392 // lit>>1 != 0 => result = 1
6393 if (AOP_TYPE (result) == AOP_CRY)
6396 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6398 continueIfTrue (ifx);
6401 emitcode ("setb", "c");
6408 // lit == 0, result = left
6409 if (size && sameRegs (AOP (result), AOP (left)))
6411 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6415 // lit == 1, result = not(left)
6416 if (size && sameRegs (AOP (result), AOP (left)))
6418 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6423 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6424 emitcode ("cpl", "c");
6433 symbol *tlbl = newiTempLabel (NULL);
6434 if (AOP_TYPE (right) == AOP_CRY)
6437 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6441 int sizer = AOP_SIZE (right);
6443 // if val>>1 != 0, result = 1
6444 emitcode ("setb", "c");
6447 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
6449 // test the msb of the lsb
6450 emitcode ("anl", "a,#0xfe");
6451 emitcode ("jnz", "%05d$", tlbl->key + 100);
6455 emitcode ("rrc", "a");
6457 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6458 emitcode ("cpl", "c");
6459 emitcode ("", "%05d$:", (tlbl->key + 100));
6466 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6467 genIfxJump (ifx, "c", left, right, result);
6471 /* if left is same as result */
6472 if (sameRegs (AOP (result), AOP (left)))
6474 for (; size--; offset++)
6476 if (AOP_TYPE (right) == AOP_LIT)
6478 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6481 /* dummy read of volatile operand */
6482 if (isOperandVolatile (left, FALSE))
6483 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6487 else if (IS_AOP_PREG (left))
6489 MOVA (aopGet (AOP (left), offset, FALSE, TRUE));
6490 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6491 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6495 emitcode ("xrl", "%s,%s",
6496 aopGet (AOP (left), offset, FALSE, TRUE),
6497 aopGet (AOP (right), offset, FALSE, FALSE));
6502 if (AOP_TYPE (left) == AOP_ACC)
6503 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6506 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6507 if (IS_AOP_PREG (left))
6509 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
6510 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6513 emitcode ("xrl", "%s,a",
6514 aopGet (AOP (left), offset, FALSE, TRUE));
6521 // left & result in different registers
6522 if (AOP_TYPE (result) == AOP_CRY)
6525 // if(size), result in bit
6526 // if(!size && ifx), conditional oper: if(left ^ right)
6527 symbol *tlbl = newiTempLabel (NULL);
6528 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6530 emitcode ("setb", "c");
6533 if ((AOP_TYPE (right) == AOP_LIT) &&
6534 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
6536 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
6540 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6541 emitcode ("xrl", "a,%s",
6542 aopGet (AOP (right), offset, FALSE, FALSE));
6544 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6545 emitcode ("xrl", "a,%s",
6546 aopGet (AOP (left), offset, FALSE, FALSE));
6549 emitcode ("jnz", "%05d$", tlbl->key + 100);
6555 emitcode ("", "%05d$:", tlbl->key + 100);
6559 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6563 for (; (size--); offset++)
6566 // result = left & right
6567 if (AOP_TYPE (right) == AOP_LIT)
6569 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6572 aopPut (AOP (result),
6573 aopGet (AOP (left), offset, FALSE, FALSE),
6575 isOperandVolatile (result, FALSE));
6579 // faster than result <- left, anl result,right
6580 // and better if result is SFR
6581 if (AOP_TYPE (left) == AOP_ACC)
6582 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
6585 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
6586 emitcode ("xrl", "a,%s",
6587 aopGet (AOP (left), offset, FALSE, TRUE));
6589 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
6595 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6596 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6597 freeAsmop (result, NULL, ic, TRUE);
6600 /*-----------------------------------------------------------------*/
6601 /* genInline - write the inline code out */
6602 /*-----------------------------------------------------------------*/
6604 genInline (iCode * ic)
6606 char *buffer, *bp, *bp1;
6608 D(emitcode ("; genInline",""));
6610 _G.inLine += (!options.asmpeep);
6612 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6613 strcpy (buffer, IC_INLINE (ic));
6615 /* emit each line as a code */
6626 /* Add \n for labels, not dirs such as c:\mydir */
6627 if ( (*bp == ':') && (isspace(bp[1])) )
6641 /* emitcode("",buffer); */
6642 _G.inLine -= (!options.asmpeep);
6645 /*-----------------------------------------------------------------*/
6646 /* genRRC - rotate right with carry */
6647 /*-----------------------------------------------------------------*/
6651 operand *left, *result;
6652 int size, offset = 0;
6655 D(emitcode ("; genRRC",""));
6657 /* rotate right with carry */
6658 left = IC_LEFT (ic);
6659 result = IC_RESULT (ic);
6660 aopOp (left, ic, FALSE);
6661 aopOp (result, ic, FALSE);
6663 /* move it to the result */
6664 size = AOP_SIZE (result);
6666 if (size == 1) { /* special case for 1 byte */
6667 l = aopGet (AOP (left), offset, FALSE, FALSE);
6669 emitcode ("rr", "a");
6672 /* no need to clear carry, bit7 will be written later */
6675 l = aopGet (AOP (left), offset, FALSE, FALSE);
6677 emitcode ("rrc", "a");
6678 if (AOP_SIZE (result) > 1)
6679 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
6681 /* now we need to put the carry into the
6682 highest order byte of the result */
6683 if (AOP_SIZE (result) > 1)
6685 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
6688 emitcode ("mov", "acc.7,c");
6690 aopPut (AOP (result), "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
6691 freeAsmop (left, NULL, ic, TRUE);
6692 freeAsmop (result, NULL, ic, TRUE);
6695 /*-----------------------------------------------------------------*/
6696 /* genRLC - generate code for rotate left with carry */
6697 /*-----------------------------------------------------------------*/
6701 operand *left, *result;
6702 int size, offset = 0;
6705 D(emitcode ("; genRLC",""));
6707 /* rotate right with carry */
6708 left = IC_LEFT (ic);
6709 result = IC_RESULT (ic);
6710 aopOp (left, ic, FALSE);
6711 aopOp (result, ic, FALSE);
6713 /* move it to the result */
6714 size = AOP_SIZE (result);
6718 l = aopGet (AOP (left), offset, FALSE, FALSE);
6720 if (size == 0) { /* special case for 1 byte */
6724 emitcode("rlc","a"); /* bit0 will be written later */
6725 if (AOP_SIZE (result) > 1)
6726 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6729 l = aopGet (AOP (left), offset, FALSE, FALSE);
6731 emitcode ("rlc", "a");
6732 if (AOP_SIZE (result) > 1)
6733 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
6736 /* now we need to put the carry into the
6737 highest order byte of the result */
6738 if (AOP_SIZE (result) > 1)
6740 l = aopGet (AOP (result), 0, FALSE, FALSE);
6743 emitcode ("mov", "acc.0,c");
6745 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6746 freeAsmop (left, NULL, ic, TRUE);
6747 freeAsmop (result, NULL, ic, TRUE);
6750 /*-----------------------------------------------------------------*/
6751 /* genGetHbit - generates code get highest order bit */
6752 /*-----------------------------------------------------------------*/
6754 genGetHbit (iCode * ic)
6756 operand *left, *result;
6758 D(emitcode ("; genGetHbit",""));
6760 left = IC_LEFT (ic);
6761 result = IC_RESULT (ic);
6762 aopOp (left, ic, FALSE);
6763 aopOp (result, ic, FALSE);
6765 /* get the highest order byte into a */
6766 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
6767 if (AOP_TYPE (result) == AOP_CRY)
6769 emitcode ("rlc", "a");
6774 emitcode ("rl", "a");
6775 emitcode ("anl", "a,#0x01");
6780 freeAsmop (left, NULL, ic, TRUE);
6781 freeAsmop (result, NULL, ic, TRUE);
6784 /*-----------------------------------------------------------------*/
6785 /* genSwap - generates code to swap nibbles or bytes */
6786 /*-----------------------------------------------------------------*/
6788 genSwap (iCode * ic)
6790 operand *left, *result;
6792 D(emitcode ("; genSwap",""));
6794 left = IC_LEFT (ic);
6795 result = IC_RESULT (ic);
6796 aopOp (left, ic, FALSE);
6797 aopOp (result, ic, FALSE);
6799 switch (AOP_SIZE (left))
6801 case 1: /* swap nibbles in byte */
6802 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6803 emitcode ("swap", "a");
6804 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
6806 case 2: /* swap bytes in word */
6807 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
6809 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6810 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6811 0, isOperandVolatile (result, FALSE));
6812 aopPut (AOP (result), "a", 1, isOperandVolatile (result, FALSE));
6814 else if (operandsEqu (left, result))
6817 bool pushedB = FALSE, leftInB = FALSE;
6819 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
6820 if (aopGetUsesAcc(AOP (left), 1) || aopGetUsesAcc(AOP (result), 0))
6823 emitcode ("mov", "b,a");
6827 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6828 0, isOperandVolatile (result, FALSE));
6829 aopPut (AOP (result), reg, 1, isOperandVolatile (result, FALSE));
6836 aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE),
6837 0, isOperandVolatile (result, FALSE));
6838 aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE),
6839 1, isOperandVolatile (result, FALSE));
6843 wassertl(FALSE, "unsupported SWAP operand size");
6846 freeAsmop (left, NULL, ic, TRUE);
6847 freeAsmop (result, NULL, ic, TRUE);
6851 /*-----------------------------------------------------------------*/
6852 /* AccRol - rotate left accumulator by known count */
6853 /*-----------------------------------------------------------------*/
6855 AccRol (int shCount)
6857 shCount &= 0x0007; // shCount : 0..7
6864 emitcode ("rl", "a");
6867 emitcode ("rl", "a");
6868 emitcode ("rl", "a");
6871 emitcode ("swap", "a");
6872 emitcode ("rr", "a");
6875 emitcode ("swap", "a");
6878 emitcode ("swap", "a");
6879 emitcode ("rl", "a");
6882 emitcode ("rr", "a");
6883 emitcode ("rr", "a");
6886 emitcode ("rr", "a");
6891 /*-----------------------------------------------------------------*/
6892 /* AccLsh - left shift accumulator by known count */
6893 /*-----------------------------------------------------------------*/
6895 AccLsh (int shCount)
6900 emitcode ("add", "a,acc");
6901 else if (shCount == 2)
6903 emitcode ("add", "a,acc");
6904 emitcode ("add", "a,acc");
6908 /* rotate left accumulator */
6910 /* and kill the lower order bits */
6911 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
6916 /*-----------------------------------------------------------------*/
6917 /* AccRsh - right shift accumulator by known count */
6918 /*-----------------------------------------------------------------*/
6920 AccRsh (int shCount)
6927 emitcode ("rrc", "a");
6931 /* rotate right accumulator */
6932 AccRol (8 - shCount);
6933 /* and kill the higher order bits */
6934 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6939 /*-----------------------------------------------------------------*/
6940 /* AccSRsh - signed right shift accumulator by known count */
6941 /*-----------------------------------------------------------------*/
6943 AccSRsh (int shCount)
6950 emitcode ("mov", "c,acc.7");
6951 emitcode ("rrc", "a");
6953 else if (shCount == 2)
6955 emitcode ("mov", "c,acc.7");
6956 emitcode ("rrc", "a");
6957 emitcode ("mov", "c,acc.7");
6958 emitcode ("rrc", "a");
6962 tlbl = newiTempLabel (NULL);
6963 /* rotate right accumulator */
6964 AccRol (8 - shCount);
6965 /* and kill the higher order bits */
6966 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
6967 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
6968 emitcode ("orl", "a,#0x%02x",
6969 (unsigned char) ~SRMask[shCount]);
6970 emitcode ("", "%05d$:", tlbl->key + 100);
6975 /*-----------------------------------------------------------------*/
6976 /* shiftR1Left2Result - shift right one byte from left to result */
6977 /*-----------------------------------------------------------------*/
6979 shiftR1Left2Result (operand * left, int offl,
6980 operand * result, int offr,
6981 int shCount, int sign)
6983 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6984 /* shift right accumulator */
6989 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
6992 /*-----------------------------------------------------------------*/
6993 /* shiftL1Left2Result - shift left one byte from left to result */
6994 /*-----------------------------------------------------------------*/
6996 shiftL1Left2Result (operand * left, int offl,
6997 operand * result, int offr, int shCount)
7000 l = aopGet (AOP (left), offl, FALSE, FALSE);
7002 /* shift left accumulator */
7004 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7007 /*-----------------------------------------------------------------*/
7008 /* movLeft2Result - move byte from left to result */
7009 /*-----------------------------------------------------------------*/
7011 movLeft2Result (operand * left, int offl,
7012 operand * result, int offr, int sign)
7015 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7017 l = aopGet (AOP (left), offl, FALSE, FALSE);
7019 if (*l == '@' && (IS_AOP_PREG (result)))
7021 emitcode ("mov", "a,%s", l);
7022 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7027 aopPut (AOP (result), l, offr, isOperandVolatile (result, FALSE));
7030 /* MSB sign in acc.7 ! */
7031 if (getDataSize (left) == offl + 1)
7033 emitcode ("mov", "a,%s", l);
7034 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7041 /*-----------------------------------------------------------------*/
7042 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7043 /*-----------------------------------------------------------------*/
7047 emitcode ("rrc", "a");
7048 emitcode ("xch", "a,%s", x);
7049 emitcode ("rrc", "a");
7050 emitcode ("xch", "a,%s", x);
7053 /*-----------------------------------------------------------------*/
7054 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7055 /*-----------------------------------------------------------------*/
7059 emitcode ("xch", "a,%s", x);
7060 emitcode ("rlc", "a");
7061 emitcode ("xch", "a,%s", x);
7062 emitcode ("rlc", "a");
7065 /*-----------------------------------------------------------------*/
7066 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7067 /*-----------------------------------------------------------------*/
7071 emitcode ("xch", "a,%s", x);
7072 emitcode ("add", "a,acc");
7073 emitcode ("xch", "a,%s", x);
7074 emitcode ("rlc", "a");
7077 /*-----------------------------------------------------------------*/
7078 /* AccAXLsh - left shift a:x by known count (0..7) */
7079 /*-----------------------------------------------------------------*/
7081 AccAXLsh (char *x, int shCount)
7096 case 5: // AAAAABBB:CCCCCDDD
7098 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7100 emitcode ("anl", "a,#0x%02x",
7101 SLMask[shCount]); // BBB00000:CCCCCDDD
7103 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7105 AccRol (shCount); // DDDCCCCC:BBB00000
7107 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7109 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7111 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7113 emitcode ("anl", "a,#0x%02x",
7114 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7116 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7118 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7121 case 6: // AAAAAABB:CCCCCCDD
7122 emitcode ("anl", "a,#0x%02x",
7123 SRMask[shCount]); // 000000BB:CCCCCCDD
7124 emitcode ("mov", "c,acc.0"); // c = B
7125 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7127 AccAXRrl1 (x); // BCCCCCCD:D000000B
7128 AccAXRrl1 (x); // BBCCCCCC:DD000000
7130 emitcode("rrc","a");
7131 emitcode("xch","a,%s", x);
7132 emitcode("rrc","a");
7133 emitcode("mov","c,acc.0"); //<< get correct bit
7134 emitcode("xch","a,%s", x);
7136 emitcode("rrc","a");
7137 emitcode("xch","a,%s", x);
7138 emitcode("rrc","a");
7139 emitcode("xch","a,%s", x);
7142 case 7: // a:x <<= 7
7144 emitcode ("anl", "a,#0x%02x",
7145 SRMask[shCount]); // 0000000B:CCCCCCCD
7147 emitcode ("mov", "c,acc.0"); // c = B
7149 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7151 AccAXRrl1 (x); // BCCCCCCC:D0000000
7159 /*-----------------------------------------------------------------*/
7160 /* AccAXRsh - right shift a:x known count (0..7) */
7161 /*-----------------------------------------------------------------*/
7163 AccAXRsh (char *x, int shCount)
7171 AccAXRrl1 (x); // 0->a:x
7176 AccAXRrl1 (x); // 0->a:x
7179 AccAXRrl1 (x); // 0->a:x
7184 case 5: // AAAAABBB:CCCCCDDD = a:x
7186 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7188 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7190 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7192 emitcode ("anl", "a,#0x%02x",
7193 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7195 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7197 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7199 emitcode ("anl", "a,#0x%02x",
7200 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7202 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7204 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7206 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7209 case 6: // AABBBBBB:CCDDDDDD
7211 emitcode ("mov", "c,acc.7");
7212 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7214 emitcode ("mov", "c,acc.7");
7215 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7217 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7219 emitcode ("anl", "a,#0x%02x",
7220 SRMask[shCount]); // 000000AA:BBBBBBCC
7223 case 7: // ABBBBBBB:CDDDDDDD
7225 emitcode ("mov", "c,acc.7"); // c = A
7227 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7229 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7231 emitcode ("anl", "a,#0x%02x",
7232 SRMask[shCount]); // 0000000A:BBBBBBBC
7240 /*-----------------------------------------------------------------*/
7241 /* AccAXRshS - right shift signed a:x known count (0..7) */
7242 /*-----------------------------------------------------------------*/
7244 AccAXRshS (char *x, int shCount)
7252 emitcode ("mov", "c,acc.7");
7253 AccAXRrl1 (x); // s->a:x
7257 emitcode ("mov", "c,acc.7");
7258 AccAXRrl1 (x); // s->a:x
7260 emitcode ("mov", "c,acc.7");
7261 AccAXRrl1 (x); // s->a:x
7266 case 5: // AAAAABBB:CCCCCDDD = a:x
7268 tlbl = newiTempLabel (NULL);
7269 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7271 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7273 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7275 emitcode ("anl", "a,#0x%02x",
7276 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7278 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7280 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7282 emitcode ("anl", "a,#0x%02x",
7283 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7285 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7287 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7289 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7291 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7292 emitcode ("orl", "a,#0x%02x",
7293 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7295 emitcode ("", "%05d$:", tlbl->key + 100);
7296 break; // SSSSAAAA:BBBCCCCC
7298 case 6: // AABBBBBB:CCDDDDDD
7300 tlbl = newiTempLabel (NULL);
7301 emitcode ("mov", "c,acc.7");
7302 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7304 emitcode ("mov", "c,acc.7");
7305 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7307 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7309 emitcode ("anl", "a,#0x%02x",
7310 SRMask[shCount]); // 000000AA:BBBBBBCC
7312 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7313 emitcode ("orl", "a,#0x%02x",
7314 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7316 emitcode ("", "%05d$:", tlbl->key + 100);
7318 case 7: // ABBBBBBB:CDDDDDDD
7320 tlbl = newiTempLabel (NULL);
7321 emitcode ("mov", "c,acc.7"); // c = A
7323 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7325 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7327 emitcode ("anl", "a,#0x%02x",
7328 SRMask[shCount]); // 0000000A:BBBBBBBC
7330 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7331 emitcode ("orl", "a,#0x%02x",
7332 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7334 emitcode ("", "%05d$:", tlbl->key + 100);
7341 /*-----------------------------------------------------------------*/
7342 /* shiftL2Left2Result - shift left two bytes from left to result */
7343 /*-----------------------------------------------------------------*/
7345 shiftL2Left2Result (operand * left, int offl,
7346 operand * result, int offr, int shCount)
7348 if (sameRegs (AOP (result), AOP (left)) &&
7349 ((offl + MSB16) == offr))
7351 /* don't crash result[offr] */
7352 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7353 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7357 movLeft2Result (left, offl, result, offr, 0);
7358 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7360 /* ax << shCount (x = lsb(result)) */
7361 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7362 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7366 /*-----------------------------------------------------------------*/
7367 /* shiftR2Left2Result - shift right two bytes from left to result */
7368 /*-----------------------------------------------------------------*/
7370 shiftR2Left2Result (operand * left, int offl,
7371 operand * result, int offr,
7372 int shCount, int sign)
7374 if (sameRegs (AOP (result), AOP (left)) &&
7375 ((offl + MSB16) == offr))
7377 /* don't crash result[offr] */
7378 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7379 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7383 movLeft2Result (left, offl, result, offr, 0);
7384 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
7386 /* a:x >> shCount (x = lsb(result)) */
7388 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7390 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
7391 if (getDataSize (result) > 1)
7392 aopPut (AOP (result), "a", offr + MSB16, isOperandVolatile (result, FALSE));
7395 /*-----------------------------------------------------------------*/
7396 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7397 /*-----------------------------------------------------------------*/
7399 shiftLLeftOrResult (operand * left, int offl,
7400 operand * result, int offr, int shCount)
7402 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7403 /* shift left accumulator */
7405 /* or with result */
7406 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7407 /* back to result */
7408 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7411 /*-----------------------------------------------------------------*/
7412 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7413 /*-----------------------------------------------------------------*/
7415 shiftRLeftOrResult (operand * left, int offl,
7416 operand * result, int offr, int shCount)
7418 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
7419 /* shift right accumulator */
7421 /* or with result */
7422 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
7423 /* back to result */
7424 aopPut (AOP (result), "a", offr, isOperandVolatile (result, FALSE));
7427 /*-----------------------------------------------------------------*/
7428 /* genlshOne - left shift a one byte quantity by known count */
7429 /*-----------------------------------------------------------------*/
7431 genlshOne (operand * result, operand * left, int shCount)
7433 D(emitcode ("; genlshOne",""));
7435 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7438 /*-----------------------------------------------------------------*/
7439 /* genlshTwo - left shift two bytes by known amount != 0 */
7440 /*-----------------------------------------------------------------*/
7442 genlshTwo (operand * result, operand * left, int shCount)
7446 D(emitcode ("; genlshTwo",""));
7448 size = getDataSize (result);
7450 /* if shCount >= 8 */
7458 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7460 movLeft2Result (left, LSB, result, MSB16, 0);
7462 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7465 /* 1 <= shCount <= 7 */
7469 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7471 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7475 /*-----------------------------------------------------------------*/
7476 /* shiftLLong - shift left one long from left to result */
7477 /* offl = LSB or MSB16 */
7478 /*-----------------------------------------------------------------*/
7480 shiftLLong (operand * left, operand * result, int offr)
7483 int size = AOP_SIZE (result);
7485 if (size >= LSB + offr)
7487 l = aopGet (AOP (left), LSB, FALSE, FALSE);
7489 emitcode ("add", "a,acc");
7490 if (sameRegs (AOP (left), AOP (result)) &&
7491 size >= MSB16 + offr && offr != LSB)
7492 emitcode ("xch", "a,%s",
7493 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
7495 aopPut (AOP (result), "a", LSB + offr, isOperandVolatile (result, FALSE));
7498 if (size >= MSB16 + offr)
7500 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
7502 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
7505 emitcode ("rlc", "a");
7506 if (sameRegs (AOP (left), AOP (result)) &&
7507 size >= MSB24 + offr && offr != LSB)
7508 emitcode ("xch", "a,%s",
7509 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
7511 aopPut (AOP (result), "a", MSB16 + offr, isOperandVolatile (result, FALSE));
7514 if (size >= MSB24 + offr)
7516 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
7518 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
7521 emitcode ("rlc", "a");
7522 if (sameRegs (AOP (left), AOP (result)) &&
7523 size >= MSB32 + offr && offr != LSB)
7524 emitcode ("xch", "a,%s",
7525 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
7527 aopPut (AOP (result), "a", MSB24 + offr, isOperandVolatile (result, FALSE));
7530 if (size > MSB32 + offr)
7532 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
7534 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
7537 emitcode ("rlc", "a");
7538 aopPut (AOP (result), "a", MSB32 + offr, isOperandVolatile (result, FALSE));
7541 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7544 /*-----------------------------------------------------------------*/
7545 /* genlshFour - shift four byte by a known amount != 0 */
7546 /*-----------------------------------------------------------------*/
7548 genlshFour (operand * result, operand * left, int shCount)
7552 D(emitcode ("; genlshFour",""));
7554 size = AOP_SIZE (result);
7556 /* if shifting more that 3 bytes */
7561 /* lowest order of left goes to the highest
7562 order of the destination */
7563 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
7565 movLeft2Result (left, LSB, result, MSB32, 0);
7566 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7567 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7568 aopPut (AOP (result), zero, MSB24, isOperandVolatile (result, FALSE));
7572 /* more than two bytes */
7573 else if (shCount >= 16)
7575 /* lower order two bytes goes to higher order two bytes */
7577 /* if some more remaining */
7579 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
7582 movLeft2Result (left, MSB16, result, MSB32, 0);
7583 movLeft2Result (left, LSB, result, MSB24, 0);
7585 aopPut (AOP (result), zero, MSB16, isOperandVolatile (result, FALSE));
7586 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7590 /* if more than 1 byte */
7591 else if (shCount >= 8)
7593 /* lower order three bytes goes to higher order three bytes */
7598 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7600 movLeft2Result (left, LSB, result, MSB16, 0);
7606 movLeft2Result (left, MSB24, result, MSB32, 0);
7607 movLeft2Result (left, MSB16, result, MSB24, 0);
7608 movLeft2Result (left, LSB, result, MSB16, 0);
7609 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7611 else if (shCount == 1)
7612 shiftLLong (left, result, MSB16);
7615 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
7616 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7617 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
7618 aopPut (AOP (result), zero, LSB, isOperandVolatile (result, FALSE));
7623 /* 1 <= shCount <= 7 */
7624 else if (shCount <= 2)
7626 shiftLLong (left, result, LSB);
7628 shiftLLong (result, result, LSB);
7630 /* 3 <= shCount <= 7, optimize */
7633 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
7634 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
7635 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7639 /*-----------------------------------------------------------------*/
7640 /* genLeftShiftLiteral - left shifting by known count */
7641 /*-----------------------------------------------------------------*/
7643 genLeftShiftLiteral (operand * left,
7648 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7651 D(emitcode ("; genLeftShiftLiteral",""));
7653 freeAsmop (right, NULL, ic, TRUE);
7655 aopOp (left, ic, FALSE);
7656 aopOp (result, ic, FALSE);
7658 size = getSize (operandType (result));
7661 emitcode ("; shift left ", "result %d, left %d", size,
7665 /* I suppose that the left size >= result size */
7670 movLeft2Result (left, size, result, size, 0);
7674 else if (shCount >= (size * 8))
7676 aopPut (AOP (result), zero, size, isOperandVolatile (result, FALSE));
7682 genlshOne (result, left, shCount);
7686 genlshTwo (result, left, shCount);
7690 genlshFour (result, left, shCount);
7693 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7694 "*** ack! mystery literal shift!\n");
7698 freeAsmop (left, NULL, ic, TRUE);
7699 freeAsmop (result, NULL, ic, TRUE);
7702 /*-----------------------------------------------------------------*/
7703 /* genLeftShift - generates code for left shifting */
7704 /*-----------------------------------------------------------------*/
7706 genLeftShift (iCode * ic)
7708 operand *left, *right, *result;
7711 symbol *tlbl, *tlbl1;
7714 D(emitcode ("; genLeftShift",""));
7716 right = IC_RIGHT (ic);
7717 left = IC_LEFT (ic);
7718 result = IC_RESULT (ic);
7720 aopOp (right, ic, FALSE);
7722 /* if the shift count is known then do it
7723 as efficiently as possible */
7724 if (AOP_TYPE (right) == AOP_LIT)
7726 genLeftShiftLiteral (left, right, result, ic);
7730 /* shift count is unknown then we have to form
7731 a loop get the loop count in B : Note: we take
7732 only the lower order byte since shifting
7733 more that 32 bits make no sense anyway, ( the
7734 largest size of an object can be only 32 bits ) */
7737 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
7738 emitcode ("inc", "b");
7739 freeAsmop (right, NULL, ic, TRUE);
7740 aopOp (left, ic, FALSE);
7741 aopOp (result, ic, FALSE);
7743 /* now move the left to the result if they are not the same */
7744 if (!sameRegs (AOP (left), AOP (result)) &&
7745 AOP_SIZE (result) > 1)
7748 size = AOP_SIZE (result);
7752 l = aopGet (AOP (left), offset, FALSE, TRUE);
7753 if (*l == '@' && (IS_AOP_PREG (result)))
7756 emitcode ("mov", "a,%s", l);
7757 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
7760 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
7765 tlbl = newiTempLabel (NULL);
7766 size = AOP_SIZE (result);
7768 tlbl1 = newiTempLabel (NULL);
7770 /* if it is only one byte then */
7773 symbol *tlbl1 = newiTempLabel (NULL);
7775 l = aopGet (AOP (left), 0, FALSE, FALSE);
7777 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7778 emitcode ("", "%05d$:", tlbl->key + 100);
7779 emitcode ("add", "a,acc");
7780 emitcode ("", "%05d$:", tlbl1->key + 100);
7781 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7783 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
7787 reAdjustPreg (AOP (result));
7789 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
7790 emitcode ("", "%05d$:", tlbl->key + 100);
7791 l = aopGet (AOP (result), offset, FALSE, FALSE);
7793 emitcode ("add", "a,acc");
7794 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7797 l = aopGet (AOP (result), offset, FALSE, FALSE);
7799 emitcode ("rlc", "a");
7800 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
7802 reAdjustPreg (AOP (result));
7804 emitcode ("", "%05d$:", tlbl1->key + 100);
7805 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
7808 freeAsmop (left, NULL, ic, TRUE);
7809 freeAsmop (result, NULL, ic, TRUE);
7812 /*-----------------------------------------------------------------*/
7813 /* genrshOne - right shift a one byte quantity by known count */
7814 /*-----------------------------------------------------------------*/
7816 genrshOne (operand * result, operand * left,
7817 int shCount, int sign)
7819 D(emitcode ("; genrshOne",""));
7821 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
7824 /*-----------------------------------------------------------------*/
7825 /* genrshTwo - right shift two bytes by known amount != 0 */
7826 /*-----------------------------------------------------------------*/
7828 genrshTwo (operand * result, operand * left,
7829 int shCount, int sign)
7831 D(emitcode ("; genrshTwo",""));
7833 /* if shCount >= 8 */
7838 shiftR1Left2Result (left, MSB16, result, LSB,
7841 movLeft2Result (left, MSB16, result, LSB, sign);
7842 addSign (result, MSB16, sign);
7845 /* 1 <= shCount <= 7 */
7847 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
7850 /*-----------------------------------------------------------------*/
7851 /* shiftRLong - shift right one long from left to result */
7852 /* offl = LSB or MSB16 */
7853 /*-----------------------------------------------------------------*/
7855 shiftRLong (operand * left, int offl,
7856 operand * result, int sign)
7858 int isSameRegs=sameRegs(AOP(left),AOP(result));
7860 if (isSameRegs && offl>1) {
7861 // we are in big trouble, but this shouldn't happen
7862 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
7865 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7870 emitcode ("rlc", "a");
7871 emitcode ("subb", "a,acc");
7873 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
7875 aopPut (AOP (result), "a", MSB32, isOperandVolatile (result, FALSE));
7876 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
7879 aopPut (AOP(result), zero, MSB32, isOperandVolatile (result, FALSE));
7884 emitcode ("clr", "c");
7886 emitcode ("mov", "c,acc.7");
7889 emitcode ("rrc", "a");
7891 if (isSameRegs && offl==MSB16) {
7892 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
7894 aopPut (AOP (result), "a", MSB32-offl, isOperandVolatile (result, FALSE));
7895 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
7898 emitcode ("rrc", "a");
7899 if (isSameRegs && offl==1) {
7900 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
7902 aopPut (AOP (result), "a", MSB24-offl, isOperandVolatile (result, FALSE));
7903 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
7905 emitcode ("rrc", "a");
7906 aopPut (AOP (result), "a", MSB16 - offl, isOperandVolatile (result, FALSE));
7910 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
7911 emitcode ("rrc", "a");
7912 aopPut (AOP (result), "a", LSB, isOperandVolatile (result, FALSE));
7916 /*-----------------------------------------------------------------*/
7917 /* genrshFour - shift four byte by a known amount != 0 */
7918 /*-----------------------------------------------------------------*/
7920 genrshFour (operand * result, operand * left,
7921 int shCount, int sign)
7923 D(emitcode ("; genrshFour",""));
7925 /* if shifting more that 3 bytes */
7930 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
7932 movLeft2Result (left, MSB32, result, LSB, sign);
7933 addSign (result, MSB16, sign);
7935 else if (shCount >= 16)
7939 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
7942 movLeft2Result (left, MSB24, result, LSB, 0);
7943 movLeft2Result (left, MSB32, result, MSB16, sign);
7945 addSign (result, MSB24, sign);
7947 else if (shCount >= 8)
7951 shiftRLong (left, MSB16, result, sign);
7952 else if (shCount == 0)
7954 movLeft2Result (left, MSB16, result, LSB, 0);
7955 movLeft2Result (left, MSB24, result, MSB16, 0);
7956 movLeft2Result (left, MSB32, result, MSB24, sign);
7957 addSign (result, MSB32, sign);
7961 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
7962 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
7963 /* the last shift is signed */
7964 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
7965 addSign (result, MSB32, sign);
7969 { /* 1 <= shCount <= 7 */
7972 shiftRLong (left, LSB, result, sign);
7974 shiftRLong (result, LSB, result, sign);
7978 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
7979 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
7980 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
7985 /*-----------------------------------------------------------------*/
7986 /* genRightShiftLiteral - right shifting by known count */
7987 /*-----------------------------------------------------------------*/
7989 genRightShiftLiteral (operand * left,
7995 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7998 D(emitcode ("; genRightShiftLiteral",""));
8000 freeAsmop (right, NULL, ic, TRUE);
8002 aopOp (left, ic, FALSE);
8003 aopOp (result, ic, FALSE);
8006 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8010 size = getDataSize (left);
8011 /* test the LEFT size !!! */
8013 /* I suppose that the left size >= result size */
8016 size = getDataSize (result);
8018 movLeft2Result (left, size, result, size, 0);
8021 else if (shCount >= (size * 8))
8024 /* get sign in acc.7 */
8025 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
8027 addSign (result, LSB, sign);
8034 genrshOne (result, left, shCount, sign);
8038 genrshTwo (result, left, shCount, sign);
8042 genrshFour (result, left, shCount, sign);
8048 freeAsmop (left, NULL, ic, TRUE);
8049 freeAsmop (result, NULL, ic, TRUE);
8052 /*-----------------------------------------------------------------*/
8053 /* genSignedRightShift - right shift of signed number */
8054 /*-----------------------------------------------------------------*/
8056 genSignedRightShift (iCode * ic)
8058 operand *right, *left, *result;
8061 symbol *tlbl, *tlbl1;
8064 D(emitcode ("; genSignedRightShift",""));
8066 /* we do it the hard way put the shift count in b
8067 and loop thru preserving the sign */
8069 right = IC_RIGHT (ic);
8070 left = IC_LEFT (ic);
8071 result = IC_RESULT (ic);
8073 aopOp (right, ic, FALSE);
8076 if (AOP_TYPE (right) == AOP_LIT)
8078 genRightShiftLiteral (left, right, result, ic, 1);
8081 /* shift count is unknown then we have to form
8082 a loop get the loop count in B : Note: we take
8083 only the lower order byte since shifting
8084 more that 32 bits make no sense anyway, ( the
8085 largest size of an object can be only 32 bits ) */
8088 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8089 emitcode ("inc", "b");
8090 freeAsmop (right, NULL, ic, TRUE);
8091 aopOp (left, ic, FALSE);
8092 aopOp (result, ic, FALSE);
8094 /* now move the left to the result if they are not the
8096 if (!sameRegs (AOP (left), AOP (result)) &&
8097 AOP_SIZE (result) > 1)
8100 size = AOP_SIZE (result);
8104 l = aopGet (AOP (left), offset, FALSE, TRUE);
8105 if (*l == '@' && IS_AOP_PREG (result))
8108 emitcode ("mov", "a,%s", l);
8109 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8112 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8117 /* mov the highest order bit to OVR */
8118 tlbl = newiTempLabel (NULL);
8119 tlbl1 = newiTempLabel (NULL);
8121 size = AOP_SIZE (result);
8123 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
8124 emitcode ("rlc", "a");
8125 emitcode ("mov", "ov,c");
8126 /* if it is only one byte then */
8129 l = aopGet (AOP (left), 0, FALSE, FALSE);
8131 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8132 emitcode ("", "%05d$:", tlbl->key + 100);
8133 emitcode ("mov", "c,ov");
8134 emitcode ("rrc", "a");
8135 emitcode ("", "%05d$:", tlbl1->key + 100);
8136 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8138 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8142 reAdjustPreg (AOP (result));
8143 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8144 emitcode ("", "%05d$:", tlbl->key + 100);
8145 emitcode ("mov", "c,ov");
8148 l = aopGet (AOP (result), offset, FALSE, FALSE);
8150 emitcode ("rrc", "a");
8151 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8153 reAdjustPreg (AOP (result));
8154 emitcode ("", "%05d$:", tlbl1->key + 100);
8155 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8159 freeAsmop (left, NULL, ic, TRUE);
8160 freeAsmop (result, NULL, ic, TRUE);
8163 /*-----------------------------------------------------------------*/
8164 /* genRightShift - generate code for right shifting */
8165 /*-----------------------------------------------------------------*/
8167 genRightShift (iCode * ic)
8169 operand *right, *left, *result;
8173 symbol *tlbl, *tlbl1;
8176 D(emitcode ("; genRightShift",""));
8178 /* if signed then we do it the hard way preserve the
8179 sign bit moving it inwards */
8180 letype = getSpec (operandType (IC_LEFT (ic)));
8182 if (!SPEC_USIGN (letype))
8184 genSignedRightShift (ic);
8188 /* signed & unsigned types are treated the same : i.e. the
8189 signed is NOT propagated inwards : quoting from the
8190 ANSI - standard : "for E1 >> E2, is equivalent to division
8191 by 2**E2 if unsigned or if it has a non-negative value,
8192 otherwise the result is implementation defined ", MY definition
8193 is that the sign does not get propagated */
8195 right = IC_RIGHT (ic);
8196 left = IC_LEFT (ic);
8197 result = IC_RESULT (ic);
8199 aopOp (right, ic, FALSE);
8201 /* if the shift count is known then do it
8202 as efficiently as possible */
8203 if (AOP_TYPE (right) == AOP_LIT)
8205 genRightShiftLiteral (left, right, result, ic, 0);
8209 /* shift count is unknown then we have to form
8210 a loop get the loop count in B : Note: we take
8211 only the lower order byte since shifting
8212 more that 32 bits make no sense anyway, ( the
8213 largest size of an object can be only 32 bits ) */
8216 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
8217 emitcode ("inc", "b");
8218 freeAsmop (right, NULL, ic, TRUE);
8219 aopOp (left, ic, FALSE);
8220 aopOp (result, ic, FALSE);
8222 /* now move the left to the result if they are not the
8224 if (!sameRegs (AOP (left), AOP (result)) &&
8225 AOP_SIZE (result) > 1)
8228 size = AOP_SIZE (result);
8232 l = aopGet (AOP (left), offset, FALSE, TRUE);
8233 if (*l == '@' && IS_AOP_PREG (result))
8236 emitcode ("mov", "a,%s", l);
8237 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8240 aopPut (AOP (result), l, offset, isOperandVolatile (result, FALSE));
8245 tlbl = newiTempLabel (NULL);
8246 tlbl1 = newiTempLabel (NULL);
8247 size = AOP_SIZE (result);
8250 /* if it is only one byte then */
8253 l = aopGet (AOP (left), 0, FALSE, FALSE);
8255 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8256 emitcode ("", "%05d$:", tlbl->key + 100);
8258 emitcode ("rrc", "a");
8259 emitcode ("", "%05d$:", tlbl1->key + 100);
8260 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8262 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
8266 reAdjustPreg (AOP (result));
8267 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8268 emitcode ("", "%05d$:", tlbl->key + 100);
8272 l = aopGet (AOP (result), offset, FALSE, FALSE);
8274 emitcode ("rrc", "a");
8275 aopPut (AOP (result), "a", offset--, isOperandVolatile (result, FALSE));
8277 reAdjustPreg (AOP (result));
8279 emitcode ("", "%05d$:", tlbl1->key + 100);
8280 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8284 freeAsmop (left, NULL, ic, TRUE);
8285 freeAsmop (result, NULL, ic, TRUE);
8288 /*-----------------------------------------------------------------*/
8289 /* emitPtrByteGet - emits code to get a byte into A through a */
8290 /* pointer register (R0, R1, or DPTR). The */
8291 /* original value of A can be preserved in B. */
8292 /*-----------------------------------------------------------------*/
8294 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8301 emitcode ("mov", "b,a");
8302 emitcode ("mov", "a,@%s", rname);
8307 emitcode ("mov", "b,a");
8308 emitcode ("movx", "a,@%s", rname);
8313 emitcode ("mov", "b,a");
8314 emitcode ("movx", "a,@dptr");
8319 emitcode ("mov", "b,a");
8320 emitcode ("clr", "a");
8321 emitcode ("movc", "a,@a+dptr");
8327 emitcode ("push", "b");
8328 emitcode ("push", "acc");
8330 emitcode ("lcall", "__gptrget");
8332 emitcode ("pop", "b");
8337 /*-----------------------------------------------------------------*/
8338 /* emitPtrByteSet - emits code to set a byte from src through a */
8339 /* pointer register (R0, R1, or DPTR). */
8340 /*-----------------------------------------------------------------*/
8342 emitPtrByteSet (char *rname, int p_type, char *src)
8351 emitcode ("mov", "@%s,a", rname);
8354 emitcode ("mov", "@%s,%s", rname, src);
8359 emitcode ("movx", "@%s,a", rname);
8364 emitcode ("movx", "@dptr,a");
8369 emitcode ("lcall", "__gptrput");
8374 /*-----------------------------------------------------------------*/
8375 /* genUnpackBits - generates code for unpacking bits */
8376 /*-----------------------------------------------------------------*/
8378 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8380 int offset = 0; /* result byte offset */
8381 int rsize; /* result size */
8382 int rlen = 0; /* remaining bitfield length */
8383 sym_link *etype; /* bitfield type information */
8384 int blen; /* bitfield length */
8385 int bstr; /* bitfield starting bit within byte */
8388 D(emitcode ("; genUnpackBits",""));
8390 etype = getSpec (operandType (result));
8391 rsize = getSize (operandType (result));
8392 blen = SPEC_BLEN (etype);
8393 bstr = SPEC_BSTR (etype);
8395 if (ifx && blen <= 8)
8397 emitPtrByteGet (rname, ptype, FALSE);
8400 SNPRINTF (buffer, sizeof(buffer),
8402 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8407 emitcode ("anl", "a,#0x%02x",
8408 (((unsigned char) -1) >> (8 - blen)) << bstr);
8409 genIfxJump (ifx, "a", NULL, NULL, NULL);
8415 /* If the bitfield length is less than a byte */
8418 emitPtrByteGet (rname, ptype, FALSE);
8420 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8421 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8425 /* Bit field did not fit in a byte. Copy all
8426 but the partial byte at the end. */
8427 for (rlen=blen;rlen>=8;rlen-=8)
8429 emitPtrByteGet (rname, ptype, FALSE);
8430 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8432 emitcode ("inc", "%s", rname);
8435 /* Handle the partial byte at the end */
8438 emitPtrByteGet (rname, ptype, FALSE);
8439 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8440 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8448 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
8453 /*-----------------------------------------------------------------*/
8454 /* genDataPointerGet - generates code when ptr offset is known */
8455 /*-----------------------------------------------------------------*/
8457 genDataPointerGet (operand * left,
8463 int size, offset = 0;
8465 D(emitcode ("; genDataPointerGet",""));
8467 aopOp (result, ic, TRUE);
8469 /* get the string representation of the name */
8470 l = aopGet (AOP (left), 0, FALSE, TRUE);
8471 size = AOP_SIZE (result);
8475 sprintf (buffer, "(%s + %d)", l + 1, offset);
8477 sprintf (buffer, "%s", l + 1);
8478 aopPut (AOP (result), buffer, offset++, isOperandVolatile (result, FALSE));
8481 freeAsmop (left, NULL, ic, TRUE);
8482 freeAsmop (result, NULL, ic, TRUE);
8485 /*-----------------------------------------------------------------*/
8486 /* genNearPointerGet - emitcode for near pointer fetch */
8487 /*-----------------------------------------------------------------*/
8489 genNearPointerGet (operand * left,
8498 sym_link *rtype, *retype;
8499 sym_link *ltype = operandType (left);
8502 D(emitcode ("; genNearPointerGet",""));
8504 rtype = operandType (result);
8505 retype = getSpec (rtype);
8507 aopOp (left, ic, FALSE);
8509 /* if left is rematerialisable and
8510 result is not bitfield variable type and
8511 the left is pointer to data space i.e
8512 lower 128 bytes of space */
8513 if (AOP_TYPE (left) == AOP_IMMD &&
8514 !IS_BITFIELD (retype) &&
8515 DCL_TYPE (ltype) == POINTER)
8517 genDataPointerGet (left, result, ic);
8521 /* if the value is already in a pointer register
8522 then don't need anything more */
8523 if (!AOP_INPREG (AOP (left)))
8525 if (IS_AOP_PREG (left))
8527 // Aha, it is a pointer, just in disguise.
8528 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8531 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
8532 __FILE__, __LINE__);
8537 emitcode ("mov", "a%s,%s", rname + 1, rname);
8538 rname++; // skip the '@'.
8543 /* otherwise get a free pointer register */
8545 preg = getFreePtr (ic, &aop, FALSE);
8546 emitcode ("mov", "%s,%s",
8548 aopGet (AOP (left), 0, FALSE, TRUE));
8553 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8555 //aopOp (result, ic, FALSE);
8556 aopOp (result, ic, result?TRUE:FALSE);
8558 /* if bitfield then unpack the bits */
8559 if (IS_BITFIELD (retype))
8560 genUnpackBits (result, rname, POINTER, ifx);
8563 /* we have can just get the values */
8564 int size = AOP_SIZE (result);
8569 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
8572 emitcode ("mov", "a,@%s", rname);
8574 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8578 sprintf (buffer, "@%s", rname);
8579 aopPut (AOP (result), buffer, offset, isOperandVolatile (result, FALSE));
8583 emitcode ("inc", "%s", rname);
8587 /* now some housekeeping stuff */
8588 if (aop) /* we had to allocate for this iCode */
8590 if (pi) { /* post increment present */
8591 aopPut(AOP ( left ),rname,0, isOperandVolatile (left, FALSE));
8593 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8597 /* we did not allocate which means left
8598 already in a pointer register, then
8599 if size > 0 && this could be used again
8600 we have to point it back to where it
8602 if ((AOP_SIZE (result) > 1 &&
8603 !OP_SYMBOL (left)->remat &&
8604 (OP_SYMBOL (left)->liveTo > ic->seq ||
8608 int size = AOP_SIZE (result) - 1;
8610 emitcode ("dec", "%s", rname);
8614 if (ifx && !ifx->generated)
8616 genIfxJump (ifx, "a", left, NULL, result);
8620 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
8621 freeAsmop (left, NULL, ic, TRUE);
8622 if (pi) pi->generated = 1;
8625 /*-----------------------------------------------------------------*/
8626 /* genPagedPointerGet - emitcode for paged pointer fetch */
8627 /*-----------------------------------------------------------------*/
8629 genPagedPointerGet (operand * left,
8638 sym_link *rtype, *retype;
8640 D(emitcode ("; genPagedPointerGet",""));
8642 rtype = operandType (result);
8643 retype = getSpec (rtype);
8645 aopOp (left, ic, FALSE);
8647 /* if the value is already in a pointer register
8648 then don't need anything more */
8649 if (!AOP_INPREG (AOP (left)))
8651 /* otherwise get a free pointer register */
8653 preg = getFreePtr (ic, &aop, FALSE);
8654 emitcode ("mov", "%s,%s",
8656 aopGet (AOP (left), 0, FALSE, TRUE));
8660 rname = aopGet (AOP (left), 0, FALSE, FALSE);
8662 aopOp (result, ic, FALSE);
8664 /* if bitfield then unpack the bits */
8665 if (IS_BITFIELD (retype))
8666 genUnpackBits (result, rname, PPOINTER, ifx);
8669 /* we have can just get the values */
8670 int size = AOP_SIZE (result);
8676 emitcode ("movx", "a,@%s", rname);
8678 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
8683 emitcode ("inc", "%s", rname);
8687 /* now some housekeeping stuff */
8688 if (aop) /* we had to allocate for this iCode */
8690 if (pi) aopPut ( AOP (left), rname, 0, isOperandVolatile (left, FALSE));
8691 freeAsmop (NULL, aop, ic, TRUE);
8695 /* we did not allocate which means left
8696 already in a pointer register, then
8697 if size > 0 && this could be used again
8698 we have to point it back to where it
8700 if ((AOP_SIZE (result) > 1 &&
8701 !OP_SYMBOL (left)->remat &&
8702 (OP_SYMBOL (left)->liveTo > ic->seq ||
8706 int size = AOP_SIZE (result) - 1;
8708 emitcode ("dec", "%s", rname);
8712 if (ifx && !ifx->generated)
8714 genIfxJump (ifx, "a", left, NULL, result);
8718 freeAsmop (left, NULL, ic, TRUE);
8719 freeAsmop (result, NULL, ic, TRUE);
8720 if (pi) pi->generated = 1;
8724 /*--------------------------------------------------------------------*/
8725 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
8726 /*--------------------------------------------------------------------*/
8728 loadDptrFromOperand (operand *op, bool loadBToo)
8730 if (AOP_TYPE (op) != AOP_STR)
8732 /* if this is rematerializable */
8733 if (AOP_TYPE (op) == AOP_IMMD)
8735 emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
8738 if (AOP(op)->aopu.aop_immd.from_cast_remat)
8739 emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
8742 wassertl(FALSE, "need pointerCode");
8743 emitcode ("", "; mov b,???");
8744 /* genPointerGet and genPointerSet originally did different
8745 ** things for this case. Both seem wrong.
8746 ** from genPointerGet:
8747 ** emitcode ("mov", "b,#%d", pointerCode (retype));
8748 ** from genPointerSet:
8749 ** emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8754 else if (AOP_TYPE (op) == AOP_DPTR)
8758 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8759 emitcode ("push", "acc");
8760 MOVA (aopGet (AOP (op), 1, FALSE, FALSE));
8761 emitcode ("push", "acc");
8762 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8763 emitcode ("pop", "dph");
8764 emitcode ("pop", "dpl");
8768 MOVA (aopGet (AOP (op), 0, FALSE, FALSE));
8769 emitcode ("push", "acc");
8770 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8771 emitcode ("pop", "dpl");
8775 { /* we need to get it byte by byte */
8776 emitcode ("mov", "dpl,%s", aopGet (AOP (op), 0, FALSE, FALSE));
8777 emitcode ("mov", "dph,%s", aopGet (AOP (op), 1, FALSE, FALSE));
8779 emitcode ("mov", "b,%s", aopGet (AOP (op), 2, FALSE, FALSE));
8784 /*-----------------------------------------------------------------*/
8785 /* genFarPointerGet - gget value from far space */
8786 /*-----------------------------------------------------------------*/
8788 genFarPointerGet (operand * left,
8789 operand * result, iCode * ic, iCode * pi, iCode * ifx)
8792 sym_link *retype = getSpec (operandType (result));
8794 D(emitcode ("; genFarPointerGet",""));
8796 aopOp (left, ic, FALSE);
8797 loadDptrFromOperand (left, FALSE);
8799 /* so dptr now contains the address */
8800 aopOp (result, ic, FALSE);
8802 /* if bit then unpack */
8803 if (IS_BITFIELD (retype))
8804 genUnpackBits (result, "dptr", FPOINTER, ifx);
8807 size = AOP_SIZE (result);
8812 emitcode ("movx", "a,@dptr");
8814 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8816 emitcode ("inc", "dptr");
8820 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8822 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8823 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8827 if (ifx && !ifx->generated)
8829 genIfxJump (ifx, "a", left, NULL, result);
8832 freeAsmop (left, NULL, ic, TRUE);
8833 freeAsmop (result, NULL, ic, TRUE);
8836 /*-----------------------------------------------------------------*/
8837 /* genCodePointerGet - gget value from code space */
8838 /*-----------------------------------------------------------------*/
8840 genCodePointerGet (operand * left,
8841 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8844 sym_link *retype = getSpec (operandType (result));
8846 D(emitcode ("; genCodePointerGet",""));
8848 aopOp (left, ic, FALSE);
8849 loadDptrFromOperand (left, FALSE);
8851 /* so dptr now contains the address */
8852 aopOp (result, ic, FALSE);
8854 /* if bit then unpack */
8855 if (IS_BITFIELD (retype))
8856 genUnpackBits (result, "dptr", CPOINTER, ifx);
8859 size = AOP_SIZE (result);
8866 emitcode ("clr", "a");
8867 emitcode ("movc", "a,@a+dptr");
8869 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8870 emitcode ("inc", "dptr");
8874 emitcode ("mov", "a,#0x%02x", offset);
8875 emitcode ("movc", "a,@a+dptr");
8877 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8882 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8884 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8885 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8889 if (ifx && !ifx->generated)
8891 genIfxJump (ifx, "a", left, NULL, result);
8894 freeAsmop (left, NULL, ic, TRUE);
8895 freeAsmop (result, NULL, ic, TRUE);
8898 /*-----------------------------------------------------------------*/
8899 /* genGenPointerGet - gget value from generic pointer space */
8900 /*-----------------------------------------------------------------*/
8902 genGenPointerGet (operand * left,
8903 operand * result, iCode * ic, iCode *pi, iCode *ifx)
8906 sym_link *retype = getSpec (operandType (result));
8908 D(emitcode ("; genGenPointerGet",""));
8910 aopOp (left, ic, FALSE);
8911 loadDptrFromOperand (left, TRUE);
8913 /* so dptr know contains the address */
8914 aopOp (result, ic, FALSE);
8916 /* if bit then unpack */
8917 if (IS_BITFIELD (retype))
8918 genUnpackBits (result, "dptr", GPOINTER, ifx);
8921 size = AOP_SIZE (result);
8926 emitcode ("lcall", "__gptrget");
8928 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
8930 emitcode ("inc", "dptr");
8934 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
8936 aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
8937 aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
8941 if (ifx && !ifx->generated)
8943 genIfxJump (ifx, "a", left, NULL, result);
8947 freeAsmop (left, NULL, ic, TRUE);
8948 freeAsmop (result, NULL, ic, TRUE);
8951 /*-----------------------------------------------------------------*/
8952 /* genPointerGet - generate code for pointer get */
8953 /*-----------------------------------------------------------------*/
8955 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
8957 operand *left, *result;
8958 sym_link *type, *etype;
8961 D(emitcode ("; genPointerGet",""));
8963 left = IC_LEFT (ic);
8964 result = IC_RESULT (ic);
8966 if (getSize (operandType (result))>1)
8969 /* depending on the type of pointer we need to
8970 move it to the correct pointer register */
8971 type = operandType (left);
8972 etype = getSpec (type);
8973 /* if left is of type of pointer then it is simple */
8974 if (IS_PTR (type) && !IS_FUNC (type->next))
8975 p_type = DCL_TYPE (type);
8978 /* we have to go by the storage class */
8979 p_type = PTR_TYPE (SPEC_OCLS (etype));
8982 /* special case when cast remat */
8983 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
8984 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
8985 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
8986 type = operandType (left);
8987 p_type = DCL_TYPE (type);
8989 /* now that we have the pointer type we assign
8990 the pointer values */
8996 genNearPointerGet (left, result, ic, pi, ifx);
9000 genPagedPointerGet (left, result, ic, pi, ifx);
9004 genFarPointerGet (left, result, ic, pi, ifx);
9008 genCodePointerGet (left, result, ic, pi, ifx);
9012 genGenPointerGet (left, result, ic, pi, ifx);
9020 /*-----------------------------------------------------------------*/
9021 /* genPackBits - generates code for packed bit storage */
9022 /*-----------------------------------------------------------------*/
9024 genPackBits (sym_link * etype,
9026 char *rname, int p_type)
9028 int offset = 0; /* source byte offset */
9029 int rlen = 0; /* remaining bitfield length */
9030 int blen; /* bitfield length */
9031 int bstr; /* bitfield starting bit within byte */
9032 int litval; /* source literal value (if AOP_LIT) */
9033 unsigned char mask; /* bitmask within current byte */
9035 D(emitcode ("; genPackBits",""));
9037 blen = SPEC_BLEN (etype);
9038 bstr = SPEC_BSTR (etype);
9040 /* If the bitfield length is less than a byte */
9043 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9044 (unsigned char) (0xFF >> (8 - bstr)));
9046 if (AOP_TYPE (right) == AOP_LIT)
9048 /* Case with a bitfield length <8 and literal source
9050 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9052 litval &= (~mask) & 0xff;
9053 emitPtrByteGet (rname, p_type, FALSE);
9054 if ((mask|litval)!=0xff)
9055 emitcode ("anl","a,#0x%02x", mask);
9057 emitcode ("orl","a,#0x%02x", litval);
9061 if ((blen==1) && (p_type!=GPOINTER))
9063 /* Case with a bitfield length == 1 and no generic pointer
9065 if (AOP_TYPE (right) == AOP_CRY)
9066 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9069 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9070 emitcode ("rrc","a");
9072 emitPtrByteGet (rname, p_type, FALSE);
9073 emitcode ("mov","acc.%d,c",bstr);
9078 /* Case with a bitfield length < 8 and arbitrary source
9080 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
9081 /* shift and mask source value */
9083 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9086 /* transfer A to B and get next byte */
9087 emitPtrByteGet (rname, p_type, TRUE);
9089 emitcode ("anl", "a,#0x%02x", mask);
9090 emitcode ("orl", "a,b");
9091 if (p_type == GPOINTER)
9092 emitcode ("pop", "b");
9098 emitPtrByteSet (rname, p_type, "a");
9102 /* Bit length is greater than 7 bits. In this case, copy */
9103 /* all except the partial byte at the end */
9104 for (rlen=blen;rlen>=8;rlen-=8)
9106 emitPtrByteSet (rname, p_type,
9107 aopGet (AOP (right), offset++, FALSE, TRUE) );
9109 emitcode ("inc", "%s", rname);
9112 /* If there was a partial byte at the end */
9115 mask = (((unsigned char) -1 << rlen) & 0xff);
9117 if (AOP_TYPE (right) == AOP_LIT)
9119 /* Case with partial byte and literal source
9121 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9122 litval >>= (blen-rlen);
9123 litval &= (~mask) & 0xff;
9124 emitPtrByteGet (rname, p_type, FALSE);
9125 if ((mask|litval)!=0xff)
9126 emitcode ("anl","a,#0x%02x", mask);
9128 emitcode ("orl","a,#0x%02x", litval);
9133 /* Case with partial byte and arbitrary source
9135 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE));
9136 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9139 /* transfer A to B and get next byte */
9140 emitPtrByteGet (rname, p_type, TRUE);
9142 emitcode ("anl", "a,#0x%02x", mask);
9143 emitcode ("orl", "a,b");
9144 if (p_type == GPOINTER)
9145 emitcode ("pop", "b");
9149 emitPtrByteSet (rname, p_type, "a");
9155 /*-----------------------------------------------------------------*/
9156 /* genDataPointerSet - remat pointer to data space */
9157 /*-----------------------------------------------------------------*/
9159 genDataPointerSet (operand * right,
9163 int size, offset = 0;
9164 char *l, buffer[256];
9166 D(emitcode ("; genDataPointerSet",""));
9168 aopOp (right, ic, FALSE);
9170 l = aopGet (AOP (result), 0, FALSE, TRUE);
9171 size = AOP_SIZE (right);
9175 sprintf (buffer, "(%s + %d)", l + 1, offset);
9177 sprintf (buffer, "%s", l + 1);
9178 emitcode ("mov", "%s,%s", buffer,
9179 aopGet (AOP (right), offset++, FALSE, FALSE));
9182 freeAsmop (right, NULL, ic, TRUE);
9183 freeAsmop (result, NULL, ic, TRUE);
9186 /*-----------------------------------------------------------------*/
9187 /* genNearPointerSet - emitcode for near pointer put */
9188 /*-----------------------------------------------------------------*/
9190 genNearPointerSet (operand * right,
9198 sym_link *retype, *letype;
9199 sym_link *ptype = operandType (result);
9201 D(emitcode ("; genNearPointerSet",""));
9203 retype = getSpec (operandType (right));
9204 letype = getSpec (ptype);
9205 aopOp (result, ic, FALSE);
9207 /* if the result is rematerializable &
9208 in data space & not a bit variable */
9209 if (AOP_TYPE (result) == AOP_IMMD &&
9210 DCL_TYPE (ptype) == POINTER &&
9211 !IS_BITVAR (retype) &&
9212 !IS_BITVAR (letype))
9214 genDataPointerSet (right, result, ic);
9218 /* if the value is already in a pointer register
9219 then don't need anything more */
9220 if (!AOP_INPREG (AOP (result)))
9223 //AOP_TYPE (result) == AOP_STK
9227 // Aha, it is a pointer, just in disguise.
9228 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9231 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9232 __FILE__, __LINE__);
9237 emitcode ("mov", "a%s,%s", rname + 1, rname);
9238 rname++; // skip the '@'.
9243 /* otherwise get a free pointer register */
9245 preg = getFreePtr (ic, &aop, FALSE);
9246 emitcode ("mov", "%s,%s",
9248 aopGet (AOP (result), 0, FALSE, TRUE));
9254 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9257 aopOp (right, ic, FALSE);
9259 /* if bitfield then unpack the bits */
9260 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9261 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9264 /* we have can just get the values */
9265 int size = AOP_SIZE (right);
9270 l = aopGet (AOP (right), offset, FALSE, TRUE);
9274 emitcode ("mov", "@%s,a", rname);
9277 emitcode ("mov", "@%s,%s", rname, l);
9279 emitcode ("inc", "%s", rname);
9284 /* now some housekeeping stuff */
9285 if (aop) /* we had to allocate for this iCode */
9288 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9289 freeAsmop (NULL, aop, ic, TRUE);
9293 /* we did not allocate which means left
9294 already in a pointer register, then
9295 if size > 0 && this could be used again
9296 we have to point it back to where it
9298 if ((AOP_SIZE (right) > 1 &&
9299 !OP_SYMBOL (result)->remat &&
9300 (OP_SYMBOL (result)->liveTo > ic->seq ||
9304 int size = AOP_SIZE (right) - 1;
9306 emitcode ("dec", "%s", rname);
9311 if (pi) pi->generated = 1;
9312 freeAsmop (result, NULL, ic, TRUE);
9313 freeAsmop (right, NULL, ic, TRUE);
9316 /*-----------------------------------------------------------------*/
9317 /* genPagedPointerSet - emitcode for Paged pointer put */
9318 /*-----------------------------------------------------------------*/
9320 genPagedPointerSet (operand * right,
9328 sym_link *retype, *letype;
9330 D(emitcode ("; genPagedPointerSet",""));
9332 retype = getSpec (operandType (right));
9333 letype = getSpec (operandType (result));
9335 aopOp (result, ic, FALSE);
9337 /* if the value is already in a pointer register
9338 then don't need anything more */
9339 if (!AOP_INPREG (AOP (result)))
9341 /* otherwise get a free pointer register */
9343 preg = getFreePtr (ic, &aop, FALSE);
9344 emitcode ("mov", "%s,%s",
9346 aopGet (AOP (result), 0, FALSE, TRUE));
9350 rname = aopGet (AOP (result), 0, FALSE, FALSE);
9352 aopOp (right, ic, FALSE);
9354 /* if bitfield then unpack the bits */
9355 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9356 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9359 /* we have can just get the values */
9360 int size = AOP_SIZE (right);
9365 l = aopGet (AOP (right), offset, FALSE, TRUE);
9368 emitcode ("movx", "@%s,a", rname);
9371 emitcode ("inc", "%s", rname);
9377 /* now some housekeeping stuff */
9378 if (aop) /* we had to allocate for this iCode */
9381 aopPut (AOP (result), rname, 0, isOperandVolatile (result, FALSE));
9382 freeAsmop (NULL, aop, ic, TRUE);
9386 /* we did not allocate which means left
9387 already in a pointer register, then
9388 if size > 0 && this could be used again
9389 we have to point it back to where it
9391 if (AOP_SIZE (right) > 1 &&
9392 !OP_SYMBOL (result)->remat &&
9393 (OP_SYMBOL (result)->liveTo > ic->seq ||
9396 int size = AOP_SIZE (right) - 1;
9398 emitcode ("dec", "%s", rname);
9403 if (pi) pi->generated = 1;
9404 freeAsmop (result, NULL, ic, TRUE);
9405 freeAsmop (right, NULL, ic, TRUE);
9410 /*-----------------------------------------------------------------*/
9411 /* genFarPointerSet - set value from far space */
9412 /*-----------------------------------------------------------------*/
9414 genFarPointerSet (operand * right,
9415 operand * result, iCode * ic, iCode * pi)
9418 sym_link *retype = getSpec (operandType (right));
9419 sym_link *letype = getSpec (operandType (result));
9421 D(emitcode ("; genFarPointerSet",""));
9423 aopOp (result, ic, FALSE);
9424 loadDptrFromOperand (result, FALSE);
9426 /* so dptr know contains the address */
9427 aopOp (right, ic, FALSE);
9429 /* if bit then unpack */
9430 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9431 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9434 size = AOP_SIZE (right);
9439 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9441 emitcode ("movx", "@dptr,a");
9443 emitcode ("inc", "dptr");
9446 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9447 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9448 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9451 freeAsmop (result, NULL, ic, TRUE);
9452 freeAsmop (right, NULL, ic, TRUE);
9455 /*-----------------------------------------------------------------*/
9456 /* genGenPointerSet - set value from generic pointer space */
9457 /*-----------------------------------------------------------------*/
9459 genGenPointerSet (operand * right,
9460 operand * result, iCode * ic, iCode * pi)
9463 sym_link *retype = getSpec (operandType (right));
9464 sym_link *letype = getSpec (operandType (result));
9466 D(emitcode ("; genGenPointerSet",""));
9468 aopOp (result, ic, FALSE);
9469 loadDptrFromOperand (result, TRUE);
9471 /* so dptr know contains the address */
9472 aopOp (right, ic, FALSE);
9474 /* if bit then unpack */
9475 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9476 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9479 size = AOP_SIZE (right);
9484 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
9486 emitcode ("lcall", "__gptrput");
9488 emitcode ("inc", "dptr");
9492 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9493 aopPut (AOP(result), "dpl", 0, isOperandVolatile (result, FALSE));
9494 aopPut (AOP(result), "dph", 1, isOperandVolatile (result, FALSE));
9497 freeAsmop (result, NULL, ic, TRUE);
9498 freeAsmop (right, NULL, ic, TRUE);
9501 /*-----------------------------------------------------------------*/
9502 /* genPointerSet - stores the value into a pointer location */
9503 /*-----------------------------------------------------------------*/
9505 genPointerSet (iCode * ic, iCode *pi)
9507 operand *right, *result;
9508 sym_link *type, *etype;
9511 D(emitcode ("; genPointerSet",""));
9513 right = IC_RIGHT (ic);
9514 result = IC_RESULT (ic);
9516 /* depending on the type of pointer we need to
9517 move it to the correct pointer register */
9518 type = operandType (result);
9519 etype = getSpec (type);
9520 /* if left is of type of pointer then it is simple */
9521 if (IS_PTR (type) && !IS_FUNC (type->next))
9523 p_type = DCL_TYPE (type);
9527 /* we have to go by the storage class */
9528 p_type = PTR_TYPE (SPEC_OCLS (etype));
9531 /* special case when cast remat */
9532 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
9533 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
9534 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
9535 type = operandType (result);
9536 p_type = DCL_TYPE (type);
9538 /* now that we have the pointer type we assign
9539 the pointer values */
9545 genNearPointerSet (right, result, ic, pi);
9549 genPagedPointerSet (right, result, ic, pi);
9553 genFarPointerSet (right, result, ic, pi);
9557 genGenPointerSet (right, result, ic, pi);
9561 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
9562 "genPointerSet: illegal pointer type");
9567 /*-----------------------------------------------------------------*/
9568 /* genIfx - generate code for Ifx statement */
9569 /*-----------------------------------------------------------------*/
9571 genIfx (iCode * ic, iCode * popIc)
9573 operand *cond = IC_COND (ic);
9576 D(emitcode ("; genIfx",""));
9578 aopOp (cond, ic, FALSE);
9580 /* get the value into acc */
9581 if (AOP_TYPE (cond) != AOP_CRY)
9585 /* the result is now in the accumulator */
9586 freeAsmop (cond, NULL, ic, TRUE);
9588 /* if there was something to be popped then do it */
9592 /* if the condition is a bit variable */
9593 if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
9594 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
9595 else if (isbit && !IS_ITEMP (cond))
9596 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
9598 genIfxJump (ic, "a", NULL, NULL, NULL);
9603 /*-----------------------------------------------------------------*/
9604 /* genAddrOf - generates code for address of */
9605 /*-----------------------------------------------------------------*/
9607 genAddrOf (iCode * ic)
9609 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
9612 D(emitcode ("; genAddrOf",""));
9614 aopOp (IC_RESULT (ic), ic, FALSE);
9616 /* if the operand is on the stack then we
9617 need to get the stack offset of this
9621 /* if it has an offset then we need to compute
9625 emitcode ("mov", "a,%s", SYM_BP (sym));
9626 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
9627 ((char) (sym->stack - _G.nRegsSaved)) :
9628 ((char) sym->stack)) & 0xff);
9629 aopPut (AOP (IC_RESULT (ic)), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9633 /* we can just move _bp */
9634 aopPut (AOP (IC_RESULT (ic)), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
9636 /* fill the result with zero */
9637 size = AOP_SIZE (IC_RESULT (ic)) - 1;
9642 aopPut (AOP (IC_RESULT (ic)), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9648 /* object not on stack then we need the name */
9649 size = AOP_SIZE (IC_RESULT (ic));
9654 char s[SDCC_NAME_MAX];
9656 sprintf (s, "#(%s >> %d)",
9660 sprintf (s, "#%s", sym->rname);
9661 aopPut (AOP (IC_RESULT (ic)), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
9665 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
9669 /*-----------------------------------------------------------------*/
9670 /* genFarFarAssign - assignment when both are in far space */
9671 /*-----------------------------------------------------------------*/
9673 genFarFarAssign (operand * result, operand * right, iCode * ic)
9675 int size = AOP_SIZE (right);
9679 D(emitcode ("; genFarFarAssign",""));
9681 /* first push the right side on to the stack */
9684 l = aopGet (AOP (right), offset++, FALSE, FALSE);
9686 emitcode ("push", "acc");
9689 freeAsmop (right, NULL, ic, FALSE);
9690 /* now assign DPTR to result */
9691 aopOp (result, ic, FALSE);
9692 size = AOP_SIZE (result);
9695 emitcode ("pop", "acc");
9696 aopPut (AOP (result), "a", --offset, isOperandVolatile (result, FALSE));
9698 freeAsmop (result, NULL, ic, FALSE);
9702 /*-----------------------------------------------------------------*/
9703 /* genAssign - generate code for assignment */
9704 /*-----------------------------------------------------------------*/
9706 genAssign (iCode * ic)
9708 operand *result, *right;
9710 unsigned long lit = 0L;
9712 D(emitcode("; genAssign",""));
9714 result = IC_RESULT (ic);
9715 right = IC_RIGHT (ic);
9717 /* if they are the same */
9718 if (operandsEqu (result, right) &&
9719 !isOperandVolatile (result, FALSE) &&
9720 !isOperandVolatile (right, FALSE))
9723 aopOp (right, ic, FALSE);
9725 /* special case both in far space */
9726 if (AOP_TYPE (right) == AOP_DPTR &&
9727 IS_TRUE_SYMOP (result) &&
9728 isOperandInFarSpace (result))
9731 genFarFarAssign (result, right, ic);
9735 aopOp (result, ic, TRUE);
9737 /* if they are the same registers */
9738 if (sameRegs (AOP (right), AOP (result)) &&
9739 !isOperandVolatile (result, FALSE) &&
9740 !isOperandVolatile (right, FALSE))
9743 /* if the result is a bit */
9744 if (AOP_TYPE (result) == AOP_CRY)
9747 /* if the right size is a literal then
9748 we know what the value is */
9749 if (AOP_TYPE (right) == AOP_LIT)
9751 if (((int) operandLitValue (right)))
9752 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9754 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9758 /* the right is also a bit variable */
9759 if (AOP_TYPE (right) == AOP_CRY)
9761 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9762 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9768 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9772 /* bit variables done */
9774 size = AOP_SIZE (result);
9776 if (AOP_TYPE (right) == AOP_LIT)
9777 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
9779 (AOP_TYPE (result) != AOP_REG) &&
9780 (AOP_TYPE (right) == AOP_LIT) &&
9781 !IS_FLOAT (operandType (right)) &&
9784 while ((size) && (lit))
9786 aopPut (AOP (result),
9787 aopGet (AOP (right), offset, FALSE, FALSE),
9789 isOperandVolatile (result, FALSE));
9794 emitcode ("clr", "a");
9797 aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
9805 aopPut (AOP (result),
9806 aopGet (AOP (right), offset, FALSE, FALSE),
9808 isOperandVolatile (result, FALSE));
9814 freeAsmop (right, NULL, ic, TRUE);
9815 freeAsmop (result, NULL, ic, TRUE);
9818 /*-----------------------------------------------------------------*/
9819 /* genJumpTab - generates code for jump table */
9820 /*-----------------------------------------------------------------*/
9822 genJumpTab (iCode * ic)
9824 symbol *jtab,*jtablo,*jtabhi;
9828 D(emitcode ("; genJumpTab",""));
9830 count = elementsInSet( IC_JTLABELS (ic) );
9834 /* this algorithm needs 9 cycles and 7 + 3*n bytes
9835 if the switch argument is in a register.
9836 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
9837 /* (MB) What if peephole converts ljmp to sjmp or ret ???
9838 How will multiply by three be updated ???*/
9839 aopOp (IC_JTCOND (ic), ic, FALSE);
9840 /* get the condition into accumulator */
9841 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9843 /* multiply by three */
9844 emitcode ("add", "a,acc");
9845 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
9846 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9848 jtab = newiTempLabel (NULL);
9849 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
9850 emitcode ("jmp", "@a+dptr");
9851 emitcode ("", "%05d$:", jtab->key + 100);
9852 /* now generate the jump labels */
9853 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9854 jtab = setNextItem (IC_JTLABELS (ic)))
9855 emitcode ("ljmp", "%05d$", jtab->key + 100);
9859 /* this algorithm needs 14 cycles and 13 + 2*n bytes
9860 if the switch argument is in a register.
9861 For n>6 this algorithm may be more compact */
9862 jtablo = newiTempLabel (NULL);
9863 jtabhi = newiTempLabel (NULL);
9865 /* get the condition into accumulator.
9866 Using b as temporary storage, if register push/pop is needed */
9867 aopOp (IC_JTCOND (ic), ic, FALSE);
9868 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
9869 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
9870 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
9872 // (MB) what if B is in use???
9873 wassertl(!BINUSE, "B was in use");
9874 emitcode ("mov", "b,%s", l);
9877 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
9881 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
9882 emitcode ("movc", "a,@a+pc");
9883 emitcode ("push", "acc");
9886 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
9887 emitcode ("movc", "a,@a+pc");
9888 emitcode ("push", "acc");
9892 /* this scales up to n<=255, but needs two more bytes
9894 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
9895 emitcode ("movc", "a,@a+dptr");
9896 emitcode ("push", "acc");
9899 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
9900 emitcode ("movc", "a,@a+dptr");
9901 emitcode ("push", "acc");
9904 emitcode ("ret", "");
9906 /* now generate jump table, LSB */
9907 emitcode ("", "%05d$:", jtablo->key + 100);
9908 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9909 jtab = setNextItem (IC_JTLABELS (ic)))
9910 emitcode (".db", "%05d$", jtab->key + 100);
9912 /* now generate jump table, MSB */
9913 emitcode ("", "%05d$:", jtabhi->key + 100);
9914 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
9915 jtab = setNextItem (IC_JTLABELS (ic)))
9916 emitcode (".db", "%05d$>>8", jtab->key + 100);
9920 /*-----------------------------------------------------------------*/
9921 /* genCast - gen code for casting */
9922 /*-----------------------------------------------------------------*/
9924 genCast (iCode * ic)
9926 operand *result = IC_RESULT (ic);
9927 sym_link *ctype = operandType (IC_LEFT (ic));
9928 sym_link *rtype = operandType (IC_RIGHT (ic));
9929 operand *right = IC_RIGHT (ic);
9932 D(emitcode("; genCast",""));
9934 /* if they are equivalent then do nothing */
9935 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
9938 aopOp (right, ic, FALSE);
9939 aopOp (result, ic, FALSE);
9941 /* if the result is a bit (and not a bitfield) */
9942 // if (AOP_TYPE (result) == AOP_CRY)
9943 if (IS_BITVAR (OP_SYMBOL (result)->type)
9944 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
9946 /* if the right size is a literal then
9947 we know what the value is */
9948 if (AOP_TYPE (right) == AOP_LIT)
9950 if (((int) operandLitValue (right)))
9951 aopPut (AOP (result), one, 0, isOperandVolatile (result, FALSE));
9953 aopPut (AOP (result), zero, 0, isOperandVolatile (result, FALSE));
9958 /* the right is also a bit variable */
9959 if (AOP_TYPE (right) == AOP_CRY)
9961 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
9962 aopPut (AOP (result), "c", 0, isOperandVolatile (result, FALSE));
9968 aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
9973 /* if they are the same size : or less */
9974 if (AOP_SIZE (result) <= AOP_SIZE (right))
9977 /* if they are in the same place */
9978 if (sameRegs (AOP (right), AOP (result)))
9981 /* if they in different places then copy */
9982 size = AOP_SIZE (result);
9986 aopPut (AOP (result),
9987 aopGet (AOP (right), offset, FALSE, FALSE),
9989 isOperandVolatile (result, FALSE));
9996 /* if the result is of type pointer */
10001 sym_link *type = operandType (right);
10002 sym_link *etype = getSpec (type);
10004 /* pointer to generic pointer */
10005 if (IS_GENPTR (ctype))
10008 p_type = DCL_TYPE (type);
10011 if (SPEC_SCLS(etype)==S_REGISTER) {
10012 // let's assume it is a generic pointer
10015 /* we have to go by the storage class */
10016 p_type = PTR_TYPE (SPEC_OCLS (etype));
10020 /* the first two bytes are known */
10021 size = GPTRSIZE - 1;
10025 aopPut (AOP (result),
10026 aopGet (AOP (right), offset, FALSE, FALSE),
10028 isOperandVolatile (result, FALSE));
10031 /* the last byte depending on type */
10033 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10038 // pointerTypeToGPByte will have bitched.
10042 sprintf(gpValStr, "#0x%d", gpVal);
10043 aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10048 /* just copy the pointers */
10049 size = AOP_SIZE (result);
10053 aopPut (AOP (result),
10054 aopGet (AOP (right), offset, FALSE, FALSE),
10056 isOperandVolatile (result, FALSE));
10062 /* so we now know that the size of destination is greater
10063 than the size of the source */
10064 /* we move to result for the size of source */
10065 size = AOP_SIZE (right);
10069 aopPut (AOP (result),
10070 aopGet (AOP (right), offset, FALSE, FALSE),
10072 isOperandVolatile (result, FALSE));
10076 /* now depending on the sign of the source && destination */
10077 size = AOP_SIZE (result) - AOP_SIZE (right);
10078 /* if unsigned or not an integral type */
10079 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10082 aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
10086 /* we need to extend the sign :{ */
10087 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
10090 emitcode ("rlc", "a");
10091 emitcode ("subb", "a,acc");
10093 aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
10096 /* we are done hurray !!!! */
10099 freeAsmop (right, NULL, ic, TRUE);
10100 freeAsmop (result, NULL, ic, TRUE);
10104 /*-----------------------------------------------------------------*/
10105 /* genDjnz - generate decrement & jump if not zero instrucion */
10106 /*-----------------------------------------------------------------*/
10108 genDjnz (iCode * ic, iCode * ifx)
10110 symbol *lbl, *lbl1;
10114 D(emitcode ("; genDjnz",""));
10116 /* if the if condition has a false label
10117 then we cannot save */
10118 if (IC_FALSE (ifx))
10121 /* if the minus is not of the form
10123 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10124 !IS_OP_LITERAL (IC_RIGHT (ic)))
10127 if (operandLitValue (IC_RIGHT (ic)) != 1)
10130 /* if the size of this greater than one then no
10132 if (getSize (operandType (IC_RESULT (ic))) > 1)
10135 /* otherwise we can save BIG */
10136 lbl = newiTempLabel (NULL);
10137 lbl1 = newiTempLabel (NULL);
10139 aopOp (IC_RESULT (ic), ic, FALSE);
10141 if (AOP_NEEDSACC(IC_RESULT(ic)))
10143 /* If the result is accessed indirectly via
10144 * the accumulator, we must explicitly write
10145 * it back after the decrement.
10147 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
10149 if (strcmp(rByte, "a"))
10151 /* Something is hopelessly wrong */
10152 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10153 __FILE__, __LINE__);
10154 /* We can just give up; the generated code will be inefficient,
10155 * but what the hey.
10157 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10160 emitcode ("dec", "%s", rByte);
10161 aopPut(AOP(IC_RESULT(ic)), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10162 emitcode ("jnz", "%05d$", lbl->key + 100);
10164 else if (IS_AOP_PREG (IC_RESULT (ic)))
10166 emitcode ("dec", "%s",
10167 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10168 MOVA (aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
10169 emitcode ("jnz", "%05d$", lbl->key + 100);
10173 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
10176 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10177 emitcode ("", "%05d$:", lbl->key + 100);
10178 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10179 emitcode ("", "%05d$:", lbl1->key + 100);
10181 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10182 ifx->generated = 1;
10186 /*-----------------------------------------------------------------*/
10187 /* genReceive - generate code for a receive iCode */
10188 /*-----------------------------------------------------------------*/
10190 genReceive (iCode * ic)
10192 int size = getSize (operandType (IC_RESULT (ic)));
10194 D(emitcode ("; genReceive",""));
10196 if (ic->argreg == 1) { /* first parameter */
10197 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10198 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10199 IS_TRUE_SYMOP (IC_RESULT (ic)))) {
10202 int receivingA = 0;
10205 for (offset = 0; offset<size; offset++)
10206 if (!strcmp (fReturn[offset], "a"))
10211 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10213 for (offset = size-1; offset>0; offset--)
10214 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10215 emitcode("mov","a,%s", fReturn[0]);
10217 aopOp (IC_RESULT (ic), ic, FALSE);
10219 aopPut (AOP (IC_RESULT (ic)), "a", offset,
10220 isOperandVolatile (IC_RESULT (ic), FALSE));
10221 for (offset = 1; offset<size; offset++)
10222 aopPut (AOP (IC_RESULT (ic)), tempRegs[--roffset]->name, offset,
10223 isOperandVolatile (IC_RESULT (ic), FALSE));
10229 if (getTempRegs(tempRegs, size, ic))
10231 for (offset = 0; offset<size; offset++)
10232 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10233 aopOp (IC_RESULT (ic), ic, FALSE);
10234 for (offset = 0; offset<size; offset++)
10235 aopPut (AOP (IC_RESULT (ic)), tempRegs[offset]->name, offset,
10236 isOperandVolatile (IC_RESULT (ic), FALSE));
10241 offset = fReturnSizeMCS51 - size;
10243 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10244 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10247 aopOp (IC_RESULT (ic), ic, FALSE);
10248 size = AOP_SIZE (IC_RESULT (ic));
10251 emitcode ("pop", "acc");
10252 aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10257 aopOp (IC_RESULT (ic), ic, FALSE);
10259 assignResultValue (IC_RESULT (ic));
10261 } else { /* second receive onwards */
10263 aopOp (IC_RESULT (ic), ic, FALSE);
10264 rb1off = ic->argreg;
10266 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10271 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10274 /*-----------------------------------------------------------------*/
10275 /* genDummyRead - generate code for dummy read of volatiles */
10276 /*-----------------------------------------------------------------*/
10278 genDummyRead (iCode * ic)
10283 D(emitcode("; genDummyRead",""));
10285 op = IC_RIGHT (ic);
10286 if (op && IS_SYMOP (op))
10288 aopOp (op, ic, FALSE);
10290 /* if the result is a bit */
10291 if (AOP_TYPE (op) == AOP_CRY)
10292 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10295 /* bit variables done */
10297 size = AOP_SIZE (op);
10301 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10306 freeAsmop (op, NULL, ic, TRUE);
10310 if (op && IS_SYMOP (op))
10312 aopOp (op, ic, FALSE);
10314 /* if the result is a bit */
10315 if (AOP_TYPE (op) == AOP_CRY)
10316 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10319 /* bit variables done */
10321 size = AOP_SIZE (op);
10325 MOVA (aopGet (AOP (op), offset, FALSE, FALSE));
10330 freeAsmop (op, NULL, ic, TRUE);
10334 /*-----------------------------------------------------------------*/
10335 /* genCritical - generate code for start of a critical sequence */
10336 /*-----------------------------------------------------------------*/
10338 genCritical (iCode *ic)
10340 symbol *tlbl = newiTempLabel (NULL);
10342 D(emitcode("; genCritical",""));
10344 if (IC_RESULT (ic))
10346 aopOp (IC_RESULT (ic), ic, TRUE);
10347 aopPut (AOP (IC_RESULT (ic)), one, 0, 0);
10348 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10349 aopPut (AOP (IC_RESULT (ic)), zero, 0, 0);
10350 emitcode ("", "%05d$:", (tlbl->key + 100));
10351 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10355 emitcode ("setb", "c");
10356 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10357 emitcode ("clr", "c");
10358 emitcode ("", "%05d$:", (tlbl->key + 100));
10359 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10363 /*-----------------------------------------------------------------*/
10364 /* genEndCritical - generate code for end of a critical sequence */
10365 /*-----------------------------------------------------------------*/
10367 genEndCritical (iCode *ic)
10369 D(emitcode("; genEndCritical",""));
10373 aopOp (IC_RIGHT (ic), ic, FALSE);
10374 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10376 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10377 emitcode ("mov", "ea,c");
10381 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10382 MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE));
10383 emitcode ("rrc", "a");
10384 emitcode ("mov", "ea,c");
10386 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10390 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10391 emitcode ("mov", "ea,c");
10395 /*-----------------------------------------------------------------*/
10396 /* gen51Code - generate code for 8051 based controllers */
10397 /*-----------------------------------------------------------------*/
10399 gen51Code (iCode * lic)
10403 /* int cseq = 0; */
10405 _G.currentFunc = NULL;
10406 lineHead = lineCurr = NULL;
10408 /* print the allocation information */
10409 if (allocInfo && currFunc)
10410 printAllocInfo (currFunc, codeOutFile);
10411 /* if debug information required */
10412 if (options.debug && currFunc)
10414 debugFile->writeFunction (currFunc, lic);
10416 /* stack pointer name */
10417 if (options.useXstack)
10423 for (ic = lic; ic; ic = ic->next)
10425 _G.current_iCode = ic;
10427 if (ic->lineno && cln != ic->lineno)
10431 debugFile->writeCLine (ic);
10433 if (!options.noCcodeInAsm) {
10434 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10435 printCLine(ic->filename, ic->lineno));
10440 if (ic->seqPoint && ic->seqPoint != cseq)
10442 emitcode ("", "; sequence point %d", ic->seqPoint);
10443 cseq = ic->seqPoint;
10446 if (options.iCodeInAsm) {
10447 char regsInUse[80];
10450 for (i=0; i<8; i++) {
10451 sprintf (®sInUse[i],
10452 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10455 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10457 /* if the result is marked as
10458 spilt and rematerializable or code for
10459 this has already been generated then
10461 if (resultRemat (ic) || ic->generated)
10464 /* depending on the operation */
10484 /* IPOP happens only when trying to restore a
10485 spilt live range, if there is an ifx statement
10486 following this pop then the if statement might
10487 be using some of the registers being popped which
10488 would destory the contents of the register so
10489 we need to check for this condition and handle it */
10491 ic->next->op == IFX &&
10492 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
10493 genIfx (ic->next, ic);
10511 genEndFunction (ic);
10531 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
10548 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
10552 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
10559 /* note these two are xlated by algebraic equivalence
10560 during parsing SDCC.y */
10561 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10562 "got '>=' or '<=' shouldn't have come here");
10566 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
10578 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
10582 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
10586 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
10610 genRightShift (ic);
10613 case GET_VALUE_AT_ADDRESS:
10615 hasInc (IC_LEFT (ic), ic,
10616 getSize (operandType (IC_RESULT (ic)))),
10617 ifxForOp (IC_RESULT (ic), ic) );
10621 if (POINTER_SET (ic))
10622 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
10648 addSet (&_G.sendSet, ic);
10651 case DUMMY_READ_VOLATILE:
10660 genEndCritical (ic);
10672 _G.current_iCode = NULL;
10674 /* now we are ready to call the
10675 peep hole optimizer */
10676 if (!options.nopeep)
10677 peepHole (&lineHead);
10679 /* now do the actual printing */
10680 printLine (lineHead, codeOutFile);