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);
47 char *aopLiteralLong (value * val, int offset, int size);
50 /* this is the down and dirty file with all kinds of
51 kludgy & hacky stuff. This is what it is all about
52 CODE GENERATION for a specific MCU . some of the
53 routines may be reusable, will have to see */
55 static char *zero = "#0x00";
56 static char *one = "#0x01";
60 {"dpl", "dph", "b", "a"};
61 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
62 char **fReturn = fReturn8051;
63 static char *accUse[] =
66 static unsigned short rbank = -1;
68 #define AOP(op) op->aop
69 #define AOP_TYPE(op) AOP(op)->type
70 #define AOP_SIZE(op) AOP(op)->size
71 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
72 AOP_TYPE(x) == AOP_R0))
74 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
75 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
77 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
78 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
79 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
82 #define SYM_BP(sym) (SPEC_OCLS (sym->etype)->paged ? "_bpx" : "_bp")
84 #define R0INB _G.bu.bs.r0InB
85 #define R1INB _G.bu.bs.r1InB
86 #define OPINB _G.bu.bs.OpInB
87 #define BINUSE _G.bu.BInUse
97 short r0InB : 2;//2 so we can see it overflow
98 short r1InB : 2;//2 so we can see it overflow
99 short OpInB : 2;//2 so we can see it overflow
108 iCode *current_iCode;
113 static char *rb1regs[] = {
114 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7",
115 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7"
118 extern int mcs51_ptrRegReq;
119 extern int mcs51_nRegs;
120 extern FILE *codeOutFile;
121 static void saveRBank (int, iCode *, bool);
123 #define RESULTONSTACK(x) \
124 (IC_RESULT(x) && IC_RESULT(x)->aop && \
125 IC_RESULT(x)->aop->type == AOP_STK )
127 #define MOVA(x) mova(x) /* use function to avoid multiple eval */
128 #define CLRC emitcode("clr","c")
129 #define SETC emitcode("setb","c")
131 static lineNode *lineHead = NULL;
132 static lineNode *lineCurr = NULL;
134 static unsigned char SLMask[] =
135 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
136 0xE0, 0xC0, 0x80, 0x00};
137 static unsigned char SRMask[] =
138 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
139 0x07, 0x03, 0x01, 0x00};
146 /*-----------------------------------------------------------------*/
147 /* emitcode - writes the code into a file : for now it is simple */
148 /*-----------------------------------------------------------------*/
150 emitcode (char *inst, const char *fmt,...)
153 char lb[INITIAL_INLINEASM];
161 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
163 SNPRINTF (lb, sizeof(lb), "%s", inst);
164 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb), fmt, ap);
167 tvsprintf (lb, sizeof(lb), fmt, ap);
169 while (isspace ((unsigned char)*lbp))
173 lineCurr = (lineCurr ?
174 connectLine (lineCurr, newLineNode (lb)) :
175 (lineHead = newLineNode (lb)));
176 lineCurr->isInline = _G.inLine;
177 lineCurr->isDebug = _G.debugLine;
178 lineCurr->ic = _G.current_iCode;
179 lineCurr->isComment = (*lbp==';');
183 /*-----------------------------------------------------------------*/
184 /* mcs51_emitDebuggerSymbol - associate the current code location */
185 /* with a debugger symbol */
186 /*-----------------------------------------------------------------*/
188 mcs51_emitDebuggerSymbol (char * debugSym)
191 emitcode ("", "%s ==.", debugSym);
195 /*-----------------------------------------------------------------*/
196 /* mova - moves specified value into accumulator */
197 /*-----------------------------------------------------------------*/
201 /* do some early peephole optimization */
202 if (!strncmp(x, "a", 2) || !strncmp(x, "acc", 4))
205 emitcode("mov","a,%s", x);
208 /*-----------------------------------------------------------------*/
209 /* movc - moves specified value into the carry */
210 /*-----------------------------------------------------------------*/
218 else if (strcmp (s, "c"))
219 {/* it's not in carry already */
221 /* set C, if a >= 1 */
222 emitcode ("add", "a,#0xff");
226 /*-----------------------------------------------------------------*/
227 /* pushB - saves register B if necessary */
228 /*-----------------------------------------------------------------*/
232 bool pushedB = FALSE;
236 emitcode ("push", "b");
237 // printf("B was in use !\n");
247 /*-----------------------------------------------------------------*/
248 /* popB - restores value of register B if necessary */
249 /*-----------------------------------------------------------------*/
255 emitcode ("pop", "b");
263 /*-----------------------------------------------------------------*/
264 /* pushReg - saves register */
265 /*-----------------------------------------------------------------*/
267 pushReg (int index, bool bits_pushed)
269 regs * reg = mcs51_regWithIdx (index);
270 if (reg->type == REG_BIT)
273 emitcode ("push", "%s", reg->base);
277 emitcode ("push", "%s", reg->dname);
281 /*-----------------------------------------------------------------*/
282 /* popReg - restores register */
283 /*-----------------------------------------------------------------*/
285 popReg (int index, bool bits_popped)
287 regs * reg = mcs51_regWithIdx (index);
288 if (reg->type == REG_BIT)
291 emitcode ("pop", "%s", reg->base);
295 emitcode ("pop", "%s", reg->dname);
299 /*-----------------------------------------------------------------*/
300 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
301 /*-----------------------------------------------------------------*/
303 getFreePtr (iCode * ic, asmop ** aopp, bool result)
308 /* the logic: if r0 & r1 used in the instruction
309 then we are in trouble otherwise */
311 /* first check if r0 & r1 are used by this
312 instruction, in which case we are in trouble */
313 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
314 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
319 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
320 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
322 /* if no usage of r0 then return it */
325 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
326 (*aopp)->type = AOP_R0;
328 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
331 /* if no usage of r1 then return it */
334 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
335 (*aopp)->type = AOP_R1;
337 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
340 /* now we know they both have usage */
341 /* if r0 not used in this instruction */
344 /* push it if not already pushed */
347 emitcode ("mov", "b,%s",
348 mcs51_regWithIdx (R0_IDX)->dname);
351 else if (!_G.r0Pushed)
353 emitcode ("push", "%s",
354 mcs51_regWithIdx (R0_IDX)->dname);
358 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
359 (*aopp)->type = AOP_R0;
361 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
364 /* if r1 not used then */
368 /* push it if not already pushed */
371 emitcode ("mov", "b,%s",
372 mcs51_regWithIdx (R1_IDX)->dname);
375 else if (!_G.r1Pushed)
377 emitcode ("push", "%s",
378 mcs51_regWithIdx (R1_IDX)->dname);
382 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
383 (*aopp)->type = AOP_R1;
384 return mcs51_regWithIdx (R1_IDX);
387 /* I said end of world, but not quite end of world yet */
389 /* we can push it on the stack */
390 (*aopp)->type = AOP_STK;
393 /* in the case that result AND left AND right needs a pointer reg
394 we can safely use the result's */
395 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R0_IDX)) {
396 (*aopp)->type = AOP_R0;
397 return mcs51_regWithIdx (R0_IDX);
399 if (bitVectBitValue (mcs51_rUmaskForOp(IC_RESULT(ic)), R1_IDX)) {
400 (*aopp)->type = AOP_R1;
401 return mcs51_regWithIdx (R1_IDX);
405 /* now this is REALLY the end of the world */
406 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
407 "getFreePtr should never reach here");
412 /*-----------------------------------------------------------------*/
413 /* getTempRegs - initialize an array of pointers to GPR registers */
414 /* that are not in use. Returns 1 if the requested */
415 /* number of registers were available, 0 otherwise. */
416 /*-----------------------------------------------------------------*/
418 getTempRegs(regs **tempRegs, int size, iCode *ic)
425 ic = _G.current_iCode;
431 freeRegs = newBitVect(8);
432 bitVectSetBit (freeRegs, R2_IDX);
433 bitVectSetBit (freeRegs, R3_IDX);
434 bitVectSetBit (freeRegs, R4_IDX);
435 bitVectSetBit (freeRegs, R5_IDX);
436 bitVectSetBit (freeRegs, R6_IDX);
437 bitVectSetBit (freeRegs, R7_IDX);
439 if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
441 bitVect * newfreeRegs;
442 newfreeRegs = bitVectIntersect (freeRegs, _G.currentFunc->regsUsed);
443 freeBitVect(freeRegs);
444 freeRegs = newfreeRegs;
446 freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
449 for (i=0; i<freeRegs->size; i++)
451 if (bitVectBitValue(freeRegs,i))
452 tempRegs[offset++] = mcs51_regWithIdx(i);
455 freeBitVect(freeRegs);
460 freeBitVect(freeRegs);
465 /*-----------------------------------------------------------------*/
466 /* newAsmop - creates a new asmOp */
467 /*-----------------------------------------------------------------*/
469 newAsmop (short type)
473 aop = Safe_calloc (1, sizeof (asmop));
479 /*-----------------------------------------------------------------*/
480 /* pointerCode - returns the code for a pointer type */
481 /*-----------------------------------------------------------------*/
483 pointerCode (sym_link * etype)
486 return PTR_TYPE (SPEC_OCLS (etype));
490 /*-----------------------------------------------------------------*/
491 /* leftRightUseAcc - returns size of accumulator use by operands */
492 /*-----------------------------------------------------------------*/
494 leftRightUseAcc(iCode *ic)
503 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
504 "null iCode pointer");
511 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
514 size = getSize (OP_SYMBOL (op)->type);
519 else if (ic->op == JUMPTABLE)
522 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
525 size = getSize (OP_SYMBOL (op)->type);
533 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
536 size = getSize (OP_SYMBOL (op)->type);
541 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
544 size = getSize (OP_SYMBOL (op)->type);
556 /*-----------------------------------------------------------------*/
557 /* aopForSym - for a true symbol */
558 /*-----------------------------------------------------------------*/
560 aopForSym (iCode * ic, symbol * sym, bool result)
565 wassertl (ic != NULL, "Got a null iCode");
566 wassertl (sym != NULL, "Got a null symbol");
568 space = SPEC_OCLS (sym->etype);
570 /* if already has one */
573 sym->aop->allocated++;
577 /* assign depending on the storage class */
578 /* if it is on the stack or indirectly addressable */
579 /* space we need to assign either r0 or r1 to it */
580 if (sym->onStack || sym->iaccess)
582 sym->aop = aop = newAsmop (0);
583 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
584 aop->size = getSize (sym->type);
586 /* now assign the address of the variable to
587 the pointer register */
588 if (aop->type != AOP_STK)
593 char offset = ((sym->stack < 0) ?
594 ((char) (sym->stack - _G.nRegsSaved)) :
595 ((char) sym->stack)) & 0xff;
597 if ((offset >= -3) && (offset <= 3))
599 emitcode ("mov", "%s,%s",
600 aop->aopu.aop_ptr->name, SYM_BP (sym));
603 emitcode ("dec", aop->aopu.aop_ptr->name);
608 emitcode ("inc", aop->aopu.aop_ptr->name);
614 if (_G.accInUse || leftRightUseAcc (ic))
615 emitcode ("push", "acc");
616 emitcode ("mov", "a,%s", SYM_BP (sym));
617 emitcode ("add", "a,#0x%02x", offset);
618 emitcode ("mov", "%s,a",
619 aop->aopu.aop_ptr->name);
620 if (_G.accInUse || leftRightUseAcc (ic))
621 emitcode ("pop", "acc");
625 emitcode ("mov", "%s,#%s",
626 aop->aopu.aop_ptr->name,
628 aop->paged = space->paged;
631 aop->aopu.aop_stk = sym->stack;
635 /* if in bit space */
636 if (IN_BITSPACE (space))
638 sym->aop = aop = newAsmop (AOP_CRY);
639 aop->aopu.aop_dir = sym->rname;
640 aop->size = getSize (sym->type);
643 /* if it is in direct space */
644 if (IN_DIRSPACE (space))
646 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
647 //printTypeChainRaw(sym->type, NULL);
648 //printf("space = %s\n", space ? space->sname : "NULL");
649 sym->aop = aop = newAsmop (AOP_DIR);
650 aop->aopu.aop_dir = sym->rname;
651 aop->size = getSize (sym->type);
655 /* special case for a function */
656 if (IS_FUNC (sym->type))
658 sym->aop = aop = newAsmop (AOP_IMMD);
659 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
660 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
661 aop->size = getSize (sym->type);
665 /* only remaining is far space */
666 /* in which case DPTR gets the address */
667 sym->aop = aop = newAsmop (AOP_DPTR);
668 emitcode ("mov", "dptr,#%s", sym->rname);
669 aop->size = getSize (sym->type);
671 /* if it is in code space */
672 if (IN_CODESPACE (space))
678 /*-----------------------------------------------------------------*/
679 /* aopForRemat - rematerialzes an object */
680 /*-----------------------------------------------------------------*/
682 aopForRemat (symbol * sym)
684 iCode *ic = sym->rematiCode;
685 asmop *aop = newAsmop (AOP_IMMD);
692 val += (int) operandLitValue (IC_RIGHT (ic));
693 else if (ic->op == '-')
694 val -= (int) operandLitValue (IC_RIGHT (ic));
695 else if (IS_CAST_ICODE(ic)) {
696 sym_link *from_type = operandType(IC_RIGHT(ic));
697 aop->aopu.aop_immd.from_cast_remat = 1;
698 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
699 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
703 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
707 sprintf (buffer, "(%s %c 0x%04x)",
708 OP_SYMBOL (IC_LEFT (ic))->rname,
709 val >= 0 ? '+' : '-',
712 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
714 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
715 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
716 /* set immd2 field if required */
717 if (aop->aopu.aop_immd.from_cast_remat) {
718 sprintf(buffer,"#0x%02x",ptr_type);
719 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
720 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
726 /*-----------------------------------------------------------------*/
727 /* regsInCommon - two operands have some registers in common */
728 /*-----------------------------------------------------------------*/
730 regsInCommon (operand * op1, operand * op2)
735 /* if they have registers in common */
736 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
739 sym1 = OP_SYMBOL (op1);
740 sym2 = OP_SYMBOL (op2);
742 if (sym1->nRegs == 0 || sym2->nRegs == 0)
745 for (i = 0; i < sym1->nRegs; i++)
751 for (j = 0; j < sym2->nRegs; j++)
756 if (sym2->regs[j] == sym1->regs[i])
764 /*-----------------------------------------------------------------*/
765 /* operandsEqu - equivalent */
766 /*-----------------------------------------------------------------*/
768 operandsEqu (operand * op1, operand * op2)
772 /* if they're not symbols */
773 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
776 sym1 = OP_SYMBOL (op1);
777 sym2 = OP_SYMBOL (op2);
779 /* if both are itemps & one is spilt
780 and the other is not then false */
781 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
782 sym1->isspilt != sym2->isspilt)
785 /* if they are the same */
789 /* if they have the same rname */
790 if (sym1->rname[0] && sym2->rname[0] &&
791 strcmp (sym1->rname, sym2->rname) == 0 &&
792 !(IS_PARM (op2) && IS_ITEMP (op1)))
795 /* if left is a tmp & right is not */
796 if (IS_ITEMP (op1) &&
799 (sym1->usl.spillLoc == sym2))
802 if (IS_ITEMP (op2) &&
806 (sym2->usl.spillLoc == sym1))
812 /*-----------------------------------------------------------------*/
813 /* sameReg - two asmops have the same register at given offsets */
814 /*-----------------------------------------------------------------*/
816 sameReg (asmop * aop1, int off1, asmop * aop2, int off2)
818 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
821 if (aop1->type != aop2->type)
824 if (aop1->aopu.aop_reg[off1] != aop2->aopu.aop_reg[off2])
830 /*-----------------------------------------------------------------*/
831 /* sameRegs - two asmops have the same registers */
832 /*-----------------------------------------------------------------*/
834 sameRegs (asmop * aop1, asmop * aop2)
841 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
844 if (aop1->type != aop2->type)
847 if (aop1->size != aop2->size)
850 for (i = 0; i < aop1->size; i++)
851 if (aop1->aopu.aop_reg[i] != aop2->aopu.aop_reg[i])
857 /*-----------------------------------------------------------------*/
858 /* aopOp - allocates an asmop for an operand : */
859 /*-----------------------------------------------------------------*/
861 aopOp (operand * op, iCode * ic, bool result)
870 /* if this a literal */
871 if (IS_OP_LITERAL (op))
873 op->aop = aop = newAsmop (AOP_LIT);
874 aop->aopu.aop_lit = op->operand.valOperand;
875 aop->size = getSize (operandType (op));
879 /* if already has a asmop then continue */
882 op->aop->allocated++;
886 /* if the underlying symbol has a aop */
887 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
889 op->aop = OP_SYMBOL (op)->aop;
890 op->aop->allocated++;
894 /* if this is a true symbol */
895 if (IS_TRUE_SYMOP (op))
897 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
901 /* this is a temporary : this has
907 e) can be a return use only */
909 sym = OP_SYMBOL (op);
911 /* if the type is a conditional */
912 if (sym->regType == REG_CND)
914 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
919 /* if it is spilt then two situations
921 b) has a spill location */
922 if (sym->isspilt || sym->nRegs == 0)
925 /* rematerialize it NOW */
928 sym->aop = op->aop = aop =
930 aop->size = getSize (sym->type);
937 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
938 aop->size = getSize (sym->type);
939 for (i = 0; i < 2; i++)
940 aop->aopu.aop_str[i] = accUse[i];
948 aop = op->aop = sym->aop = newAsmop (AOP_STR);
949 aop->size = getSize (sym->type);
950 for (i = 0; i < fReturnSizeMCS51; i++)
951 aop->aopu.aop_str[i] = fReturn[i];
955 if (sym->usl.spillLoc)
957 asmop *oldAsmOp = NULL;
959 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
961 /* force a new aop if sizes differ */
962 oldAsmOp = sym->usl.spillLoc->aop;
963 sym->usl.spillLoc->aop = NULL;
965 sym->aop = op->aop = aop =
966 aopForSym (ic, sym->usl.spillLoc, result);
967 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
969 /* Don't reuse the new aop, go with the last one */
970 sym->usl.spillLoc->aop = oldAsmOp;
972 aop->size = getSize (sym->type);
976 /* else must be a dummy iTemp */
977 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
978 aop->size = getSize (sym->type);
982 /* if the type is a bit register */
983 if (sym->regType == REG_BIT)
985 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
986 aop->size = sym->nRegs;//1???
987 aop->aopu.aop_reg[0] = sym->regs[0];
988 aop->aopu.aop_dir = sym->regs[0]->name;
992 /* must be in a register */
993 sym->aop = op->aop = aop = newAsmop (AOP_REG);
994 aop->size = sym->nRegs;
995 for (i = 0; i < sym->nRegs; i++)
996 aop->aopu.aop_reg[i] = sym->regs[i];
999 /*-----------------------------------------------------------------*/
1000 /* freeAsmop - free up the asmop given to an operand */
1001 /*----------------------------------------------------------------*/
1003 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1020 /* depending on the asmop type only three cases need work
1021 AOP_R0, AOP_R1 & AOP_STK */
1027 emitcode ("mov", "r0,b");
1030 else if (_G.r0Pushed)
1034 emitcode ("pop", "ar0");
1038 bitVectUnSetBit (ic->rUsed, R0_IDX);
1044 emitcode ("mov", "r1,b");
1051 emitcode ("pop", "ar1");
1055 bitVectUnSetBit (ic->rUsed, R1_IDX);
1061 int stk = aop->aopu.aop_stk + aop->size - 1;
1062 bitVectUnSetBit (ic->rUsed, R0_IDX);
1063 bitVectUnSetBit (ic->rUsed, R1_IDX);
1065 getFreePtr (ic, &aop, FALSE);
1069 emitcode ("mov", "a,_bp");
1070 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1071 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1075 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1080 emitcode ("pop", "acc");
1081 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1084 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1087 freeAsmop (op, NULL, ic, TRUE);
1090 emitcode ("pop", "ar1");
1096 emitcode ("pop", "ar0");
1103 /* all other cases just dealloc */
1109 OP_SYMBOL (op)->aop = NULL;
1110 /* if the symbol has a spill */
1112 SPIL_LOC (op)->aop = NULL;
1117 /*------------------------------------------------------------------*/
1118 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1119 /* pop r0 or r1 off stack if pushed */
1120 /*------------------------------------------------------------------*/
1122 freeForBranchAsmop (operand * op)
1134 if (!aop->allocated)
1142 emitcode ("mov", "r0,b");
1144 else if (_G.r0Pushed)
1146 emitcode ("pop", "ar0");
1153 emitcode ("mov", "r1,b");
1155 else if (_G.r1Pushed)
1157 emitcode ("pop", "ar1");
1164 int stk = aop->aopu.aop_stk + aop->size - 1;
1166 emitcode ("mov", "b,r0");
1169 emitcode ("mov", "a,_bp");
1170 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1171 emitcode ("mov", "r0,a");
1175 emitcode ("mov", "r0,_bp");
1180 emitcode ("pop", "acc");
1181 emitcode ("mov", "@r0,a");
1184 emitcode ("dec", "r0");
1186 emitcode ("mov", "r0,b");
1192 /*-----------------------------------------------------------------*/
1193 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1194 /* clobber the accumulator */
1195 /*-----------------------------------------------------------------*/
1197 aopGetUsesAcc (operand * oper, int offset)
1199 asmop * aop = AOP (oper);
1201 if (offset > (aop->size - 1))
1219 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1230 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1236 /* Error case --- will have been caught already */
1242 /*-----------------------------------------------------------------*/
1243 /* aopGet - for fetching value of the aop */
1244 /*-----------------------------------------------------------------*/
1246 aopGet (operand * oper, int offset, bool bit16, bool dname)
1250 asmop * aop = AOP (oper);
1252 /* offset is greater than
1254 if (offset > (aop->size - 1) &&
1255 aop->type != AOP_LIT)
1258 /* depending on type */
1266 /* if we need to increment it */
1267 while (offset > aop->coff)
1269 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1273 while (offset < aop->coff)
1275 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1282 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1283 return (dname ? "acc" : "a");
1285 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1286 rs = Safe_calloc (1, strlen (s) + 1);
1291 if (aop->code && aop->coff==0 && offset>=1) {
1292 emitcode ("mov", "a,#0x%02x", offset);
1293 emitcode ("movc", "a,@a+dptr");
1294 return (dname ? "acc" : "a");
1297 while (offset > aop->coff)
1299 emitcode ("inc", "dptr");
1303 while (offset < aop->coff)
1305 emitcode ("lcall", "__decdptr");
1312 emitcode ("clr", "a");
1313 emitcode ("movc", "a,@a+dptr");
1317 emitcode ("movx", "a,@dptr");
1319 return (dname ? "acc" : "a");
1323 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1324 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1326 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1328 sprintf (s, "#(%s >> %d)",
1329 aop->aopu.aop_immd.aop_immd1,
1333 aop->aopu.aop_immd.aop_immd1);
1334 rs = Safe_calloc (1, strlen (s) + 1);
1339 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1340 sprintf (s, "(%s >> %d)",
1341 aop->aopu.aop_dir, offset * 8);
1343 sprintf (s, "(%s + %d)",
1347 sprintf (s, "%s", aop->aopu.aop_dir);
1348 rs = Safe_calloc (1, strlen (s) + 1);
1354 return aop->aopu.aop_reg[offset]->dname;
1356 return aop->aopu.aop_reg[offset]->name;
1359 emitcode ("clr", "a");
1360 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1361 emitcode ("rlc", "a");
1362 return (dname ? "acc" : "a");
1365 if (!offset && dname)
1367 return aop->aopu.aop_str[offset];
1370 return aopLiteral (aop->aopu.aop_lit, offset);
1374 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1378 return aop->aopu.aop_str[offset];
1382 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1383 "aopget got unsupported aop->type");
1387 /*-----------------------------------------------------------------*/
1388 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1389 /* clobber the accumulator */
1390 /*-----------------------------------------------------------------*/
1392 aopPutUsesAcc (operand * oper, const char *s, int offset)
1394 asmop * aop = AOP (oper);
1396 if (offset > (aop->size - 1))
1406 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1412 return ((aop->paged) || (*s == '@'));
1416 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1424 /* Error case --- will have been caught already */
1430 /*-----------------------------------------------------------------*/
1431 /* aopPut - puts a string for a aop and indicates if acc is in use */
1432 /*-----------------------------------------------------------------*/
1434 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1437 bool accuse = FALSE;
1438 asmop * aop = AOP (result);
1440 if (aop->size && offset > (aop->size - 1))
1442 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1443 "aopPut got offset > aop->size");
1447 /* will assign value to value */
1448 /* depending on where it is ofcourse */
1452 MOVA (s); /* read s in case it was volatile */
1457 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1458 sprintf (d, "(%s >> %d)", aop->aopu.aop_dir, offset * 8);
1460 sprintf (d, "(%s + %d)", aop->aopu.aop_dir, offset);
1462 sprintf (d, "%s", aop->aopu.aop_dir);
1464 if (strcmp (d, s) || bvolatile)
1465 emitcode ("mov", "%s,%s", d, s);
1466 if (!strcmp (d, "acc"))
1472 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1473 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1476 strcmp (s, "r0") == 0 ||
1477 strcmp (s, "r1") == 0 ||
1478 strcmp (s, "r2") == 0 ||
1479 strcmp (s, "r3") == 0 ||
1480 strcmp (s, "r4") == 0 ||
1481 strcmp (s, "r5") == 0 ||
1482 strcmp (s, "r6") == 0 ||
1483 strcmp (s, "r7") == 0)
1484 emitcode ("mov", "%s,%s",
1485 aop->aopu.aop_reg[offset]->dname, s);
1487 emitcode ("mov", "%s,%s",
1488 aop->aopu.aop_reg[offset]->name, s);
1495 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1496 "aopPut writing to code space");
1500 while (offset > aop->coff)
1503 emitcode ("inc", "dptr");
1506 while (offset < aop->coff)
1509 emitcode ("lcall", "__decdptr");
1514 /* if not in accumulator */
1517 emitcode ("movx", "@dptr,a");
1522 while (offset > aop->coff)
1525 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1527 while (offset < aop->coff)
1530 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1537 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1542 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1544 else if (strcmp (s, "r0") == 0 ||
1545 strcmp (s, "r1") == 0 ||
1546 strcmp (s, "r2") == 0 ||
1547 strcmp (s, "r3") == 0 ||
1548 strcmp (s, "r4") == 0 ||
1549 strcmp (s, "r5") == 0 ||
1550 strcmp (s, "r6") == 0 ||
1551 strcmp (s, "r7") == 0)
1554 sprintf (buffer, "a%s", s);
1555 emitcode ("mov", "@%s,%s",
1556 aop->aopu.aop_ptr->name, buffer);
1559 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1564 if (strcmp (s, "a") == 0)
1565 emitcode ("push", "acc");
1569 emitcode ("push", "acc");
1571 emitcode ("push", s);
1577 /* if not bit variable */
1578 if (!aop->aopu.aop_dir)
1580 /* inefficient: move carry into A and use jz/jnz */
1581 emitcode ("clr", "a");
1582 emitcode ("rlc", "a");
1588 emitcode ("clr", "%s", aop->aopu.aop_dir);
1590 emitcode ("setb", "%s", aop->aopu.aop_dir);
1591 else if (!strcmp (s, "c"))
1592 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1593 else if (strcmp (s, aop->aopu.aop_dir))
1596 /* set C, if a >= 1 */
1597 emitcode ("add", "a,#0xff");
1598 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1605 if (strcmp (aop->aopu.aop_str[offset], s) ||
1607 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1613 if (!offset && (strcmp (s, "acc") == 0) &&
1617 if (strcmp (aop->aopu.aop_str[offset], s) &&
1619 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1623 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1624 "aopPut got unsupported aop->type");
1633 /*-----------------------------------------------------------------*/
1634 /* pointToEnd :- points to the last byte of the operand */
1635 /*-----------------------------------------------------------------*/
1637 pointToEnd (asmop * aop)
1643 aop->coff = count = (aop->size - 1);
1649 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1653 emitcode ("inc", "dptr");
1660 /*-----------------------------------------------------------------*/
1661 /* reAdjustPreg - points a register back to where it should */
1662 /*-----------------------------------------------------------------*/
1664 reAdjustPreg (asmop * aop)
1666 if ((aop->coff==0) || aop->size <= 1)
1674 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1679 emitcode ("lcall", "__decdptr");
1686 /*-----------------------------------------------------------------*/
1687 /* opIsGptr: returns non-zero if the passed operand is */
1688 /* a generic pointer type. */
1689 /*-----------------------------------------------------------------*/
1691 opIsGptr (operand * op)
1693 sym_link *type = operandType (op);
1695 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1702 /*-----------------------------------------------------------------*/
1703 /* getDataSize - get the operand data size */
1704 /*-----------------------------------------------------------------*/
1706 getDataSize (operand * op)
1709 size = AOP_SIZE (op);
1710 if (size == GPTRSIZE)
1712 sym_link *type = operandType (op);
1713 if (IS_GENPTR (type))
1715 /* generic pointer; arithmetic operations
1716 * should ignore the high byte (pointer type).
1724 /*-----------------------------------------------------------------*/
1725 /* outAcc - output Acc */
1726 /*-----------------------------------------------------------------*/
1728 outAcc (operand * result)
1731 size = getDataSize (result);
1734 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1737 /* unsigned or positive */
1740 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1745 /*-----------------------------------------------------------------*/
1746 /* outBitC - output a bit C */
1747 /*-----------------------------------------------------------------*/
1749 outBitC (operand * result)
1751 /* if the result is bit */
1752 if (AOP_TYPE (result) == AOP_CRY)
1753 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1756 emitcode ("clr", "a");
1757 emitcode ("rlc", "a");
1762 /*-----------------------------------------------------------------*/
1763 /* toBoolean - emit code for orl a,operator(sizeop) */
1764 /*-----------------------------------------------------------------*/
1766 toBoolean (operand * oper)
1768 int size = AOP_SIZE (oper) - 1;
1770 bool AccUsed = FALSE;
1773 while (!AccUsed && size--)
1775 AccUsed |= aopGetUsesAcc(oper, offset++);
1778 size = AOP_SIZE (oper) - 1;
1780 MOVA (aopGet (oper, 0, FALSE, FALSE));
1781 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1784 emitcode("mov", "b,a");
1787 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1788 emitcode ("orl", "b,a");
1790 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1791 emitcode ("orl", "a,b");
1798 emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1804 /*-----------------------------------------------------------------*/
1805 /* genNot - generate code for ! operation */
1806 /*-----------------------------------------------------------------*/
1812 D(emitcode ("; genNot",""));
1814 /* assign asmOps to operand & result */
1815 aopOp (IC_LEFT (ic), ic, FALSE);
1816 aopOp (IC_RESULT (ic), ic, TRUE);
1818 /* if in bit space then a special case */
1819 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1821 /* if left==result then cpl bit */
1822 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1824 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1828 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1829 emitcode ("cpl", "c");
1830 outBitC (IC_RESULT (ic));
1835 toBoolean (IC_LEFT (ic));
1837 /* set C, if a == 0 */
1838 tlbl = newiTempLabel (NULL);
1839 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1840 emitcode ("", "%05d$:", tlbl->key + 100);
1841 outBitC (IC_RESULT (ic));
1844 /* release the aops */
1845 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1846 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1850 /*-----------------------------------------------------------------*/
1851 /* genCpl - generate code for complement */
1852 /*-----------------------------------------------------------------*/
1859 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1861 D(emitcode (";", "genCpl"));
1863 /* assign asmOps to operand & result */
1864 aopOp (IC_LEFT (ic), ic, FALSE);
1865 aopOp (IC_RESULT (ic), ic, TRUE);
1867 /* special case if in bit space */
1868 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1872 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1873 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1875 /* promotion rules are responsible for this strange result:
1876 bit -> int -> ~int -> bit
1877 uchar -> int -> ~int -> bit
1879 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1883 tlbl=newiTempLabel(NULL);
1884 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1885 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1886 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1887 IS_AOP_PREG (IC_LEFT (ic)))
1889 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1894 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1896 emitcode ("", "%05d$:", tlbl->key + 100);
1897 outBitC (IC_RESULT(ic));
1901 size = AOP_SIZE (IC_RESULT (ic));
1904 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1906 emitcode ("cpl", "a");
1907 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1912 /* release the aops */
1913 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1914 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1917 /*-----------------------------------------------------------------*/
1918 /* genUminusFloat - unary minus for floating points */
1919 /*-----------------------------------------------------------------*/
1921 genUminusFloat (operand * op, operand * result)
1923 int size, offset = 0;
1926 D(emitcode ("; genUminusFloat",""));
1928 /* for this we just copy and then flip the bit */
1930 size = AOP_SIZE (op) - 1;
1935 aopGet (op, offset, FALSE, FALSE),
1937 isOperandVolatile (result, FALSE));
1941 l = aopGet (op, offset, FALSE, FALSE);
1945 emitcode ("cpl", "acc.7");
1946 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1949 /*-----------------------------------------------------------------*/
1950 /* genUminus - unary minus code generation */
1951 /*-----------------------------------------------------------------*/
1953 genUminus (iCode * ic)
1956 sym_link *optype, *rtype;
1959 D(emitcode ("; genUminus",""));
1962 aopOp (IC_LEFT (ic), ic, FALSE);
1963 aopOp (IC_RESULT (ic), ic, TRUE);
1965 /* if both in bit space then special
1967 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1968 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1971 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1972 emitcode ("cpl", "c");
1973 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1977 optype = operandType (IC_LEFT (ic));
1978 rtype = operandType (IC_RESULT (ic));
1980 /* if float then do float stuff */
1981 if (IS_FLOAT (optype))
1983 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1987 /* otherwise subtract from zero */
1988 size = AOP_SIZE (IC_LEFT (ic));
1993 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1994 if (!strcmp (l, "a"))
1998 emitcode ("cpl", "a");
1999 emitcode ("addc", "a,#0");
2005 emitcode ("clr", "a");
2006 emitcode ("subb", "a,%s", l);
2008 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
2011 /* if any remaining bytes in the result */
2012 /* we just need to propagate the sign */
2013 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2015 emitcode ("rlc", "a");
2016 emitcode ("subb", "a,acc");
2018 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
2022 /* release the aops */
2023 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2024 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2027 /*-----------------------------------------------------------------*/
2028 /* saveRegisters - will look for a call and save the registers */
2029 /*-----------------------------------------------------------------*/
2031 saveRegisters (iCode * lic)
2038 for (ic = lic; ic; ic = ic->next)
2039 if (ic->op == CALL || ic->op == PCALL)
2044 fprintf (stderr, "found parameter push with no function call\n");
2048 /* if the registers have been saved already or don't need to be then
2052 if (IS_SYMOP(IC_LEFT(ic)) &&
2053 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2054 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2057 /* save the registers in use at this time but skip the
2058 ones for the result */
2059 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2060 mcs51_rUmaskForOp (IC_RESULT(ic)));
2063 if (options.useXstack)
2065 int count = bitVectnBitsOn (rsave);
2069 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2070 if (reg->type == REG_BIT)
2072 emitcode ("mov", "a,%s", reg->base);
2076 emitcode ("mov", "a,%s", reg->name);
2078 emitcode ("mov", "r0,%s", spname);
2079 emitcode ("inc", "%s", spname);// allocate before use
2080 emitcode ("movx", "@r0,a");
2081 if (bitVectBitValue (rsave, R0_IDX))
2082 emitcode ("mov", "r0,a");
2084 else if (count != 0)
2086 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2087 int nBits = bitVectnBitsOn (rsavebits);
2091 count = count - nBits + 1;
2092 /* remove all but the first bits as they are pushed all at once */
2093 rsave = bitVectCplAnd (rsave, rsavebits);
2094 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2097 if (bitVectBitValue (rsave, R0_IDX))
2099 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2101 emitcode ("mov", "r0,%s", spname);
2103 emitcode ("add", "a,#%d", count);
2104 emitcode ("mov", "%s,a", spname);
2105 for (i = 0; i < mcs51_nRegs; i++)
2107 if (bitVectBitValue (rsave, i))
2109 regs * reg = mcs51_regWithIdx (i);
2112 emitcode ("pop", "acc");
2113 emitcode ("push", "acc");
2115 else if (reg->type == REG_BIT)
2117 emitcode ("mov", "a,%s", reg->base);
2121 emitcode ("mov", "a,%s", reg->name);
2123 emitcode ("movx", "@r0,a");
2126 emitcode ("inc", "r0");
2130 if (bitVectBitValue (rsave, R0_IDX))
2132 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2138 bool bits_pushed = FALSE;
2139 for (i = 0; i < mcs51_nRegs; i++)
2141 if (bitVectBitValue (rsave, i))
2143 bits_pushed = pushReg (i, bits_pushed);
2149 /*-----------------------------------------------------------------*/
2150 /* unsaveRegisters - pop the pushed registers */
2151 /*-----------------------------------------------------------------*/
2153 unsaveRegisters (iCode * ic)
2158 /* restore the registers in use at this time but skip the
2159 ones for the result */
2160 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2161 mcs51_rUmaskForOp (IC_RESULT(ic)));
2163 if (options.useXstack)
2165 int count = bitVectnBitsOn (rsave);
2169 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2170 emitcode ("mov", "r0,%s", spname);
2171 emitcode ("dec", "r0");
2172 emitcode ("movx", "a,@r0");
2173 if (reg->type == REG_BIT)
2175 emitcode ("mov", "%s,a", reg->base);
2179 emitcode ("mov", "%s,a", reg->name);
2181 emitcode ("dec", "%s", spname);
2183 else if (count != 0)
2185 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2186 int nBits = bitVectnBitsOn (rsavebits);
2190 count = count - nBits + 1;
2191 /* remove all but the first bits as they are popped all at once */
2192 rsave = bitVectCplAnd (rsave, rsavebits);
2193 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2196 emitcode ("mov", "r0,%s", spname);
2197 for (i = mcs51_nRegs; i >= 0; i--)
2199 if (bitVectBitValue (rsave, i))
2201 regs * reg = mcs51_regWithIdx (i);
2202 emitcode ("dec", "r0");
2203 emitcode ("movx", "a,@r0");
2206 emitcode ("push", "acc");
2208 else if (reg->type == REG_BIT)
2210 emitcode ("mov", "%s,a", reg->base);
2214 emitcode ("mov", "%s,a", reg->name);
2218 emitcode ("mov", "%s,r0", spname);
2219 if (bitVectBitValue (rsave, R0_IDX))
2221 emitcode ("pop", "ar0");
2227 bool bits_popped = FALSE;
2228 for (i = mcs51_nRegs; i >= 0; i--)
2230 if (bitVectBitValue (rsave, i))
2232 bits_popped = popReg (i, bits_popped);
2239 /*-----------------------------------------------------------------*/
2241 /*-----------------------------------------------------------------*/
2243 pushSide (operand * oper, int size)
2248 char *l = aopGet (oper, offset++, FALSE, TRUE);
2249 if (AOP_TYPE (oper) != AOP_REG &&
2250 AOP_TYPE (oper) != AOP_DIR &&
2254 emitcode ("push", "acc");
2258 emitcode ("push", "%s", l);
2263 /*-----------------------------------------------------------------*/
2264 /* assignResultValue - also indicates if acc is in use afterwards */
2265 /*-----------------------------------------------------------------*/
2267 assignResultValue (operand * oper, operand * func)
2270 int size = AOP_SIZE (oper);
2271 bool accuse = FALSE;
2272 bool pushedA = FALSE;
2274 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2280 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2282 emitcode ("push", "acc");
2287 if ((offset == 3) && pushedA)
2288 emitcode ("pop", "acc");
2289 accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2296 /*-----------------------------------------------------------------*/
2297 /* genXpush - pushes onto the external stack */
2298 /*-----------------------------------------------------------------*/
2300 genXpush (iCode * ic)
2302 asmop *aop = newAsmop (0);
2304 int size, offset = 0;
2306 D(emitcode ("; genXpush",""));
2308 aopOp (IC_LEFT (ic), ic, FALSE);
2309 r = getFreePtr (ic, &aop, FALSE);
2311 size = AOP_SIZE (IC_LEFT (ic));
2315 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2316 emitcode ("mov", "%s,%s", r->name, spname);
2317 emitcode ("inc", "%s", spname); // allocate space first
2318 emitcode ("movx", "@%s,a", r->name);
2322 // allocate space first
2323 emitcode ("mov", "%s,%s", r->name, spname);
2325 emitcode ("add", "a,#%d", size);
2326 emitcode ("mov", "%s,a", spname);
2330 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2331 emitcode ("movx", "@%s,a", r->name);
2332 emitcode ("inc", "%s", r->name);
2336 freeAsmop (NULL, aop, ic, TRUE);
2337 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2340 /*-----------------------------------------------------------------*/
2341 /* genIpush - generate code for pushing this gets a little complex */
2342 /*-----------------------------------------------------------------*/
2344 genIpush (iCode * ic)
2346 int size, offset = 0;
2350 D(emitcode ("; genIpush",""));
2352 /* if this is not a parm push : ie. it is spill push
2353 and spill push is always done on the local stack */
2357 /* and the item is spilt then do nothing */
2358 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2361 aopOp (IC_LEFT (ic), ic, FALSE);
2362 size = AOP_SIZE (IC_LEFT (ic));
2363 /* push it on the stack */
2366 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2372 emitcode ("push", "%s", l);
2377 /* this is a parameter push: in this case we call
2378 the routine to find the call and save those
2379 registers that need to be saved */
2382 /* if use external stack then call the external
2383 stack pushing routine */
2384 if (options.useXstack)
2390 /* then do the push */
2391 aopOp (IC_LEFT (ic), ic, FALSE);
2393 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2394 size = AOP_SIZE (IC_LEFT (ic));
2398 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2399 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2400 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2403 if (strcmp (l, prev) || *l == '@')
2405 emitcode ("push", "acc");
2409 emitcode ("push", "%s", l);
2414 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2417 /*-----------------------------------------------------------------*/
2418 /* genIpop - recover the registers: can happen only for spilling */
2419 /*-----------------------------------------------------------------*/
2421 genIpop (iCode * ic)
2425 D(emitcode ("; genIpop",""));
2427 /* if the temp was not pushed then */
2428 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2431 aopOp (IC_LEFT (ic), ic, FALSE);
2432 size = AOP_SIZE (IC_LEFT (ic));
2433 offset = (size - 1);
2435 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2438 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2441 /*-----------------------------------------------------------------*/
2442 /* saveRBank - saves an entire register bank on the stack */
2443 /*-----------------------------------------------------------------*/
2445 saveRBank (int bank, iCode * ic, bool pushPsw)
2448 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2452 if (options.useXstack)
2456 /* Assume r0 is available for use. */
2457 r = mcs51_regWithIdx (R0_IDX);;
2462 r = getFreePtr (ic, &aop, FALSE);
2464 // allocate space first
2465 emitcode ("mov", "%s,%s", r->name, spname);
2467 emitcode ("add", "a,#%d", count);
2468 emitcode ("mov", "%s,a", spname);
2471 for (i = 0; i < 8; i++)
2473 if (options.useXstack)
2475 emitcode ("mov", "a,(%s+%d)",
2476 regs8051[i].base, 8 * bank + regs8051[i].offset);
2477 emitcode ("movx", "@%s,a", r->name);
2479 emitcode ("inc", "%s", r->name);
2482 emitcode ("push", "(%s+%d)",
2483 regs8051[i].base, 8 * bank + regs8051[i].offset);
2486 if (mcs51_nRegs > 8)
2488 if (options.useXstack)
2490 emitcode ("mov", "a,bits");
2491 emitcode ("movx", "@%s,a", r->name);
2493 emitcode ("inc", "%s", r->name);
2497 emitcode ("push", "bits");
2504 if (options.useXstack)
2506 emitcode ("mov", "a,psw");
2507 emitcode ("movx", "@%s,a", r->name);
2512 emitcode ("push", "psw");
2515 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2520 freeAsmop (NULL, aop, ic, TRUE);
2529 /*-----------------------------------------------------------------*/
2530 /* unsaveRBank - restores the register bank from stack */
2531 /*-----------------------------------------------------------------*/
2533 unsaveRBank (int bank, iCode * ic, bool popPsw)
2539 if (options.useXstack)
2543 /* Assume r0 is available for use. */
2544 r = mcs51_regWithIdx (R0_IDX);;
2549 r = getFreePtr (ic, &aop, FALSE);
2551 emitcode ("mov", "%s,%s", r->name, spname);
2556 if (options.useXstack)
2558 emitcode ("dec", "%s", r->name);
2559 emitcode ("movx", "a,@%s", r->name);
2560 emitcode ("mov", "psw,a");
2564 emitcode ("pop", "psw");
2568 if (mcs51_nRegs > 8)
2570 if (options.useXstack)
2572 emitcode ("dec", "%s", r->name);
2573 emitcode ("movx", "a,@%s", r->name);
2574 emitcode ("mov", "bits,a");
2578 emitcode ("pop", "bits");
2582 for (i = 7; i >= 0; i--)
2584 if (options.useXstack)
2586 emitcode ("dec", "%s", r->name);
2587 emitcode ("movx", "a,@%s", r->name);
2588 emitcode ("mov", "(%s+%d),a",
2589 regs8051[i].base, 8 * bank + regs8051[i].offset);
2593 emitcode ("pop", "(%s+%d)",
2594 regs8051[i].base, 8 * bank + regs8051[i].offset);
2598 if (options.useXstack)
2600 emitcode ("mov", "%s,%s", spname, r->name);
2605 freeAsmop (NULL, aop, ic, TRUE);
2609 /*-----------------------------------------------------------------*/
2610 /* genSend - gen code for SEND */
2611 /*-----------------------------------------------------------------*/
2612 static void genSend(set *sendSet)
2617 /* first we do all bit parameters */
2618 for (sic = setFirstItem (sendSet); sic;
2619 sic = setNextItem (sendSet))
2621 if (sic->argreg > 12)
2623 int bit = sic->argreg-13;
2625 aopOp (IC_LEFT (sic), sic, FALSE);
2627 /* if left is a literal then
2628 we know what the value is */
2629 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2631 if (((int) operandLitValue (IC_LEFT (sic))))
2632 emitcode ("setb", "b[%d]", bit);
2634 emitcode ("clr", "b[%d]", bit);
2636 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2638 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2639 if (strcmp (l, "c"))
2640 emitcode ("mov", "c,%s", l);
2641 emitcode ("mov", "b[%d],c", bit);
2646 toBoolean (IC_LEFT (sic));
2647 /* set C, if a >= 1 */
2648 emitcode ("add", "a,#0xff");
2649 emitcode ("mov", "b[%d],c", bit);
2654 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2660 saveRegisters (setFirstItem (sendSet));
2661 emitcode ("mov", "bits,b");
2664 /* then we do all other parameters */
2665 for (sic = setFirstItem (sendSet); sic;
2666 sic = setNextItem (sendSet))
2668 if (sic->argreg <= 12)
2670 int size, offset = 0;
2671 aopOp (IC_LEFT (sic), sic, FALSE);
2672 size = AOP_SIZE (IC_LEFT (sic));
2674 if (sic->argreg == 1)
2678 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2679 if (strcmp (l, fReturn[offset]))
2680 emitcode ("mov", "%s,%s", fReturn[offset], l);
2688 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2689 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2693 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2698 /*-----------------------------------------------------------------*/
2699 /* selectRegBank - emit code to select the register bank */
2700 /*-----------------------------------------------------------------*/
2702 selectRegBank (short bank, bool keepFlags)
2704 /* if f.e. result is in carry */
2707 emitcode ("anl", "psw,#0xE7");
2709 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2713 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2717 /*-----------------------------------------------------------------*/
2718 /* genCall - generates a call statement */
2719 /*-----------------------------------------------------------------*/
2721 genCall (iCode * ic)
2725 // bool restoreBank = FALSE;
2726 bool swapBanks = FALSE;
2727 bool accuse = FALSE;
2728 bool accPushed = FALSE;
2729 bool resultInF0 = FALSE;
2730 bool assignResultGenerated = FALSE;
2732 D(emitcode("; genCall",""));
2734 dtype = operandType (IC_LEFT (ic));
2735 etype = getSpec(dtype);
2736 /* if send set is not empty then assign */
2739 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2740 genSend(reverseSet(_G.sendSet));
2742 genSend(_G.sendSet);
2748 /* if we are calling a not _naked function that is not using
2749 the same register bank then we need to save the
2750 destination registers on the stack */
2751 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2752 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2753 !IFFUNC_ISISR (dtype))
2758 /* if caller saves & we have not saved then */
2764 emitcode ("mov", "psw,#0x%02x",
2765 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2769 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2771 if (IFFUNC_CALLEESAVES(dtype))
2773 werror (E_BANKED_WITH_CALLEESAVES);
2777 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2778 OP_SYMBOL (IC_LEFT (ic))->rname :
2779 OP_SYMBOL (IC_LEFT (ic))->name);
2781 emitcode ("mov", "r0,#%s", l);
2782 emitcode ("mov", "r1,#(%s >> 8)", l);
2783 emitcode ("mov", "r2,#(%s >> 16)", l);
2784 emitcode ("lcall", "__sdcc_banked_call");
2789 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2790 OP_SYMBOL (IC_LEFT (ic))->rname :
2791 OP_SYMBOL (IC_LEFT (ic))->name));
2796 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2799 /* if we need assign a result value */
2800 if ((IS_ITEMP (IC_RESULT (ic)) &&
2801 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2802 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2803 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2804 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2805 IS_TRUE_SYMOP (IC_RESULT (ic)))
2809 aopOp (IC_RESULT (ic), ic, FALSE);
2812 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2813 assignResultGenerated = TRUE;
2815 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2818 /* adjust the stack for parameters if required */
2822 if (ic->parmBytes > 3)
2826 emitcode ("push", "acc");
2829 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2830 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2831 !assignResultGenerated)
2833 emitcode ("mov", "F0,c");
2837 emitcode ("mov", "a,%s", spname);
2838 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2839 emitcode ("mov", "%s,a", spname);
2841 /* unsaveRegisters from xstack needs acc, but */
2842 /* unsaveRegisters from stack needs this popped */
2843 if (accPushed && !options.useXstack)
2845 emitcode ("pop", "acc");
2850 for (i = 0; i < ic->parmBytes; i++)
2851 emitcode ("dec", "%s", spname);
2854 /* if we had saved some registers then unsave them */
2855 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2857 if (accuse && !accPushed && options.useXstack)
2859 /* xstack needs acc, but doesn't touch normal stack */
2860 emitcode ("push", "acc");
2863 unsaveRegisters (ic);
2866 // /* if register bank was saved then pop them */
2868 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2870 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2873 emitcode ("mov", "c,F0");
2875 aopOp (IC_RESULT (ic), ic, FALSE);
2876 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2877 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2881 emitcode ("pop", "acc");
2884 /*-----------------------------------------------------------------*/
2885 /* -10l - generates a call by pointer statement */
2886 /*-----------------------------------------------------------------*/
2888 genPcall (iCode * ic)
2892 symbol *rlbl = newiTempLabel (NULL);
2893 // bool restoreBank=FALSE;
2894 bool swapBanks = FALSE;
2895 bool resultInF0 = FALSE;
2897 D(emitcode("; genPCall",""));
2899 dtype = operandType (IC_LEFT (ic))->next;
2900 etype = getSpec(dtype);
2901 /* if caller saves & we have not saved then */
2905 /* if we are calling a not _naked function that is not using
2906 the same register bank then we need to save the
2907 destination registers on the stack */
2908 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2909 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2910 !IFFUNC_ISISR (dtype))
2912 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2913 // restoreBank=TRUE;
2915 // need caution message to user here
2918 if (IS_LITERAL(etype))
2920 /* if send set is not empty then assign */
2923 genSend(reverseSet(_G.sendSet));
2929 emitcode ("mov", "psw,#0x%02x",
2930 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2933 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2935 if (IFFUNC_CALLEESAVES(dtype))
2937 werror (E_BANKED_WITH_CALLEESAVES);
2941 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2943 emitcode ("mov", "r0,#%s", l);
2944 emitcode ("mov", "r1,#(%s >> 8)", l);
2945 emitcode ("mov", "r2,#(%s >> 16)", l);
2946 emitcode ("lcall", "__sdcc_banked_call");
2951 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2956 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2958 if (IFFUNC_CALLEESAVES(dtype))
2960 werror (E_BANKED_WITH_CALLEESAVES);
2964 aopOp (IC_LEFT (ic), ic, FALSE);
2968 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2969 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2970 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2974 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2975 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2976 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2977 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2980 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2982 /* if send set is not empty then assign */
2985 genSend(reverseSet(_G.sendSet));
2991 emitcode ("mov", "psw,#0x%02x",
2992 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2996 emitcode ("lcall", "__sdcc_banked_call");
3001 /* push the return address on to the stack */
3002 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
3003 emitcode ("push", "acc");
3004 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
3005 emitcode ("push", "acc");
3007 /* now push the calling address */
3008 aopOp (IC_LEFT (ic), ic, FALSE);
3010 pushSide (IC_LEFT (ic), FPTRSIZE);
3012 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3014 /* if send set is not empty the assign */
3017 genSend(reverseSet(_G.sendSet));
3023 emitcode ("mov", "psw,#0x%02x",
3024 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3028 emitcode ("ret", "");
3029 emitcode ("", "%05d$:", (rlbl->key + 100));
3034 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3037 /* if we need assign a result value */
3038 if ((IS_ITEMP (IC_RESULT (ic)) &&
3039 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3040 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3041 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3042 IS_TRUE_SYMOP (IC_RESULT (ic)))
3046 aopOp (IC_RESULT (ic), ic, FALSE);
3049 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3051 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3054 /* adjust the stack for parameters if required */
3058 if (ic->parmBytes > 3)
3060 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3061 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3063 emitcode ("mov", "F0,c");
3067 emitcode ("mov", "a,%s", spname);
3068 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3069 emitcode ("mov", "%s,a", spname);
3072 for (i = 0; i < ic->parmBytes; i++)
3073 emitcode ("dec", "%s", spname);
3077 // /* if register bank was saved then unsave them */
3079 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3081 /* if we had saved some registers then unsave them */
3082 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3083 unsaveRegisters (ic);
3085 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3088 emitcode ("mov", "c,F0");
3090 aopOp (IC_RESULT (ic), ic, FALSE);
3091 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3092 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3096 /*-----------------------------------------------------------------*/
3097 /* resultRemat - result is rematerializable */
3098 /*-----------------------------------------------------------------*/
3100 resultRemat (iCode * ic)
3102 if (SKIP_IC (ic) || ic->op == IFX)
3105 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3107 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3108 if (sym->remat && !POINTER_SET (ic))
3115 #if defined(__BORLANDC__) || defined(_MSC_VER)
3116 #define STRCASECMP stricmp
3118 #define STRCASECMP strcasecmp
3121 /*-----------------------------------------------------------------*/
3122 /* inExcludeList - return 1 if the string is in exclude Reg list */
3123 /*-----------------------------------------------------------------*/
3125 regsCmp(void *p1, void *p2)
3127 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3131 inExcludeList (char *s)
3133 const char *p = setFirstItem(options.excludeRegsSet);
3135 if (p == NULL || STRCASECMP(p, "none") == 0)
3139 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3142 /*-----------------------------------------------------------------*/
3143 /* genFunction - generated code for function entry */
3144 /*-----------------------------------------------------------------*/
3146 genFunction (iCode * ic)
3148 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3150 bool switchedPSW = FALSE;
3151 int calleesaves_saved_register = -1;
3152 int stackAdjust = sym->stack;
3153 int accIsFree = sym->recvSize < 4;
3154 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3155 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3158 /* create the function header */
3159 emitcode (";", "-----------------------------------------");
3160 emitcode (";", " function %s", sym->name);
3161 emitcode (";", "-----------------------------------------");
3163 emitcode ("", "%s:", sym->rname);
3164 ftype = operandType (IC_LEFT (ic));
3165 _G.currentFunc = sym;
3167 if (IFFUNC_ISNAKED(ftype))
3169 emitcode(";", "naked function: no prologue.");
3173 /* here we need to generate the equates for the
3174 register bank if required */
3175 if (FUNC_REGBANK (ftype) != rbank)
3179 rbank = FUNC_REGBANK (ftype);
3180 for (i = 0; i < mcs51_nRegs; i++)
3182 if (regs8051[i].type != REG_BIT)
3184 if (strcmp (regs8051[i].base, "0") == 0)
3185 emitcode ("", "%s = 0x%02x",
3187 8 * rbank + regs8051[i].offset);
3189 emitcode ("", "%s = %s + 0x%02x",
3192 8 * rbank + regs8051[i].offset);
3197 /* if this is an interrupt service routine then
3198 save acc, b, dpl, dph */
3199 if (IFFUNC_ISISR (sym->type))
3202 if (!inExcludeList ("acc"))
3203 emitcode ("push", "acc");
3204 if (!inExcludeList ("b"))
3205 emitcode ("push", "b");
3206 if (!inExcludeList ("dpl"))
3207 emitcode ("push", "dpl");
3208 if (!inExcludeList ("dph"))
3209 emitcode ("push", "dph");
3210 /* if this isr has no bank i.e. is going to
3211 run with bank 0 , then we need to save more
3213 if (!FUNC_REGBANK (sym->type))
3216 /* if this function does not call any other
3217 function then we can be economical and
3218 save only those registers that are used */
3219 if (!IFFUNC_HASFCALL(sym->type))
3223 /* if any registers used */
3226 bool bits_pushed = FALSE;
3227 /* save the registers used */
3228 for (i = 0; i < sym->regsUsed->size; i++)
3230 if (bitVectBitValue (sym->regsUsed, i))
3231 bits_pushed = pushReg (i, bits_pushed);
3238 /* this function has a function call. We cannot
3239 determines register usage so we will have to push the
3241 saveRBank (0, ic, FALSE);
3242 if (options.parms_in_bank1) {
3244 for (i=0; i < 8 ; i++ ) {
3245 emitcode ("push","%s",rb1regs[i]);
3252 /* This ISR uses a non-zero bank.
3254 * We assume that the bank is available for our
3257 * However, if this ISR calls a function which uses some
3258 * other bank, we must save that bank entirely.
3260 unsigned long banksToSave = 0;
3262 if (IFFUNC_HASFCALL(sym->type))
3265 #define MAX_REGISTER_BANKS 4
3270 for (i = ic; i; i = i->next)
3272 if (i->op == ENDFUNCTION)
3274 /* we got to the end OK. */
3282 dtype = operandType (IC_LEFT(i));
3284 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3286 /* Mark this bank for saving. */
3287 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3289 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3293 banksToSave |= (1 << FUNC_REGBANK(dtype));
3296 /* And note that we don't need to do it in
3304 /* This is a mess; we have no idea what
3305 * register bank the called function might
3308 * The only thing I can think of to do is
3309 * throw a warning and hope.
3311 werror(W_FUNCPTR_IN_USING_ISR);
3315 if (banksToSave && options.useXstack)
3317 /* Since we aren't passing it an ic,
3318 * saveRBank will assume r0 is available to abuse.
3320 * So switch to our (trashable) bank now, so
3321 * the caller's R0 isn't trashed.
3323 emitcode ("push", "psw");
3324 emitcode ("mov", "psw,#0x%02x",
3325 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3329 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3331 if (banksToSave & (1 << ix))
3333 saveRBank(ix, NULL, FALSE);
3337 // TODO: this needs a closer look
3338 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3341 /* Set the register bank to the desired value if nothing else */
3342 /* has done so yet. */
3345 emitcode ("push", "psw");
3346 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3351 /* This is a non-ISR function. The caller has already switched register */
3352 /* banks, if necessary, so just handle the callee-saves option. */
3354 /* if callee-save to be used for this function
3355 then save the registers being used in this function */
3356 if (IFFUNC_CALLEESAVES(sym->type))
3360 /* if any registers used */
3363 bool bits_pushed = FALSE;
3364 /* save the registers used */
3365 for (i = 0; i < sym->regsUsed->size; i++)
3367 if (bitVectBitValue (sym->regsUsed, i))
3369 /* remember one saved register for later usage */
3370 if (calleesaves_saved_register < 0)
3371 calleesaves_saved_register = i;
3372 bits_pushed = pushReg (i, bits_pushed);
3383 if (options.useXstack)
3385 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3387 emitcode ("mov", "r0,%s", spname);
3388 emitcode ("inc", "%s", spname);
3389 emitcode ("xch", "a,_bpx");
3390 emitcode ("movx", "@r0,a");
3391 emitcode ("inc", "r0");
3392 emitcode ("mov", "a,r0");
3393 emitcode ("xch", "a,_bpx");
3397 emitcode ("push", "_bp"); /* save the callers stack */
3398 emitcode ("mov", "_bp,sp");
3403 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3405 /* set up the stack */
3406 emitcode ("push", "_bp"); /* save the callers stack */
3407 emitcode ("mov", "_bp,sp");
3412 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3413 /* before setting up the stack frame completely. */
3414 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3416 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3420 if (rsym && rsym->regType == REG_CND)
3422 if (rsym && (rsym->accuse || rsym->ruonly))
3424 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3425 rsym = rsym->usl.spillLoc;
3428 /* If the RECEIVE operand immediately spills to the first entry on the */
3429 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3430 /* rather than the usual @r0/r1 machinations. */
3431 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3435 _G.current_iCode = ric;
3436 D(emitcode ("; genReceive",""));
3437 for (ofs=0; ofs < sym->recvSize; ofs++)
3439 if (!strcmp (fReturn[ofs], "a"))
3440 emitcode ("push", "acc");
3442 emitcode ("push", fReturn[ofs]);
3444 stackAdjust -= sym->recvSize;
3447 assert (stackAdjust>=0);
3450 _G.current_iCode = ic;
3454 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3455 /* to free up the accumulator. */
3456 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3460 _G.current_iCode = ric;
3461 D(emitcode ("; genReceive",""));
3462 for (ofs=0; ofs < sym->recvSize; ofs++)
3464 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3466 _G.current_iCode = ic;
3472 /* adjust the stack for the function */
3475 int i = stackAdjust;
3477 werror (W_STACK_OVERFLOW, sym->name);
3479 if (i > 3 && accIsFree)
3481 emitcode ("mov", "a,sp");
3482 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3483 emitcode ("mov", "sp,a");
3487 /* The accumulator is not free, so we will need another register */
3488 /* to clobber. No need to worry about a possible conflict with */
3489 /* the above early RECEIVE optimizations since they would have */
3490 /* freed the accumulator if they were generated. */
3492 if (IFFUNC_CALLEESAVES(sym->type))
3494 /* if it's a callee-saves function we need a saved register */
3495 if (calleesaves_saved_register >= 0)
3497 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3498 emitcode ("mov", "a,sp");
3499 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3500 emitcode ("mov", "sp,a");
3501 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3504 /* do it the hard way */
3506 emitcode ("inc", "sp");
3510 /* not callee-saves, we can clobber r0 */
3511 emitcode ("mov", "r0,a");
3512 emitcode ("mov", "a,sp");
3513 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3514 emitcode ("mov", "sp,a");
3515 emitcode ("mov", "a,r0");
3520 emitcode ("inc", "sp");
3525 char i = ((char) sym->xstack & 0xff);
3527 if (i > 3 && accIsFree)
3529 emitcode ("mov", "a,_spx");
3530 emitcode ("add", "a,#0x%02x", i);
3531 emitcode ("mov", "_spx,a");
3535 emitcode ("push", "acc");
3536 emitcode ("mov", "a,_spx");
3537 emitcode ("add", "a,#0x%02x", i);
3538 emitcode ("mov", "_spx,a");
3539 emitcode ("pop", "acc");
3544 emitcode ("inc", "_spx");
3548 /* if critical function then turn interrupts off */
3549 if (IFFUNC_ISCRITICAL (ftype))
3551 symbol *tlbl = newiTempLabel (NULL);
3552 emitcode ("setb", "c");
3553 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3554 emitcode ("clr", "c");
3555 emitcode ("", "%05d$:", (tlbl->key + 100));
3556 emitcode ("push", "psw"); /* save old ea via c in psw */
3560 /*-----------------------------------------------------------------*/
3561 /* genEndFunction - generates epilogue for functions */
3562 /*-----------------------------------------------------------------*/
3564 genEndFunction (iCode * ic)
3566 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3567 lineNode *lnp = lineCurr;
3569 bitVect *regsUsedPrologue;
3570 bitVect *regsUnneeded;
3573 _G.currentFunc = NULL;
3574 if (IFFUNC_ISNAKED(sym->type))
3576 emitcode(";", "naked function: no epilogue.");
3577 if (options.debug && currFunc)
3578 debugFile->writeEndFunction (currFunc, ic, 0);
3582 if (IFFUNC_ISCRITICAL (sym->type))
3584 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3586 emitcode ("rlc", "a"); /* save c in a */
3587 emitcode ("pop", "psw"); /* restore ea via c in psw */
3588 emitcode ("mov", "ea,c");
3589 emitcode ("rrc", "a"); /* restore c from a */
3593 emitcode ("pop", "psw"); /* restore ea via c in psw */
3594 emitcode ("mov", "ea,c");
3598 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3600 if (options.useXstack)
3604 emitcode ("mov", "sp,_bp");
3605 emitcode ("pop", "_bp");
3607 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3609 emitcode ("xch", "a,_bpx");
3610 emitcode ("mov", "r0,a");
3611 emitcode ("dec", "r0");
3612 emitcode ("movx", "a,@r0");
3613 emitcode ("xch", "a,_bpx");
3614 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3617 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3619 emitcode ("mov", "sp,_bp");
3620 emitcode ("pop", "_bp");
3624 /* restore the register bank */
3625 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3627 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3628 || !options.useXstack)
3630 /* Special case of ISR using non-zero bank with useXstack
3633 emitcode ("pop", "psw");
3637 if (IFFUNC_ISISR (sym->type))
3640 /* now we need to restore the registers */
3641 /* if this isr has no bank i.e. is going to
3642 run with bank 0 , then we need to save more
3644 if (!FUNC_REGBANK (sym->type))
3646 /* if this function does not call any other
3647 function then we can be economical and
3648 save only those registers that are used */
3649 if (!IFFUNC_HASFCALL(sym->type))
3653 /* if any registers used */
3656 bool bits_popped = FALSE;
3657 /* save the registers used */
3658 for (i = sym->regsUsed->size; i >= 0; i--)
3660 if (bitVectBitValue (sym->regsUsed, i))
3661 bits_popped = popReg (i, bits_popped);
3667 if (options.parms_in_bank1) {
3669 for (i = 7 ; i >= 0 ; i-- ) {
3670 emitcode ("pop","%s",rb1regs[i]);
3673 /* this function has a function call cannot
3674 determines register usage so we will have to pop the
3676 unsaveRBank (0, ic, FALSE);
3681 /* This ISR uses a non-zero bank.
3683 * Restore any register banks saved by genFunction
3686 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3689 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3691 if (savedBanks & (1 << ix))
3693 unsaveRBank(ix, NULL, FALSE);
3697 if (options.useXstack)
3699 /* Restore bank AFTER calling unsaveRBank,
3700 * since it can trash r0.
3702 emitcode ("pop", "psw");
3706 if (!inExcludeList ("dph"))
3707 emitcode ("pop", "dph");
3708 if (!inExcludeList ("dpl"))
3709 emitcode ("pop", "dpl");
3710 if (!inExcludeList ("b"))
3711 emitcode ("pop", "b");
3712 if (!inExcludeList ("acc"))
3713 emitcode ("pop", "acc");
3715 /* if debug then send end of function */
3716 if (options.debug && currFunc)
3718 debugFile->writeEndFunction (currFunc, ic, 1);
3721 emitcode ("reti", "");
3725 if (IFFUNC_CALLEESAVES(sym->type))
3729 /* if any registers used */
3732 /* save the registers used */
3733 for (i = sym->regsUsed->size; i >= 0; i--)
3735 if (bitVectBitValue (sym->regsUsed, i) ||
3736 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3737 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3740 else if (mcs51_ptrRegReq)
3742 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3743 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3748 /* if debug then send end of function */
3749 if (options.debug && currFunc)
3751 debugFile->writeEndFunction (currFunc, ic, 1);
3754 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3756 emitcode ("ljmp", "__sdcc_banked_ret");
3760 emitcode ("ret", "");
3764 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3767 /* If this was an interrupt handler using bank 0 that called another */
3768 /* function, then all registers must be saved; nothing to optimized. */
3769 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3770 && !FUNC_REGBANK(sym->type))
3773 /* There are no push/pops to optimize if not callee-saves or ISR */
3774 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3777 /* If there were stack parameters, we cannot optimize without also */
3778 /* fixing all of the stack offsets; this is too dificult to consider. */
3779 if (FUNC_HASSTACKPARM(sym->type))
3782 /* Compute the registers actually used */
3783 regsUsed = newBitVect (mcs51_nRegs);
3784 regsUsedPrologue = newBitVect (mcs51_nRegs);
3787 if (lnp->ic && lnp->ic->op == FUNCTION)
3788 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3790 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3792 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3793 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3800 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3801 && !bitVectBitValue (regsUsed, CND_IDX))
3803 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3804 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3805 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3806 bitVectUnSetBit (regsUsed, CND_IDX);
3809 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3811 /* If this was an interrupt handler that called another function */
3812 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3813 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3815 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3816 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3817 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3818 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3819 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3822 /* Remove the unneeded push/pops */
3823 regsUnneeded = newBitVect (mcs51_nRegs);
3826 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3828 if (!strncmp(lnp->line, "push", 4))
3830 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3831 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3833 connectLine (lnp->prev, lnp->next);
3834 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3837 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3839 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3840 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3842 connectLine (lnp->prev, lnp->next);
3843 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3850 for (idx = 0; idx < regsUnneeded->size; idx++)
3851 if (bitVectBitValue (regsUnneeded, idx))
3852 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3854 freeBitVect (regsUnneeded);
3855 freeBitVect (regsUsed);
3856 freeBitVect (regsUsedPrologue);
3859 /*-----------------------------------------------------------------*/
3860 /* genRet - generate code for return statement */
3861 /*-----------------------------------------------------------------*/
3865 int size, offset = 0, pushed = 0;
3867 D(emitcode ("; genRet",""));
3869 /* if we have no return value then
3870 just generate the "ret" */
3874 /* we have something to return then
3875 move the return value into place */
3876 aopOp (IC_LEFT (ic), ic, FALSE);
3877 size = AOP_SIZE (IC_LEFT (ic));
3880 if (IS_BIT(_G.currentFunc->etype))
3882 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3889 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3892 l = aopGet (IC_LEFT (ic), offset++,
3894 emitcode ("push", "%s", l);
3899 l = aopGet (IC_LEFT (ic), offset,
3901 if (strcmp (fReturn[offset], l))
3902 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3909 if (strcmp (fReturn[pushed], "a"))
3910 emitcode ("pop", fReturn[pushed]);
3912 emitcode ("pop", "acc");
3914 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3917 /* generate a jump to the return label
3918 if the next is not the return statement */
3919 if (!(ic->next && ic->next->op == LABEL &&
3920 IC_LABEL (ic->next) == returnLabel))
3922 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3926 /*-----------------------------------------------------------------*/
3927 /* genLabel - generates a label */
3928 /*-----------------------------------------------------------------*/
3930 genLabel (iCode * ic)
3932 /* special case never generate */
3933 if (IC_LABEL (ic) == entryLabel)
3936 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3939 /*-----------------------------------------------------------------*/
3940 /* genGoto - generates a ljmp */
3941 /*-----------------------------------------------------------------*/
3943 genGoto (iCode * ic)
3945 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3948 /*-----------------------------------------------------------------*/
3949 /* findLabelBackwards: walks back through the iCode chain looking */
3950 /* for the given label. Returns number of iCode instructions */
3951 /* between that label and given ic. */
3952 /* Returns zero if label not found. */
3953 /*-----------------------------------------------------------------*/
3955 findLabelBackwards (iCode * ic, int key)
3964 /* If we have any pushes or pops, we cannot predict the distance.
3965 I don't like this at all, this should be dealt with in the
3967 if (ic->op == IPUSH || ic->op == IPOP) {
3971 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3980 /*-----------------------------------------------------------------*/
3981 /* genPlusIncr :- does addition with increment if possible */
3982 /*-----------------------------------------------------------------*/
3984 genPlusIncr (iCode * ic)
3986 unsigned int icount;
3987 unsigned int size = getDataSize (IC_RESULT (ic));
3989 /* will try to generate an increment */
3990 /* if the right side is not a literal
3992 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3995 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3997 D(emitcode ("; genPlusIncr",""));
3999 /* if increment >=16 bits in register or direct space */
4000 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
4001 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4002 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4010 /* If the next instruction is a goto and the goto target
4011 * is < 10 instructions previous to this, we can generate
4012 * jumps straight to that target.
4014 if (ic->next && ic->next->op == GOTO
4015 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4016 && labelRange <= 10)
4018 emitcode (";", "tail increment optimized");
4019 tlbl = IC_LABEL (ic->next);
4024 tlbl = newiTempLabel (NULL);
4027 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4028 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4029 IS_AOP_PREG (IC_RESULT (ic)))
4030 emitcode ("cjne", "%s,#0x00,%05d$",
4031 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4035 emitcode ("clr", "a");
4036 emitcode ("cjne", "a,%s,%05d$",
4037 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4041 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4044 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4045 IS_AOP_PREG (IC_RESULT (ic)))
4046 emitcode ("cjne", "%s,#0x00,%05d$",
4047 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4050 emitcode ("cjne", "a,%s,%05d$",
4051 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4054 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4058 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4059 IS_AOP_PREG (IC_RESULT (ic)))
4060 emitcode ("cjne", "%s,#0x00,%05d$",
4061 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4065 emitcode ("cjne", "a,%s,%05d$",
4066 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4069 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4074 emitcode ("", "%05d$:", tlbl->key + 100);
4079 /* if result is dptr */
4080 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4081 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4082 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4083 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4085 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4091 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4094 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
4095 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
4097 emitcode ("inc", "dptr");
4102 /* if the literal value of the right hand side
4103 is greater than 4 then it is not worth it */
4107 /* if the sizes are greater than 1 then we cannot */
4108 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4109 AOP_SIZE (IC_LEFT (ic)) > 1)
4112 /* we can if the aops of the left & result match or
4113 if they are in registers and the registers are the
4115 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4120 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4121 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4122 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4128 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4137 /*-----------------------------------------------------------------*/
4138 /* outBitAcc - output a bit in acc */
4139 /*-----------------------------------------------------------------*/
4141 outBitAcc (operand * result)
4143 symbol *tlbl = newiTempLabel (NULL);
4144 /* if the result is a bit */
4145 if (AOP_TYPE (result) == AOP_CRY)
4147 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4151 emitcode ("jz", "%05d$", tlbl->key + 100);
4152 emitcode ("mov", "a,%s", one);
4153 emitcode ("", "%05d$:", tlbl->key + 100);
4158 /*-----------------------------------------------------------------*/
4159 /* genPlusBits - generates code for addition of two bits */
4160 /*-----------------------------------------------------------------*/
4162 genPlusBits (iCode * ic)
4164 D(emitcode ("; genPlusBits",""));
4166 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4168 symbol *lbl = newiTempLabel (NULL);
4169 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4170 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4171 emitcode ("cpl", "c");
4172 emitcode ("", "%05d$:", (lbl->key + 100));
4173 outBitC (IC_RESULT (ic));
4177 emitcode ("clr", "a");
4178 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4179 emitcode ("rlc", "a");
4180 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4181 emitcode ("addc", "a,#0x00");
4182 outAcc (IC_RESULT (ic));
4187 /* This is the original version of this code.
4189 * This is being kept around for reference,
4190 * because I am not entirely sure I got it right...
4193 adjustArithmeticResult (iCode * ic)
4195 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4196 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4197 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4198 aopPut (IC_RESULT (ic),
4199 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4201 isOperandVolatile (IC_RESULT (ic), FALSE));
4203 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4204 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4205 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4206 aopPut (IC_RESULT (ic),
4207 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4209 isOperandVolatile (IC_RESULT (ic), FALSE));
4211 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4212 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4213 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4214 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4215 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4218 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4219 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4223 /* This is the pure and virtuous version of this code.
4224 * I'm pretty certain it's right, but not enough to toss the old
4228 adjustArithmeticResult (iCode * ic)
4230 if (opIsGptr (IC_RESULT (ic)) &&
4231 opIsGptr (IC_LEFT (ic)) &&
4232 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4234 aopPut (IC_RESULT (ic),
4235 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4237 isOperandVolatile (IC_RESULT (ic), FALSE));
4240 if (opIsGptr (IC_RESULT (ic)) &&
4241 opIsGptr (IC_RIGHT (ic)) &&
4242 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4244 aopPut (IC_RESULT (ic),
4245 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4247 isOperandVolatile (IC_RESULT (ic), FALSE));
4250 if (opIsGptr (IC_RESULT (ic)) &&
4251 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4252 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4253 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4254 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4257 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4258 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4263 /*-----------------------------------------------------------------*/
4264 /* genPlus - generates code for addition */
4265 /*-----------------------------------------------------------------*/
4267 genPlus (iCode * ic)
4269 int size, offset = 0;
4272 bool swappedLR = FALSE;
4273 operand *leftOp, *rightOp;
4276 /* special cases :- */
4278 D(emitcode ("; genPlus",""));
4280 aopOp (IC_LEFT (ic), ic, FALSE);
4281 aopOp (IC_RIGHT (ic), ic, FALSE);
4282 aopOp (IC_RESULT (ic), ic, TRUE);
4284 /* if literal, literal on the right or
4285 if left requires ACC or right is already
4287 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4288 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4289 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4291 operand *t = IC_RIGHT (ic);
4292 IC_RIGHT (ic) = IC_LEFT (ic);
4297 /* if both left & right are in bit
4299 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4300 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4306 /* if left in bit space & right literal */
4307 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4308 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4310 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4311 /* if result in bit space */
4312 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4314 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4315 emitcode ("cpl", "c");
4316 outBitC (IC_RESULT (ic));
4320 size = getDataSize (IC_RESULT (ic));
4323 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4324 emitcode ("addc", "a,#00");
4325 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4331 /* if I can do an increment instead
4332 of add then GOOD for ME */
4333 if (genPlusIncr (ic) == TRUE)
4336 size = getDataSize (IC_RESULT (ic));
4337 leftOp = IC_LEFT(ic);
4338 rightOp = IC_RIGHT(ic);
4341 /* if this is an add for an array access
4342 at a 256 byte boundary */
4344 && AOP_TYPE (op) == AOP_IMMD
4346 && IS_SPEC (OP_SYM_ETYPE (op))
4347 && SPEC_ABSA (OP_SYM_ETYPE (op))
4348 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4351 D(emitcode ("; genPlus aligned array",""));
4352 aopPut (IC_RESULT (ic),
4353 aopGet (rightOp, 0, FALSE, FALSE),
4355 isOperandVolatile (IC_RESULT (ic), FALSE));
4357 if( 1 == getDataSize (IC_RIGHT (ic)) )
4359 aopPut (IC_RESULT (ic),
4360 aopGet (leftOp, 1, FALSE, FALSE),
4362 isOperandVolatile (IC_RESULT (ic), FALSE));
4366 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4367 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4368 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4373 /* if the lower bytes of a literal are zero skip the addition */
4374 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4376 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4377 (skip_bytes+1 < size))
4382 D(emitcode ("; genPlus shortcut",""));
4387 if( offset >= skip_bytes )
4389 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4392 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4394 emitcode("xch", "a,b");
4395 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4396 emitcode (add, "a,b");
4399 else if (aopGetUsesAcc (leftOp, offset))
4401 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4402 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4406 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4407 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4409 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4410 add = "addc"; /* further adds must propagate carry */
4414 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4415 isOperandVolatile (IC_RESULT (ic), FALSE))
4418 aopPut (IC_RESULT (ic),
4419 aopGet (leftOp, offset, FALSE, FALSE),
4421 isOperandVolatile (IC_RESULT (ic), FALSE));
4427 adjustArithmeticResult (ic);
4430 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4433 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4434 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4438 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4439 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4443 /*-----------------------------------------------------------------*/
4444 /* genMinusDec :- does subtraction with decrement if possible */
4445 /*-----------------------------------------------------------------*/
4447 genMinusDec (iCode * ic)
4449 unsigned int icount;
4450 unsigned int size = getDataSize (IC_RESULT (ic));
4452 /* will try to generate an increment */
4453 /* if the right side is not a literal
4455 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4458 /* if the literal value of the right hand side
4459 is greater than 4 then it is not worth it */
4460 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4463 D(emitcode ("; genMinusDec",""));
4465 /* if decrement >=16 bits in register or direct space */
4466 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4467 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4475 /* If the next instruction is a goto and the goto target
4476 * is <= 10 instructions previous to this, we can generate
4477 * jumps straight to that target.
4479 if (ic->next && ic->next->op == GOTO
4480 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4481 && labelRange <= 10)
4483 emitcode (";", "tail decrement optimized");
4484 tlbl = IC_LABEL (ic->next);
4489 tlbl = newiTempLabel (NULL);
4493 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4494 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4495 IS_AOP_PREG (IC_RESULT (ic)))
4496 emitcode ("cjne", "%s,#0xff,%05d$"
4497 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4501 emitcode ("mov", "a,#0xff");
4502 emitcode ("cjne", "a,%s,%05d$"
4503 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4506 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4509 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4510 IS_AOP_PREG (IC_RESULT (ic)))
4511 emitcode ("cjne", "%s,#0xff,%05d$"
4512 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4516 emitcode ("cjne", "a,%s,%05d$"
4517 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4520 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4524 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4525 IS_AOP_PREG (IC_RESULT (ic)))
4526 emitcode ("cjne", "%s,#0xff,%05d$"
4527 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4531 emitcode ("cjne", "a,%s,%05d$"
4532 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4535 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4539 emitcode ("", "%05d$:", tlbl->key + 100);
4544 /* if the sizes are greater than 1 then we cannot */
4545 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4546 AOP_SIZE (IC_LEFT (ic)) > 1)
4549 /* we can if the aops of the left & result match or
4550 if they are in registers and the registers are the
4552 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4556 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4558 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4563 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4567 emitcode ("dec", "%s", l);
4569 if (AOP_NEEDSACC (IC_RESULT (ic)))
4570 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4578 /*-----------------------------------------------------------------*/
4579 /* addSign - complete with sign */
4580 /*-----------------------------------------------------------------*/
4582 addSign (operand * result, int offset, int sign)
4584 int size = (getDataSize (result) - offset);
4589 emitcode ("rlc", "a");
4590 emitcode ("subb", "a,acc");
4592 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4596 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4600 /*-----------------------------------------------------------------*/
4601 /* genMinusBits - generates code for subtraction of two bits */
4602 /*-----------------------------------------------------------------*/
4604 genMinusBits (iCode * ic)
4606 symbol *lbl = newiTempLabel (NULL);
4608 D(emitcode ("; genMinusBits",""));
4610 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4612 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4613 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4614 emitcode ("cpl", "c");
4615 emitcode ("", "%05d$:", (lbl->key + 100));
4616 outBitC (IC_RESULT (ic));
4620 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4621 emitcode ("subb", "a,acc");
4622 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4623 emitcode ("inc", "a");
4624 emitcode ("", "%05d$:", (lbl->key + 100));
4625 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4626 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4630 /*-----------------------------------------------------------------*/
4631 /* genMinus - generates code for subtraction */
4632 /*-----------------------------------------------------------------*/
4634 genMinus (iCode * ic)
4636 int size, offset = 0;
4638 D(emitcode ("; genMinus",""));
4640 aopOp (IC_LEFT (ic), ic, FALSE);
4641 aopOp (IC_RIGHT (ic), ic, FALSE);
4642 aopOp (IC_RESULT (ic), ic, TRUE);
4644 /* special cases :- */
4645 /* if both left & right are in bit space */
4646 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4647 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4653 /* if I can do an decrement instead
4654 of subtract then GOOD for ME */
4655 if (genMinusDec (ic) == TRUE)
4658 size = getDataSize (IC_RESULT (ic));
4660 /* if literal, add a,#-lit, else normal subb */
4661 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4663 unsigned long lit = 0L;
4664 bool useCarry = FALSE;
4666 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4671 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4673 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4674 if (!offset && !size && lit== (unsigned long) -1)
4676 emitcode ("dec", "a");
4680 /* first add without previous c */
4681 emitcode ("add", "a,#0x%02x",
4682 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4687 emitcode ("addc", "a,#0x%02x",
4688 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4690 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4694 /* no need to add zeroes */
4695 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4697 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4698 offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4706 operand *leftOp, *rightOp;
4708 leftOp = IC_LEFT(ic);
4709 rightOp = IC_RIGHT(ic);
4713 if (aopGetUsesAcc(rightOp, offset)) {
4714 if (aopGetUsesAcc(leftOp, offset)) {
4717 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4719 emitcode ("mov", "b,a");
4722 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4723 emitcode ("subb", "a,b");
4726 /* reverse subtraction with 2's complement */
4728 emitcode( "setb", "c");
4730 emitcode( "cpl", "c");
4731 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4732 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4733 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4734 emitcode("cpl", "a");
4735 if (size) /* skip if last byte */
4736 emitcode( "cpl", "c");
4739 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4742 emitcode ("subb", "a,%s",
4743 aopGet(rightOp, offset, FALSE, TRUE));
4746 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4751 adjustArithmeticResult (ic);
4754 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4755 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4756 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4760 /*-----------------------------------------------------------------*/
4761 /* genMultbits :- multiplication of bits */
4762 /*-----------------------------------------------------------------*/
4764 genMultbits (operand * left,
4768 D(emitcode ("; genMultbits",""));
4770 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4771 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4775 /*-----------------------------------------------------------------*/
4776 /* genMultOneByte : 8*8=8/16 bit multiplication */
4777 /*-----------------------------------------------------------------*/
4779 genMultOneByte (operand * left,
4784 int size = AOP_SIZE (result);
4785 bool runtimeSign, compiletimeSign;
4786 bool lUnsigned, rUnsigned, pushedB;
4788 D(emitcode ("; genMultOneByte",""));
4790 if (size < 1 || size > 2)
4792 /* this should never happen */
4793 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4794 AOP_SIZE(result), __FILE__, lineno);
4798 /* (if two literals: the value is computed before) */
4799 /* if one literal, literal on the right */
4800 if (AOP_TYPE (left) == AOP_LIT)
4805 /* emitcode (";", "swapped left and right"); */
4807 /* if no literal, unsigned on the right: shorter code */
4808 if ( AOP_TYPE (right) != AOP_LIT
4809 && SPEC_USIGN (getSpec (operandType (left))))
4816 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4817 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4821 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4822 no need to take care about the signedness! */
4823 || (lUnsigned && rUnsigned))
4825 /* just an unsigned 8 * 8 = 8 multiply
4827 /* emitcode (";","unsigned"); */
4828 /* TODO: check for accumulator clash between left & right aops? */
4830 if (AOP_TYPE (right) == AOP_LIT)
4832 /* moving to accumulator first helps peepholes */
4833 MOVA (aopGet (left, 0, FALSE, FALSE));
4834 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4838 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4839 MOVA (aopGet (left, 0, FALSE, FALSE));
4842 emitcode ("mul", "ab");
4843 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4845 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4851 /* we have to do a signed multiply */
4852 /* emitcode (";", "signed"); */
4854 /* now sign adjust for both left & right */
4856 /* let's see what's needed: */
4857 /* apply negative sign during runtime */
4858 runtimeSign = FALSE;
4859 /* negative sign from literals */
4860 compiletimeSign = FALSE;
4864 if (AOP_TYPE(left) == AOP_LIT)
4866 /* signed literal */
4867 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4869 compiletimeSign = TRUE;
4872 /* signed but not literal */
4878 if (AOP_TYPE(right) == AOP_LIT)
4880 /* signed literal */
4881 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4883 compiletimeSign ^= TRUE;
4886 /* signed but not literal */
4890 /* initialize F0, which stores the runtime sign */
4893 if (compiletimeSign)
4894 emitcode ("setb", "F0"); /* set sign flag */
4896 emitcode ("clr", "F0"); /* reset sign flag */
4899 /* save the signs of the operands */
4900 if (AOP_TYPE(right) == AOP_LIT)
4902 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4904 if (!rUnsigned && val < 0)
4905 emitcode ("mov", "b,#0x%02x", -val);
4907 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4909 else /* ! literal */
4911 if (rUnsigned) /* emitcode (";", "signed"); */
4913 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4916 MOVA (aopGet (right, 0, FALSE, FALSE));
4917 lbl = newiTempLabel (NULL);
4918 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4919 emitcode ("cpl", "F0"); /* complement sign flag */
4920 emitcode ("cpl", "a"); /* 2's complement */
4921 emitcode ("inc", "a");
4922 emitcode ("", "%05d$:", (lbl->key + 100));
4923 emitcode ("mov", "b,a");
4927 if (AOP_TYPE(left) == AOP_LIT)
4929 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4931 if (!lUnsigned && val < 0)
4932 emitcode ("mov", "a,#0x%02x", -val);
4934 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4936 else /* ! literal */
4938 MOVA (aopGet (left, 0, FALSE, FALSE));
4942 lbl = newiTempLabel (NULL);
4943 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4944 emitcode ("cpl", "F0"); /* complement sign flag */
4945 emitcode ("cpl", "a"); /* 2's complement */
4946 emitcode ("inc", "a");
4947 emitcode ("", "%05d$:", (lbl->key + 100));
4951 /* now the multiplication */
4952 emitcode ("mul", "ab");
4953 if (runtimeSign || compiletimeSign)
4955 lbl = newiTempLabel (NULL);
4957 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4958 emitcode ("cpl", "a"); /* lsb 2's complement */
4960 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4963 emitcode ("add", "a,#1"); /* this sets carry flag */
4964 emitcode ("xch", "a,b");
4965 emitcode ("cpl", "a"); /* msb 2's complement */
4966 emitcode ("addc", "a,#0");
4967 emitcode ("xch", "a,b");
4969 emitcode ("", "%05d$:", (lbl->key + 100));
4971 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4973 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4978 /*-----------------------------------------------------------------*/
4979 /* genMult - generates code for multiplication */
4980 /*-----------------------------------------------------------------*/
4982 genMult (iCode * ic)
4984 operand *left = IC_LEFT (ic);
4985 operand *right = IC_RIGHT (ic);
4986 operand *result = IC_RESULT (ic);
4988 D(emitcode ("; genMult",""));
4990 /* assign the asmops */
4991 aopOp (left, ic, FALSE);
4992 aopOp (right, ic, FALSE);
4993 aopOp (result, ic, TRUE);
4995 /* special cases first */
4997 if (AOP_TYPE (left) == AOP_CRY &&
4998 AOP_TYPE (right) == AOP_CRY)
5000 genMultbits (left, right, result);
5004 /* if both are of size == 1 */
5005 #if 0 // one of them can be a sloc shared with the result
5006 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5008 if (getSize(operandType(left)) == 1 &&
5009 getSize(operandType(right)) == 1)
5012 genMultOneByte (left, right, result);
5016 /* should have been converted to function call */
5017 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5018 getSize(OP_SYMBOL(right)->type));
5022 freeAsmop (result, NULL, ic, TRUE);
5023 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5024 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5027 /*-----------------------------------------------------------------*/
5028 /* genDivbits :- division of bits */
5029 /*-----------------------------------------------------------------*/
5031 genDivbits (operand * left,
5038 D(emitcode ("; genDivbits",""));
5042 /* the result must be bit */
5043 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5044 l = aopGet (left, 0, FALSE, FALSE);
5048 emitcode ("div", "ab");
5049 emitcode ("rrc", "a");
5053 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5056 /*-----------------------------------------------------------------*/
5057 /* genDivOneByte : 8 bit division */
5058 /*-----------------------------------------------------------------*/
5060 genDivOneByte (operand * left,
5064 bool lUnsigned, rUnsigned, pushedB;
5065 bool runtimeSign, compiletimeSign;
5066 bool accuse = FALSE;
5067 bool pushedA = FALSE;
5071 D(emitcode ("; genDivOneByte",""));
5073 /* Why is it necessary that genDivOneByte() can return an int result?
5076 volatile unsigned char uc;
5077 volatile signed char sc1, sc2;
5090 In all cases a one byte result would overflow, the following cast to int
5091 would return the wrong result.
5093 Two possible solution:
5094 a) cast operands to int, if ((unsigned) / (signed)) or
5095 ((signed) / (signed))
5096 b) return an 16 bit signed int; this is what we're doing here!
5099 size = AOP_SIZE (result) - 1;
5101 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5102 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5106 /* signed or unsigned */
5107 if (lUnsigned && rUnsigned)
5109 /* unsigned is easy */
5110 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5111 MOVA (aopGet (left, 0, FALSE, FALSE));
5112 emitcode ("div", "ab");
5113 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5115 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5121 /* signed is a little bit more difficult */
5123 /* now sign adjust for both left & right */
5125 /* let's see what's needed: */
5126 /* apply negative sign during runtime */
5127 runtimeSign = FALSE;
5128 /* negative sign from literals */
5129 compiletimeSign = FALSE;
5133 if (AOP_TYPE(left) == AOP_LIT)
5135 /* signed literal */
5136 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5138 compiletimeSign = TRUE;
5141 /* signed but not literal */
5147 if (AOP_TYPE(right) == AOP_LIT)
5149 /* signed literal */
5150 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5152 compiletimeSign ^= TRUE;
5155 /* signed but not literal */
5159 /* initialize F0, which stores the runtime sign */
5162 if (compiletimeSign)
5163 emitcode ("setb", "F0"); /* set sign flag */
5165 emitcode ("clr", "F0"); /* reset sign flag */
5168 /* save the signs of the operands */
5169 if (AOP_TYPE(right) == AOP_LIT)
5171 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5173 if (!rUnsigned && val < 0)
5174 emitcode ("mov", "b,#0x%02x", -val);
5176 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5178 else /* ! literal */
5181 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5184 MOVA (aopGet (right, 0, FALSE, FALSE));
5185 lbl = newiTempLabel (NULL);
5186 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5187 emitcode ("cpl", "F0"); /* complement sign flag */
5188 emitcode ("cpl", "a"); /* 2's complement */
5189 emitcode ("inc", "a");
5190 emitcode ("", "%05d$:", (lbl->key + 100));
5191 emitcode ("mov", "b,a");
5195 if (AOP_TYPE(left) == AOP_LIT)
5197 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5199 if (!lUnsigned && val < 0)
5200 emitcode ("mov", "a,#0x%02x", -val);
5202 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5204 else /* ! literal */
5206 MOVA (aopGet (left, 0, FALSE, FALSE));
5210 lbl = newiTempLabel (NULL);
5211 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5212 emitcode ("cpl", "F0"); /* complement sign flag */
5213 emitcode ("cpl", "a"); /* 2's complement */
5214 emitcode ("inc", "a");
5215 emitcode ("", "%05d$:", (lbl->key + 100));
5219 /* now the division */
5220 emitcode ("div", "ab");
5222 if (runtimeSign || compiletimeSign)
5224 lbl = newiTempLabel (NULL);
5226 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5227 emitcode ("cpl", "a"); /* lsb 2's complement */
5228 emitcode ("inc", "a");
5229 emitcode ("", "%05d$:", (lbl->key + 100));
5231 accuse = aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5234 /* msb is 0x00 or 0xff depending on the sign */
5239 emitcode ("push", "acc");
5242 emitcode ("mov", "c,F0");
5243 emitcode ("subb", "a,acc");
5245 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5247 else /* compiletimeSign */
5249 if (aopPutUsesAcc (result, "#0xFF", offset))
5251 emitcode ("push", "acc");
5255 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5261 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5263 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5267 emitcode ("pop", "acc");
5271 /*-----------------------------------------------------------------*/
5272 /* genDiv - generates code for division */
5273 /*-----------------------------------------------------------------*/
5277 operand *left = IC_LEFT (ic);
5278 operand *right = IC_RIGHT (ic);
5279 operand *result = IC_RESULT (ic);
5281 D(emitcode ("; genDiv",""));
5283 /* assign the amsops */
5284 aopOp (left, ic, FALSE);
5285 aopOp (right, ic, FALSE);
5286 aopOp (result, ic, TRUE);
5288 /* special cases first */
5290 if (AOP_TYPE (left) == AOP_CRY &&
5291 AOP_TYPE (right) == AOP_CRY)
5293 genDivbits (left, right, result);
5297 /* if both are of size == 1 */
5298 if (AOP_SIZE (left) == 1 &&
5299 AOP_SIZE (right) == 1)
5301 genDivOneByte (left, right, result);
5305 /* should have been converted to function call */
5308 freeAsmop (result, NULL, ic, TRUE);
5309 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5310 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5313 /*-----------------------------------------------------------------*/
5314 /* genModbits :- modulus of bits */
5315 /*-----------------------------------------------------------------*/
5317 genModbits (operand * left,
5324 D(emitcode ("; genModbits",""));
5328 /* the result must be bit */
5329 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5330 l = aopGet (left, 0, FALSE, FALSE);
5334 emitcode ("div", "ab");
5335 emitcode ("mov", "a,b");
5336 emitcode ("rrc", "a");
5340 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5343 /*-----------------------------------------------------------------*/
5344 /* genModOneByte : 8 bit modulus */
5345 /*-----------------------------------------------------------------*/
5347 genModOneByte (operand * left,
5351 bool lUnsigned, rUnsigned, pushedB;
5352 bool runtimeSign, compiletimeSign;
5356 D(emitcode ("; genModOneByte",""));
5358 size = AOP_SIZE (result) - 1;
5360 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5361 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5363 /* if right is a literal, check it for 2^n */
5364 if (AOP_TYPE(right) == AOP_LIT)
5366 unsigned char val = abs((int) operandLitValue(right));
5367 symbol *lbl2 = NULL;
5371 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5380 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5381 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5382 /* because iCode should have been changed to genAnd */
5383 /* see file "SDCCopt.c", function "convertToFcall()" */
5385 MOVA (aopGet (left, 0, FALSE, FALSE));
5386 emitcode ("mov", "c,acc.7");
5387 emitcode ("anl", "a,#0x%02x", val - 1);
5388 lbl = newiTempLabel (NULL);
5389 emitcode ("jz", "%05d$", (lbl->key + 100));
5390 emitcode ("jnc", "%05d$", (lbl->key + 100));
5391 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5397 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5399 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5400 lbl2 = newiTempLabel (NULL);
5401 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5403 emitcode ("", "%05d$:", (lbl->key + 100));
5404 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5406 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5409 emitcode ("", "%05d$:", (lbl2->key + 100));
5420 /* signed or unsigned */
5421 if (lUnsigned && rUnsigned)
5423 /* unsigned is easy */
5424 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5425 MOVA (aopGet (left, 0, FALSE, FALSE));
5426 emitcode ("div", "ab");
5427 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5429 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5435 /* signed is a little bit more difficult */
5437 /* now sign adjust for both left & right */
5439 /* modulus: sign of the right operand has no influence on the result! */
5440 if (AOP_TYPE(right) == AOP_LIT)
5442 signed char val = (char) operandLitValue(right);
5444 if (!rUnsigned && val < 0)
5445 emitcode ("mov", "b,#0x%02x", -val);
5447 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5449 else /* not literal */
5452 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5455 MOVA (aopGet (right, 0, FALSE, FALSE));
5456 lbl = newiTempLabel (NULL);
5457 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5458 emitcode ("cpl", "a"); /* 2's complement */
5459 emitcode ("inc", "a");
5460 emitcode ("", "%05d$:", (lbl->key + 100));
5461 emitcode ("mov", "b,a");
5465 /* let's see what's needed: */
5466 /* apply negative sign during runtime */
5467 runtimeSign = FALSE;
5468 /* negative sign from literals */
5469 compiletimeSign = FALSE;
5471 /* sign adjust left side */
5472 if (AOP_TYPE(left) == AOP_LIT)
5474 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5476 if (!lUnsigned && val < 0)
5478 compiletimeSign = TRUE; /* set sign flag */
5479 emitcode ("mov", "a,#0x%02x", -val);
5482 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5484 else /* ! literal */
5486 MOVA (aopGet (left, 0, FALSE, FALSE));
5491 emitcode ("clr", "F0"); /* clear sign flag */
5493 lbl = newiTempLabel (NULL);
5494 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5495 emitcode ("setb", "F0"); /* set sign flag */
5496 emitcode ("cpl", "a"); /* 2's complement */
5497 emitcode ("inc", "a");
5498 emitcode ("", "%05d$:", (lbl->key + 100));
5502 /* now the modulus */
5503 emitcode ("div", "ab");
5505 if (runtimeSign || compiletimeSign)
5507 emitcode ("mov", "a,b");
5508 lbl = newiTempLabel (NULL);
5510 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5511 emitcode ("cpl", "a"); /* 2's complement */
5512 emitcode ("inc", "a");
5513 emitcode ("", "%05d$:", (lbl->key + 100));
5515 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5518 /* msb is 0x00 or 0xff depending on the sign */
5521 emitcode ("mov", "c,F0");
5522 emitcode ("subb", "a,acc");
5524 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5526 else /* compiletimeSign */
5528 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5533 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5535 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5541 /*-----------------------------------------------------------------*/
5542 /* genMod - generates code for division */
5543 /*-----------------------------------------------------------------*/
5547 operand *left = IC_LEFT (ic);
5548 operand *right = IC_RIGHT (ic);
5549 operand *result = IC_RESULT (ic);
5551 D(emitcode ("; genMod",""));
5553 /* assign the asmops */
5554 aopOp (left, ic, FALSE);
5555 aopOp (right, ic, FALSE);
5556 aopOp (result, ic, TRUE);
5558 /* special cases first */
5560 if (AOP_TYPE (left) == AOP_CRY &&
5561 AOP_TYPE (right) == AOP_CRY)
5563 genModbits (left, right, result);
5567 /* if both are of size == 1 */
5568 if (AOP_SIZE (left) == 1 &&
5569 AOP_SIZE (right) == 1)
5571 genModOneByte (left, right, result);
5575 /* should have been converted to function call */
5579 freeAsmop (result, NULL, ic, TRUE);
5580 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5581 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5584 /*-----------------------------------------------------------------*/
5585 /* genIfxJump :- will create a jump depending on the ifx */
5586 /*-----------------------------------------------------------------*/
5588 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5591 symbol *tlbl = newiTempLabel (NULL);
5594 D(emitcode ("; genIfxJump",""));
5596 /* if true label then we jump if condition
5600 jlbl = IC_TRUE (ic);
5601 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5602 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5606 /* false label is present */
5607 jlbl = IC_FALSE (ic);
5608 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5609 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5611 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5612 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5614 emitcode (inst, "%05d$", tlbl->key + 100);
5615 freeForBranchAsmop (result);
5616 freeForBranchAsmop (right);
5617 freeForBranchAsmop (left);
5618 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5619 emitcode ("", "%05d$:", tlbl->key + 100);
5621 /* mark the icode as generated */
5625 /*-----------------------------------------------------------------*/
5626 /* genCmp :- greater or less than comparison */
5627 /*-----------------------------------------------------------------*/
5629 genCmp (operand * left, operand * right,
5630 operand * result, iCode * ifx, int sign, iCode *ic)
5632 int size, offset = 0;
5633 unsigned long lit = 0L;
5636 D(emitcode ("; genCmp",""));
5638 /* if left & right are bit variables */
5639 if (AOP_TYPE (left) == AOP_CRY &&
5640 AOP_TYPE (right) == AOP_CRY)
5642 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5643 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5647 /* subtract right from left if at the
5648 end the carry flag is set then we know that
5649 left is greater than right */
5650 size = max (AOP_SIZE (left), AOP_SIZE (right));
5652 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5653 if ((size == 1) && !sign &&
5654 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5656 symbol *lbl = newiTempLabel (NULL);
5657 emitcode ("cjne", "%s,%s,%05d$",
5658 aopGet (left, offset, FALSE, FALSE),
5659 aopGet (right, offset, FALSE, FALSE),
5661 emitcode ("", "%05d$:", lbl->key + 100);
5665 if (AOP_TYPE (right) == AOP_LIT)
5667 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5668 /* optimize if(x < 0) or if(x >= 0) */
5677 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5678 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5680 genIfxJump (ifx, "acc.7", left, right, result);
5681 freeAsmop (right, NULL, ic, TRUE);
5682 freeAsmop (left, NULL, ic, TRUE);
5687 emitcode ("rlc", "a");
5695 bool pushedB = FALSE;
5696 rightInB = aopGetUsesAcc(right, offset);
5700 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5702 MOVA (aopGet (left, offset, FALSE, FALSE));
5703 if (sign && size == 0)
5705 emitcode ("xrl", "a,#0x80");
5706 if (AOP_TYPE (right) == AOP_LIT)
5708 unsigned long lit = (unsigned long)
5709 floatFromVal (AOP (right)->aopu.aop_lit);
5710 emitcode ("subb", "a,#0x%02x",
5711 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5719 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5721 emitcode ("xrl", "b,#0x80");
5722 emitcode ("subb", "a,b");
5728 emitcode ("subb", "a,b");
5730 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5740 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5741 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5742 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5748 /* if the result is used in the next
5749 ifx conditional branch then generate
5750 code a little differently */
5752 genIfxJump (ifx, "c", NULL, NULL, result);
5755 /* leave the result in acc */
5759 /*-----------------------------------------------------------------*/
5760 /* genCmpGt :- greater than comparison */
5761 /*-----------------------------------------------------------------*/
5763 genCmpGt (iCode * ic, iCode * ifx)
5765 operand *left, *right, *result;
5766 sym_link *letype, *retype;
5769 D(emitcode ("; genCmpGt",""));
5771 left = IC_LEFT (ic);
5772 right = IC_RIGHT (ic);
5773 result = IC_RESULT (ic);
5775 letype = getSpec (operandType (left));
5776 retype = getSpec (operandType (right));
5777 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5778 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5779 /* assign the amsops */
5780 aopOp (result, ic, TRUE);
5781 aopOp (left, ic, FALSE);
5782 aopOp (right, ic, FALSE);
5784 genCmp (right, left, result, ifx, sign, ic);
5786 freeAsmop (result, NULL, ic, TRUE);
5789 /*-----------------------------------------------------------------*/
5790 /* genCmpLt - less than comparisons */
5791 /*-----------------------------------------------------------------*/
5793 genCmpLt (iCode * ic, iCode * ifx)
5795 operand *left, *right, *result;
5796 sym_link *letype, *retype;
5799 D(emitcode ("; genCmpLt",""));
5801 left = IC_LEFT (ic);
5802 right = IC_RIGHT (ic);
5803 result = IC_RESULT (ic);
5805 letype = getSpec (operandType (left));
5806 retype = getSpec (operandType (right));
5807 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5808 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5809 /* assign the amsops */
5810 aopOp (result, ic, TRUE);
5811 aopOp (left, ic, FALSE);
5812 aopOp (right, ic, FALSE);
5814 genCmp (left, right, result, ifx, sign, ic);
5816 freeAsmop (result, NULL, ic, TRUE);
5819 /*-----------------------------------------------------------------*/
5820 /* gencjneshort - compare and jump if not equal */
5821 /*-----------------------------------------------------------------*/
5823 gencjneshort (operand * left, operand * right, symbol * lbl)
5825 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5827 unsigned long lit = 0L;
5829 /* if the left side is a literal or
5830 if the right is in a pointer register and left
5832 if ((AOP_TYPE (left) == AOP_LIT) ||
5833 (AOP_TYPE (left) == AOP_IMMD) ||
5834 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5841 if (AOP_TYPE (right) == AOP_LIT)
5842 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5844 /* if the right side is a literal then anything goes */
5845 if (AOP_TYPE (right) == AOP_LIT &&
5846 AOP_TYPE (left) != AOP_DIR &&
5847 AOP_TYPE (left) != AOP_IMMD)
5851 emitcode ("cjne", "%s,%s,%05d$",
5852 aopGet (left, offset, FALSE, FALSE),
5853 aopGet (right, offset, FALSE, FALSE),
5859 /* if the right side is in a register or in direct space or
5860 if the left is a pointer register & right is not */
5861 else if (AOP_TYPE (right) == AOP_REG ||
5862 AOP_TYPE (right) == AOP_DIR ||
5863 AOP_TYPE (right) == AOP_LIT ||
5864 AOP_TYPE (right) == AOP_IMMD ||
5865 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5866 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5870 MOVA (aopGet (left, offset, FALSE, FALSE));
5871 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5872 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5873 emitcode ("jnz", "%05d$", lbl->key + 100);
5875 emitcode ("cjne", "a,%s,%05d$",
5876 aopGet (right, offset, FALSE, TRUE),
5883 /* right is a pointer reg need both a & b */
5887 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5888 wassertl(!BINUSE, "B was in use");
5889 l = aopGet (left, offset, FALSE, FALSE);
5890 if (strcmp (l, "b"))
5891 emitcode ("mov", "b,%s", l);
5892 MOVA (aopGet (right, offset, FALSE, FALSE));
5893 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5899 /*-----------------------------------------------------------------*/
5900 /* gencjne - compare and jump if not equal */
5901 /*-----------------------------------------------------------------*/
5903 gencjne (operand * left, operand * right, symbol * lbl)
5905 symbol *tlbl = newiTempLabel (NULL);
5907 gencjneshort (left, right, lbl);
5909 emitcode ("mov", "a,%s", one);
5910 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5911 emitcode ("", "%05d$:", lbl->key + 100);
5912 emitcode ("clr", "a");
5913 emitcode ("", "%05d$:", tlbl->key + 100);
5916 /*-----------------------------------------------------------------*/
5917 /* genCmpEq - generates code for equal to */
5918 /*-----------------------------------------------------------------*/
5920 genCmpEq (iCode * ic, iCode * ifx)
5922 bool swappedLR = FALSE;
5923 operand *left, *right, *result;
5925 D(emitcode ("; genCmpEq",""));
5927 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5928 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5929 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5931 /* if literal, literal on the right or
5932 if the right is in a pointer register and left
5934 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5935 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5937 operand *t = IC_RIGHT (ic);
5938 IC_RIGHT (ic) = IC_LEFT (ic);
5943 if (ifx && !AOP_SIZE (result))
5946 /* if they are both bit variables */
5947 if (AOP_TYPE (left) == AOP_CRY &&
5948 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5950 if (AOP_TYPE (right) == AOP_LIT)
5952 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5955 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5956 emitcode ("cpl", "c");
5960 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5964 emitcode ("clr", "c");
5966 /* AOP_TYPE(right) == AOP_CRY */
5970 symbol *lbl = newiTempLabel (NULL);
5971 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5972 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5973 emitcode ("cpl", "c");
5974 emitcode ("", "%05d$:", (lbl->key + 100));
5976 /* if true label then we jump if condition
5978 tlbl = newiTempLabel (NULL);
5981 emitcode ("jnc", "%05d$", tlbl->key + 100);
5982 freeForBranchAsmop (result);
5983 freeForBranchAsmop (right);
5984 freeForBranchAsmop (left);
5985 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5989 emitcode ("jc", "%05d$", tlbl->key + 100);
5990 freeForBranchAsmop (result);
5991 freeForBranchAsmop (right);
5992 freeForBranchAsmop (left);
5993 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5995 emitcode ("", "%05d$:", tlbl->key + 100);
5999 tlbl = newiTempLabel (NULL);
6000 gencjneshort (left, right, tlbl);
6003 freeForBranchAsmop (result);
6004 freeForBranchAsmop (right);
6005 freeForBranchAsmop (left);
6006 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
6007 emitcode ("", "%05d$:", tlbl->key + 100);
6011 symbol *lbl = newiTempLabel (NULL);
6012 emitcode ("sjmp", "%05d$", lbl->key + 100);
6013 emitcode ("", "%05d$:", tlbl->key + 100);
6014 freeForBranchAsmop (result);
6015 freeForBranchAsmop (right);
6016 freeForBranchAsmop (left);
6017 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6018 emitcode ("", "%05d$:", lbl->key + 100);
6021 /* mark the icode as generated */
6026 /* if they are both bit variables */
6027 if (AOP_TYPE (left) == AOP_CRY &&
6028 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6030 if (AOP_TYPE (right) == AOP_LIT)
6032 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6035 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6036 emitcode ("cpl", "c");
6040 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6044 emitcode ("clr", "c");
6046 /* AOP_TYPE(right) == AOP_CRY */
6050 symbol *lbl = newiTempLabel (NULL);
6051 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6052 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6053 emitcode ("cpl", "c");
6054 emitcode ("", "%05d$:", (lbl->key + 100));
6057 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6064 genIfxJump (ifx, "c", left, right, result);
6067 /* if the result is used in an arithmetic operation
6068 then put the result in place */
6073 gencjne (left, right, newiTempLabel (NULL));
6074 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6076 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6081 genIfxJump (ifx, "a", left, right, result);
6084 /* if the result is used in an arithmetic operation
6085 then put the result in place */
6086 if (AOP_TYPE (result) != AOP_CRY)
6088 /* leave the result in acc */
6092 freeAsmop (result, NULL, ic, TRUE);
6095 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6096 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6100 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6101 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6105 /*-----------------------------------------------------------------*/
6106 /* ifxForOp - returns the icode containing the ifx for operand */
6107 /*-----------------------------------------------------------------*/
6109 ifxForOp (operand * op, iCode * ic)
6111 /* if true symbol then needs to be assigned */
6112 if (IS_TRUE_SYMOP (op))
6115 /* if this has register type condition and
6116 the next instruction is ifx with the same operand
6117 and live to of the operand is upto the ifx only then */
6119 ic->next->op == IFX &&
6120 IC_COND (ic->next)->key == op->key &&
6121 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6127 /*-----------------------------------------------------------------*/
6128 /* hasInc - operand is incremented before any other use */
6129 /*-----------------------------------------------------------------*/
6131 hasInc (operand *op, iCode *ic,int osize)
6133 sym_link *type = operandType(op);
6134 sym_link *retype = getSpec (type);
6135 iCode *lic = ic->next;
6138 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6139 if (!IS_SYMOP(op)) return NULL;
6141 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6142 if (IS_AGGREGATE(type->next)) return NULL;
6143 if (osize != (isize = getSize(type->next))) return NULL;
6146 /* if operand of the form op = op + <sizeof *op> */
6147 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6148 isOperandEqual(IC_RESULT(lic),op) &&
6149 isOperandLiteral(IC_RIGHT(lic)) &&
6150 operandLitValue(IC_RIGHT(lic)) == isize) {
6153 /* if the operand used or deffed */
6154 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6157 /* if GOTO or IFX */
6158 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6164 /*-----------------------------------------------------------------*/
6165 /* genAndOp - for && operation */
6166 /*-----------------------------------------------------------------*/
6168 genAndOp (iCode * ic)
6170 operand *left, *right, *result;
6173 D(emitcode ("; genAndOp",""));
6175 /* note here that && operations that are in an
6176 if statement are taken away by backPatchLabels
6177 only those used in arthmetic operations remain */
6178 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6179 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6180 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6182 /* if both are bit variables */
6183 if (AOP_TYPE (left) == AOP_CRY &&
6184 AOP_TYPE (right) == AOP_CRY)
6186 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6187 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6192 tlbl = newiTempLabel (NULL);
6194 emitcode ("jz", "%05d$", tlbl->key + 100);
6196 emitcode ("", "%05d$:", tlbl->key + 100);
6200 freeAsmop (result, NULL, ic, TRUE);
6201 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6202 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6206 /*-----------------------------------------------------------------*/
6207 /* genOrOp - for || operation */
6208 /*-----------------------------------------------------------------*/
6210 genOrOp (iCode * ic)
6212 operand *left, *right, *result;
6215 D(emitcode ("; genOrOp",""));
6217 /* note here that || operations that are in an
6218 if statement are taken away by backPatchLabels
6219 only those used in arthmetic operations remain */
6220 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6221 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6222 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6224 /* if both are bit variables */
6225 if (AOP_TYPE (left) == AOP_CRY &&
6226 AOP_TYPE (right) == AOP_CRY)
6228 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6229 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6234 tlbl = newiTempLabel (NULL);
6236 emitcode ("jnz", "%05d$", tlbl->key + 100);
6238 emitcode ("", "%05d$:", tlbl->key + 100);
6242 freeAsmop (result, NULL, ic, TRUE);
6243 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6244 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6247 /*-----------------------------------------------------------------*/
6248 /* isLiteralBit - test if lit == 2^n */
6249 /*-----------------------------------------------------------------*/
6251 isLiteralBit (unsigned long lit)
6253 unsigned long pw[32] =
6254 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6255 0x100L, 0x200L, 0x400L, 0x800L,
6256 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6257 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6258 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6259 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6260 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6263 for (idx = 0; idx < 32; idx++)
6269 /*-----------------------------------------------------------------*/
6270 /* continueIfTrue - */
6271 /*-----------------------------------------------------------------*/
6273 continueIfTrue (iCode * ic)
6276 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6280 /*-----------------------------------------------------------------*/
6282 /*-----------------------------------------------------------------*/
6284 jumpIfTrue (iCode * ic)
6287 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6291 /*-----------------------------------------------------------------*/
6292 /* jmpTrueOrFalse - */
6293 /*-----------------------------------------------------------------*/
6295 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6297 // ugly but optimized by peephole
6300 symbol *nlbl = newiTempLabel (NULL);
6301 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6302 emitcode ("", "%05d$:", tlbl->key + 100);
6303 freeForBranchAsmop (result);
6304 freeForBranchAsmop (right);
6305 freeForBranchAsmop (left);
6306 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6307 emitcode ("", "%05d$:", nlbl->key + 100);
6311 freeForBranchAsmop (result);
6312 freeForBranchAsmop (right);
6313 freeForBranchAsmop (left);
6314 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6315 emitcode ("", "%05d$:", tlbl->key + 100);
6320 /*-----------------------------------------------------------------*/
6321 /* genAnd - code for and */
6322 /*-----------------------------------------------------------------*/
6324 genAnd (iCode * ic, iCode * ifx)
6326 operand *left, *right, *result;
6327 int size, offset = 0;
6328 unsigned long lit = 0L;
6332 D(emitcode ("; genAnd",""));
6334 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6335 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6336 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6339 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6341 AOP_TYPE (left), AOP_TYPE (right));
6342 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6344 AOP_SIZE (left), AOP_SIZE (right));
6347 /* if left is a literal & right is not then exchange them */
6348 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6349 AOP_NEEDSACC (left))
6351 operand *tmp = right;
6356 /* if result = right then exchange left and right */
6357 if (sameRegs (AOP (result), AOP (right)))
6359 operand *tmp = right;
6364 /* if right is bit then exchange them */
6365 if (AOP_TYPE (right) == AOP_CRY &&
6366 AOP_TYPE (left) != AOP_CRY)
6368 operand *tmp = right;
6372 if (AOP_TYPE (right) == AOP_LIT)
6373 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6375 size = AOP_SIZE (result);
6378 // result = bit & yy;
6379 if (AOP_TYPE (left) == AOP_CRY)
6381 // c = bit & literal;
6382 if (AOP_TYPE (right) == AOP_LIT)
6386 if (size && sameRegs (AOP (result), AOP (left)))
6389 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6394 if (size && (AOP_TYPE (result) == AOP_CRY))
6396 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6399 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6404 emitcode ("clr", "c");
6409 if (AOP_TYPE (right) == AOP_CRY)
6412 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6413 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6418 MOVA (aopGet (right, 0, FALSE, FALSE));
6420 emitcode ("rrc", "a");
6421 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6429 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6430 genIfxJump (ifx, "c", left, right, result);
6434 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6435 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6436 if ((AOP_TYPE (right) == AOP_LIT) &&
6437 (AOP_TYPE (result) == AOP_CRY) &&
6438 (AOP_TYPE (left) != AOP_CRY))
6440 int posbit = isLiteralBit (lit);
6445 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6449 switch (posbit & 0x07)
6451 case 0: emitcode ("rrc", "a");
6453 case 7: emitcode ("rlc", "a");
6455 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6464 SNPRINTF (buffer, sizeof(buffer),
6465 "acc.%d", posbit & 0x07);
6466 genIfxJump (ifx, buffer, left, right, result);
6469 {// what is this case? just found it in ds390/gen.c
6470 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6477 symbol *tlbl = newiTempLabel (NULL);
6478 int sizel = AOP_SIZE (left);
6480 emitcode ("setb", "c");
6483 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6485 MOVA (aopGet (left, offset, FALSE, FALSE));
6487 if ((posbit = isLiteralBit (bytelit)) != 0)
6488 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6491 if (bytelit != 0x0FFL)
6492 emitcode ("anl", "a,%s",
6493 aopGet (right, offset, FALSE, TRUE));
6494 emitcode ("jnz", "%05d$", tlbl->key + 100);
6499 // bit = left & literal
6502 emitcode ("clr", "c");
6503 emitcode ("", "%05d$:", tlbl->key + 100);
6505 // if(left & literal)
6509 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6511 emitcode ("", "%05d$:", tlbl->key + 100);
6519 /* if left is same as result */
6520 if (sameRegs (AOP (result), AOP (left)))
6522 for (; size--; offset++)
6524 if (AOP_TYPE (right) == AOP_LIT)
6526 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6527 if (bytelit == 0x0FF)
6529 /* dummy read of volatile operand */
6530 if (isOperandVolatile (left, FALSE))
6531 MOVA (aopGet (left, offset, FALSE, FALSE));
6535 else if (bytelit == 0)
6537 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6539 else if (IS_AOP_PREG (result))
6541 MOVA (aopGet (left, offset, FALSE, TRUE));
6542 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6543 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6546 emitcode ("anl", "%s,%s",
6547 aopGet (left, offset, FALSE, TRUE),
6548 aopGet (right, offset, FALSE, FALSE));
6552 if (AOP_TYPE (left) == AOP_ACC)
6555 emitcode("mov", "a,b");
6556 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6558 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6560 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6561 MOVA (aopGet (right, offset, FALSE, FALSE));
6562 emitcode ("anl", "a,b");
6563 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6565 else if (aopGetUsesAcc (left, offset))
6567 MOVA (aopGet (left, offset, FALSE, FALSE));
6568 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6569 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6573 MOVA (aopGet (right, offset, FALSE, FALSE));
6574 if (IS_AOP_PREG (result))
6576 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6577 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6580 emitcode ("anl", "%s,a",
6581 aopGet (left, offset, FALSE, TRUE));
6588 // left & result in different registers
6589 if (AOP_TYPE (result) == AOP_CRY)
6592 // if(size), result in bit
6593 // if(!size && ifx), conditional oper: if(left & right)
6594 symbol *tlbl = newiTempLabel (NULL);
6595 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6597 emitcode ("setb", "c");
6600 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6601 && AOP_TYPE(left)==AOP_ACC)
6604 emitcode("mov", "a,b");
6605 emitcode ("anl", "a,%s",
6606 aopGet (right, offset, FALSE, FALSE));
6608 if (AOP_TYPE(left)==AOP_ACC)
6612 bool pushedB = pushB ();
6613 emitcode("mov", "b,a");
6614 MOVA (aopGet (right, offset, FALSE, FALSE));
6615 emitcode("anl", "a,b");
6620 MOVA (aopGet (right, offset, FALSE, FALSE));
6621 emitcode("anl", "a,b");
6624 MOVA (aopGet (right, offset, FALSE, FALSE));
6625 emitcode ("anl", "a,%s",
6626 aopGet (left, offset, FALSE, FALSE));
6629 emitcode ("jnz", "%05d$", tlbl->key + 100);
6635 emitcode ("", "%05d$:", tlbl->key + 100);
6639 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6641 emitcode ("", "%05d$:", tlbl->key + 100);
6645 for (; (size--); offset++)
6648 // result = left & right
6649 if (AOP_TYPE (right) == AOP_LIT)
6651 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6652 if (bytelit == 0x0FF)
6655 aopGet (left, offset, FALSE, FALSE),
6657 isOperandVolatile (result, FALSE));
6660 else if (bytelit == 0)
6662 /* dummy read of volatile operand */
6663 if (isOperandVolatile (left, FALSE))
6664 MOVA (aopGet (left, offset, FALSE, FALSE));
6665 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6668 else if (AOP_TYPE (left) == AOP_ACC)
6672 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6673 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6678 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6679 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6684 // faster than result <- left, anl result,right
6685 // and better if result is SFR
6686 if (AOP_TYPE (left) == AOP_ACC)
6689 emitcode("mov", "a,b");
6690 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6692 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6694 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6695 MOVA (aopGet (right, offset, FALSE, FALSE));
6696 emitcode ("anl", "a,b");
6698 else if (aopGetUsesAcc (left, offset))
6700 MOVA (aopGet (left, offset, FALSE, FALSE));
6701 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6705 MOVA (aopGet (right, offset, FALSE, FALSE));
6706 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6708 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6714 freeAsmop (result, NULL, ic, TRUE);
6715 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6716 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6719 /*-----------------------------------------------------------------*/
6720 /* genOr - code for or */
6721 /*-----------------------------------------------------------------*/
6723 genOr (iCode * ic, iCode * ifx)
6725 operand *left, *right, *result;
6726 int size, offset = 0;
6727 unsigned long lit = 0L;
6730 D(emitcode ("; genOr",""));
6732 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6733 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6734 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6737 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6739 AOP_TYPE (left), AOP_TYPE (right));
6740 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6742 AOP_SIZE (left), AOP_SIZE (right));
6745 /* if left is a literal & right is not then exchange them */
6746 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6747 AOP_NEEDSACC (left))
6749 operand *tmp = right;
6754 /* if result = right then exchange them */
6755 if (sameRegs (AOP (result), AOP (right)))
6757 operand *tmp = right;
6762 /* if right is bit then exchange them */
6763 if (AOP_TYPE (right) == AOP_CRY &&
6764 AOP_TYPE (left) != AOP_CRY)
6766 operand *tmp = right;
6770 if (AOP_TYPE (right) == AOP_LIT)
6771 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6773 size = AOP_SIZE (result);
6777 if (AOP_TYPE (left) == AOP_CRY)
6779 if (AOP_TYPE (right) == AOP_LIT)
6781 // c = bit | literal;
6784 // lit != 0 => result = 1
6785 if (AOP_TYPE (result) == AOP_CRY)
6788 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6790 continueIfTrue (ifx);
6793 emitcode ("setb", "c");
6797 // lit == 0 => result = left
6798 if (size && sameRegs (AOP (result), AOP (left)))
6800 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6805 if (AOP_TYPE (right) == AOP_CRY)
6808 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6809 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6814 symbol *tlbl = newiTempLabel (NULL);
6815 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6816 emitcode ("setb", "c");
6817 emitcode ("jb", "%s,%05d$",
6818 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6820 emitcode ("jnz", "%05d$", tlbl->key + 100);
6821 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6823 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6829 emitcode ("", "%05d$:", tlbl->key + 100);
6838 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6839 genIfxJump (ifx, "c", left, right, result);
6843 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6844 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6845 if ((AOP_TYPE (right) == AOP_LIT) &&
6846 (AOP_TYPE (result) == AOP_CRY) &&
6847 (AOP_TYPE (left) != AOP_CRY))
6853 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6855 continueIfTrue (ifx);
6860 // lit = 0, result = boolean(left)
6862 emitcode ("setb", "c");
6866 symbol *tlbl = newiTempLabel (NULL);
6867 emitcode ("jnz", "%05d$", tlbl->key + 100);
6869 emitcode ("", "%05d$:", tlbl->key + 100);
6873 genIfxJump (ifx, "a", left, right, result);
6881 /* if left is same as result */
6882 if (sameRegs (AOP (result), AOP (left)))
6884 for (; size--; offset++)
6886 if (AOP_TYPE (right) == AOP_LIT)
6888 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6891 /* dummy read of volatile operand */
6892 if (isOperandVolatile (left, FALSE))
6893 MOVA (aopGet (left, offset, FALSE, FALSE));
6897 else if (bytelit == 0x0FF)
6899 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6901 else if (IS_AOP_PREG (left))
6903 MOVA (aopGet (left, offset, FALSE, TRUE));
6904 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6905 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6909 emitcode ("orl", "%s,%s",
6910 aopGet (left, offset, FALSE, TRUE),
6911 aopGet (right, offset, FALSE, FALSE));
6916 if (AOP_TYPE (left) == AOP_ACC)
6919 emitcode("mov", "a,b");
6920 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6922 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6924 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6925 MOVA (aopGet (right, offset, FALSE, FALSE));
6926 emitcode ("orl", "a,b");
6927 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6929 else if (aopGetUsesAcc (left, offset))
6931 MOVA (aopGet (left, offset, FALSE, FALSE));
6932 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6933 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6937 MOVA (aopGet (right, offset, FALSE, FALSE));
6938 if (IS_AOP_PREG (left))
6940 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6941 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6945 emitcode ("orl", "%s,a",
6946 aopGet (left, offset, FALSE, TRUE));
6954 // left & result in different registers
6955 if (AOP_TYPE (result) == AOP_CRY)
6958 // if(size), result in bit
6959 // if(!size && ifx), conditional oper: if(left | right)
6960 symbol *tlbl = newiTempLabel (NULL);
6961 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6963 emitcode ("setb", "c");
6966 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6968 emitcode("mov", "a,b");
6969 emitcode ("orl", "a,%s",
6970 aopGet (right, offset, FALSE, FALSE));
6972 MOVA (aopGet (right, offset, FALSE, FALSE));
6973 emitcode ("orl", "a,%s",
6974 aopGet (left, offset, FALSE, FALSE));
6976 emitcode ("jnz", "%05d$", tlbl->key + 100);
6982 emitcode ("", "%05d$:", tlbl->key + 100);
6986 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6988 emitcode ("", "%05d$:", tlbl->key + 100);
6992 for (; (size--); offset++)
6995 // result = left | right
6996 if (AOP_TYPE (right) == AOP_LIT)
6998 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7002 aopGet (left, offset, FALSE, FALSE),
7004 isOperandVolatile (result, FALSE));
7007 else if (bytelit == 0x0FF)
7009 /* dummy read of volatile operand */
7010 if (isOperandVolatile (left, FALSE))
7011 MOVA (aopGet (left, offset, FALSE, FALSE));
7012 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
7016 // faster than result <- left, anl result,right
7017 // and better if result is SFR
7018 if (AOP_TYPE (left) == AOP_ACC)
7021 emitcode("mov", "a,b");
7022 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7024 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7026 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7027 MOVA (aopGet (right, offset, FALSE, FALSE));
7028 emitcode ("orl", "a,b");
7030 else if (aopGetUsesAcc (left, offset))
7032 MOVA (aopGet (left, offset, FALSE, FALSE));
7033 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7037 MOVA (aopGet (right, offset, FALSE, FALSE));
7038 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7040 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7046 freeAsmop (result, NULL, ic, TRUE);
7047 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7048 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7051 /*-----------------------------------------------------------------*/
7052 /* genXor - code for xclusive or */
7053 /*-----------------------------------------------------------------*/
7055 genXor (iCode * ic, iCode * ifx)
7057 operand *left, *right, *result;
7058 int size, offset = 0;
7059 unsigned long lit = 0L;
7062 D(emitcode ("; genXor",""));
7064 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7065 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7066 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7069 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7071 AOP_TYPE (left), AOP_TYPE (right));
7072 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7074 AOP_SIZE (left), AOP_SIZE (right));
7077 /* if left is a literal & right is not ||
7078 if left needs acc & right does not */
7079 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7080 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7082 operand *tmp = right;
7087 /* if result = right then exchange them */
7088 if (sameRegs (AOP (result), AOP (right)))
7090 operand *tmp = right;
7095 /* if right is bit then exchange them */
7096 if (AOP_TYPE (right) == AOP_CRY &&
7097 AOP_TYPE (left) != AOP_CRY)
7099 operand *tmp = right;
7103 if (AOP_TYPE (right) == AOP_LIT)
7104 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7106 size = AOP_SIZE (result);
7110 if (AOP_TYPE (left) == AOP_CRY)
7112 if (AOP_TYPE (right) == AOP_LIT)
7114 // c = bit & literal;
7117 // lit>>1 != 0 => result = 1
7118 if (AOP_TYPE (result) == AOP_CRY)
7121 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7123 continueIfTrue (ifx);
7126 emitcode ("setb", "c");
7133 // lit == 0, result = left
7134 if (size && sameRegs (AOP (result), AOP (left)))
7136 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7140 // lit == 1, result = not(left)
7141 if (size && sameRegs (AOP (result), AOP (left)))
7143 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7148 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7149 emitcode ("cpl", "c");
7158 symbol *tlbl = newiTempLabel (NULL);
7159 if (AOP_TYPE (right) == AOP_CRY)
7162 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7166 int sizer = AOP_SIZE (right);
7168 // if val>>1 != 0, result = 1
7169 emitcode ("setb", "c");
7172 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7174 // test the msb of the lsb
7175 emitcode ("anl", "a,#0xfe");
7176 emitcode ("jnz", "%05d$", tlbl->key + 100);
7180 emitcode ("rrc", "a");
7182 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7183 emitcode ("cpl", "c");
7184 emitcode ("", "%05d$:", (tlbl->key + 100));
7191 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7192 genIfxJump (ifx, "c", left, right, result);
7196 /* if left is same as result */
7197 if (sameRegs (AOP (result), AOP (left)))
7199 for (; size--; offset++)
7201 if (AOP_TYPE (right) == AOP_LIT)
7203 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7206 /* dummy read of volatile operand */
7207 if (isOperandVolatile (left, FALSE))
7208 MOVA (aopGet (left, offset, FALSE, FALSE));
7212 else if (IS_AOP_PREG (left))
7214 MOVA (aopGet (left, offset, FALSE, TRUE));
7215 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7216 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7220 emitcode ("xrl", "%s,%s",
7221 aopGet (left, offset, FALSE, TRUE),
7222 aopGet (right, offset, FALSE, FALSE));
7227 if (AOP_TYPE (left) == AOP_ACC)
7230 emitcode("mov", "a,b");
7231 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7233 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7235 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7236 MOVA (aopGet (right, offset, FALSE, FALSE));
7237 emitcode ("xrl", "a,b");
7238 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7240 else if (aopGetUsesAcc (left, offset))
7242 MOVA (aopGet (left, offset, FALSE, FALSE));
7243 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7244 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7248 MOVA (aopGet (right, offset, FALSE, FALSE));
7249 if (IS_AOP_PREG (left))
7251 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7252 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7255 emitcode ("xrl", "%s,a",
7256 aopGet (left, offset, FALSE, TRUE));
7263 // left & result in different registers
7264 if (AOP_TYPE (result) == AOP_CRY)
7267 // if(size), result in bit
7268 // if(!size && ifx), conditional oper: if(left ^ right)
7269 symbol *tlbl = newiTempLabel (NULL);
7270 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7272 emitcode ("setb", "c");
7275 if ((AOP_TYPE (right) == AOP_LIT) &&
7276 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7278 MOVA (aopGet (left, offset, FALSE, FALSE));
7282 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7284 emitcode("mov", "a,b");
7285 emitcode ("xrl", "a,%s",
7286 aopGet (right, offset, FALSE, FALSE));
7288 MOVA (aopGet (right, offset, FALSE, FALSE));
7289 emitcode ("xrl", "a,%s",
7290 aopGet (left, offset, FALSE, FALSE));
7293 emitcode ("jnz", "%05d$", tlbl->key + 100);
7299 emitcode ("", "%05d$:", tlbl->key + 100);
7303 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7307 for (; (size--); offset++)
7310 // result = left & right
7311 if (AOP_TYPE (right) == AOP_LIT)
7313 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7317 aopGet (left, offset, FALSE, FALSE),
7319 isOperandVolatile (result, FALSE));
7323 // faster than result <- left, anl result,right
7324 // and better if result is SFR
7325 if (AOP_TYPE (left) == AOP_ACC)
7328 emitcode("mov", "a,b");
7329 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7331 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7333 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7334 MOVA (aopGet (right, offset, FALSE, FALSE));
7335 emitcode ("xrl", "a,b");
7337 else if (aopGetUsesAcc (left, offset))
7339 MOVA (aopGet (left, offset, FALSE, FALSE));
7340 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7344 MOVA (aopGet (right, offset, FALSE, FALSE));
7345 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7347 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7353 freeAsmop (result, NULL, ic, TRUE);
7354 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7355 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7358 /*-----------------------------------------------------------------*/
7359 /* genInline - write the inline code out */
7360 /*-----------------------------------------------------------------*/
7362 genInline (iCode * ic)
7364 char *buffer, *bp, *bp1;
7366 D(emitcode ("; genInline",""));
7368 _G.inLine += (!options.asmpeep);
7370 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7371 strcpy (buffer, IC_INLINE (ic));
7373 /* emit each line as a code */
7384 /* Add \n for labels, not dirs such as c:\mydir */
7385 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7399 /* emitcode("",buffer); */
7400 _G.inLine -= (!options.asmpeep);
7403 /*-----------------------------------------------------------------*/
7404 /* genRRC - rotate right with carry */
7405 /*-----------------------------------------------------------------*/
7409 operand *left, *result;
7410 int size, offset = 0;
7413 D(emitcode ("; genRRC",""));
7415 /* rotate right with carry */
7416 left = IC_LEFT (ic);
7417 result = IC_RESULT (ic);
7418 aopOp (left, ic, FALSE);
7419 aopOp (result, ic, FALSE);
7421 /* move it to the result */
7422 size = AOP_SIZE (result);
7424 if (size == 1) { /* special case for 1 byte */
7425 l = aopGet (left, offset, FALSE, FALSE);
7427 emitcode ("rr", "a");
7430 /* no need to clear carry, bit7 will be written later */
7433 l = aopGet (left, offset, FALSE, FALSE);
7435 emitcode ("rrc", "a");
7436 if (AOP_SIZE (result) > 1)
7437 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7439 /* now we need to put the carry into the
7440 highest order byte of the result */
7441 if (AOP_SIZE (result) > 1)
7443 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7446 emitcode ("mov", "acc.7,c");
7448 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7449 freeAsmop (result, NULL, ic, TRUE);
7450 freeAsmop (left, NULL, ic, TRUE);
7453 /*-----------------------------------------------------------------*/
7454 /* genRLC - generate code for rotate left with carry */
7455 /*-----------------------------------------------------------------*/
7459 operand *left, *result;
7460 int size, offset = 0;
7463 D(emitcode ("; genRLC",""));
7465 /* rotate right with carry */
7466 left = IC_LEFT (ic);
7467 result = IC_RESULT (ic);
7468 aopOp (left, ic, FALSE);
7469 aopOp (result, ic, FALSE);
7471 /* move it to the result */
7472 size = AOP_SIZE (result);
7476 l = aopGet (left, offset, FALSE, FALSE);
7478 if (size == 0) { /* special case for 1 byte */
7482 emitcode("rlc","a"); /* bit0 will be written later */
7483 if (AOP_SIZE (result) > 1)
7484 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7487 l = aopGet (left, offset, FALSE, FALSE);
7489 emitcode ("rlc", "a");
7490 if (AOP_SIZE (result) > 1)
7491 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7494 /* now we need to put the carry into the
7495 highest order byte of the result */
7496 if (AOP_SIZE (result) > 1)
7498 l = aopGet (result, 0, FALSE, FALSE);
7501 emitcode ("mov", "acc.0,c");
7503 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7504 freeAsmop (result, NULL, ic, TRUE);
7505 freeAsmop (left, NULL, ic, TRUE);
7508 /*-----------------------------------------------------------------*/
7509 /* genGetHbit - generates code get highest order bit */
7510 /*-----------------------------------------------------------------*/
7512 genGetHbit (iCode * ic)
7514 operand *left, *result;
7516 D(emitcode ("; genGetHbit",""));
7518 left = IC_LEFT (ic);
7519 result = IC_RESULT (ic);
7520 aopOp (left, ic, FALSE);
7521 aopOp (result, ic, FALSE);
7523 /* get the highest order byte into a */
7524 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7525 if (AOP_TYPE (result) == AOP_CRY)
7527 emitcode ("rlc", "a");
7532 emitcode ("rl", "a");
7533 emitcode ("anl", "a,#0x01");
7537 freeAsmop (result, NULL, ic, TRUE);
7538 freeAsmop (left, NULL, ic, TRUE);
7541 /*-----------------------------------------------------------------*/
7542 /* genGetAbit - generates code get a single bit */
7543 /*-----------------------------------------------------------------*/
7545 genGetAbit (iCode * ic)
7547 operand *left, *right, *result;
7550 D(emitcode ("; genGetAbit",""));
7552 left = IC_LEFT (ic);
7553 right = IC_RIGHT (ic);
7554 result = IC_RESULT (ic);
7555 aopOp (left, ic, FALSE);
7556 aopOp (right, ic, FALSE);
7557 aopOp (result, ic, FALSE);
7559 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7561 /* get the needed byte into a */
7562 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7564 if (AOP_TYPE (result) == AOP_CRY)
7567 emitcode ("rlc", "a");
7568 else if ((shCount) == 0)
7569 emitcode ("rrc", "a");
7571 emitcode ("mov", "c,acc[%d]", shCount);
7579 emitcode ("rr", "a");
7582 emitcode ("rr", "a");
7585 emitcode ("anl", "a,#0x01");
7589 emitcode ("mov", "c,acc[%d]", shCount);
7590 emitcode ("clr", "a");
7591 emitcode ("rlc", "a");
7594 emitcode ("swap", "a");
7595 emitcode ("anl", "a,#0x01");
7598 emitcode ("rl", "a");
7601 emitcode ("rl", "a");
7602 emitcode ("anl", "a,#0x01");
7608 freeAsmop (result, NULL, ic, TRUE);
7609 freeAsmop (right, NULL, ic, TRUE);
7610 freeAsmop (left, NULL, ic, TRUE);
7613 /*-----------------------------------------------------------------*/
7614 /* genGetByte - generates code get a single byte */
7615 /*-----------------------------------------------------------------*/
7617 genGetByte (iCode * ic)
7619 operand *left, *right, *result;
7622 D(emitcode ("; genGetByte",""));
7624 left = IC_LEFT (ic);
7625 right = IC_RIGHT (ic);
7626 result = IC_RESULT (ic);
7627 aopOp (left, ic, FALSE);
7628 aopOp (right, ic, FALSE);
7629 aopOp (result, ic, FALSE);
7631 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7633 aopGet (left, offset, FALSE, FALSE),
7635 isOperandVolatile (result, FALSE));
7637 freeAsmop (result, NULL, ic, TRUE);
7638 freeAsmop (right, NULL, ic, TRUE);
7639 freeAsmop (left, NULL, ic, TRUE);
7642 /*-----------------------------------------------------------------*/
7643 /* genGetWord - generates code get two bytes */
7644 /*-----------------------------------------------------------------*/
7646 genGetWord (iCode * ic)
7648 operand *left, *right, *result;
7651 D(emitcode ("; genGetWord",""));
7653 left = IC_LEFT (ic);
7654 right = IC_RIGHT (ic);
7655 result = IC_RESULT (ic);
7656 aopOp (left, ic, FALSE);
7657 aopOp (right, ic, FALSE);
7658 aopOp (result, ic, FALSE);
7660 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7662 aopGet (left, offset, FALSE, FALSE),
7664 isOperandVolatile (result, FALSE));
7666 aopGet (left, offset+1, FALSE, FALSE),
7668 isOperandVolatile (result, FALSE));
7670 freeAsmop (result, NULL, ic, TRUE);
7671 freeAsmop (right, NULL, ic, TRUE);
7672 freeAsmop (left, NULL, ic, TRUE);
7675 /*-----------------------------------------------------------------*/
7676 /* genSwap - generates code to swap nibbles or bytes */
7677 /*-----------------------------------------------------------------*/
7679 genSwap (iCode * ic)
7681 operand *left, *result;
7683 D(emitcode ("; genSwap",""));
7685 left = IC_LEFT (ic);
7686 result = IC_RESULT (ic);
7687 aopOp (left, ic, FALSE);
7688 aopOp (result, ic, FALSE);
7690 switch (AOP_SIZE (left))
7692 case 1: /* swap nibbles in byte */
7693 MOVA (aopGet (left, 0, FALSE, FALSE));
7694 emitcode ("swap", "a");
7695 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7697 case 2: /* swap bytes in word */
7698 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7700 MOVA (aopGet (left, 0, FALSE, FALSE));
7701 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7702 0, isOperandVolatile (result, FALSE));
7703 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7705 else if (operandsEqu (left, result))
7708 bool pushedB = FALSE, leftInB = FALSE;
7710 MOVA (aopGet (left, 0, FALSE, FALSE));
7711 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7714 emitcode ("mov", "b,a");
7718 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7719 0, isOperandVolatile (result, FALSE));
7720 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7727 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7728 0, isOperandVolatile (result, FALSE));
7729 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7730 1, isOperandVolatile (result, FALSE));
7734 wassertl(FALSE, "unsupported SWAP operand size");
7737 freeAsmop (result, NULL, ic, TRUE);
7738 freeAsmop (left, NULL, ic, TRUE);
7742 /*-----------------------------------------------------------------*/
7743 /* AccRol - rotate left accumulator by known count */
7744 /*-----------------------------------------------------------------*/
7746 AccRol (int shCount)
7748 shCount &= 0x0007; // shCount : 0..7
7755 emitcode ("rl", "a");
7758 emitcode ("rl", "a");
7759 emitcode ("rl", "a");
7762 emitcode ("swap", "a");
7763 emitcode ("rr", "a");
7766 emitcode ("swap", "a");
7769 emitcode ("swap", "a");
7770 emitcode ("rl", "a");
7773 emitcode ("rr", "a");
7774 emitcode ("rr", "a");
7777 emitcode ("rr", "a");
7782 /*-----------------------------------------------------------------*/
7783 /* AccLsh - left shift accumulator by known count */
7784 /*-----------------------------------------------------------------*/
7786 AccLsh (int shCount)
7791 emitcode ("add", "a,acc");
7792 else if (shCount == 2)
7794 emitcode ("add", "a,acc");
7795 emitcode ("add", "a,acc");
7799 /* rotate left accumulator */
7801 /* and kill the lower order bits */
7802 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7807 /*-----------------------------------------------------------------*/
7808 /* AccRsh - right shift accumulator by known count */
7809 /*-----------------------------------------------------------------*/
7811 AccRsh (int shCount)
7818 emitcode ("rrc", "a");
7822 /* rotate right accumulator */
7823 AccRol (8 - shCount);
7824 /* and kill the higher order bits */
7825 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7830 /*-----------------------------------------------------------------*/
7831 /* AccSRsh - signed right shift accumulator by known count */
7832 /*-----------------------------------------------------------------*/
7834 AccSRsh (int shCount)
7841 emitcode ("mov", "c,acc.7");
7842 emitcode ("rrc", "a");
7844 else if (shCount == 2)
7846 emitcode ("mov", "c,acc.7");
7847 emitcode ("rrc", "a");
7848 emitcode ("mov", "c,acc.7");
7849 emitcode ("rrc", "a");
7853 tlbl = newiTempLabel (NULL);
7854 /* rotate right accumulator */
7855 AccRol (8 - shCount);
7856 /* and kill the higher order bits */
7857 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7858 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7859 emitcode ("orl", "a,#0x%02x",
7860 (unsigned char) ~SRMask[shCount]);
7861 emitcode ("", "%05d$:", tlbl->key + 100);
7866 /*-----------------------------------------------------------------*/
7867 /* shiftR1Left2Result - shift right one byte from left to result */
7868 /*-----------------------------------------------------------------*/
7870 shiftR1Left2Result (operand * left, int offl,
7871 operand * result, int offr,
7872 int shCount, int sign)
7874 MOVA (aopGet (left, offl, FALSE, FALSE));
7875 /* shift right accumulator */
7880 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7883 /*-----------------------------------------------------------------*/
7884 /* shiftL1Left2Result - shift left one byte from left to result */
7885 /*-----------------------------------------------------------------*/
7887 shiftL1Left2Result (operand * left, int offl,
7888 operand * result, int offr, int shCount)
7891 l = aopGet (left, offl, FALSE, FALSE);
7893 /* shift left accumulator */
7895 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7898 /*-----------------------------------------------------------------*/
7899 /* movLeft2Result - move byte from left to result */
7900 /*-----------------------------------------------------------------*/
7902 movLeft2Result (operand * left, int offl,
7903 operand * result, int offr, int sign)
7906 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7908 l = aopGet (left, offl, FALSE, FALSE);
7910 if (*l == '@' && (IS_AOP_PREG (result)))
7912 emitcode ("mov", "a,%s", l);
7913 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7918 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7921 /* MSB sign in acc.7 ! */
7922 if (getDataSize (left) == offl + 1)
7925 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7932 /*-----------------------------------------------------------------*/
7933 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7934 /*-----------------------------------------------------------------*/
7938 emitcode ("rrc", "a");
7939 emitcode ("xch", "a,%s", x);
7940 emitcode ("rrc", "a");
7941 emitcode ("xch", "a,%s", x);
7944 /*-----------------------------------------------------------------*/
7945 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7946 /*-----------------------------------------------------------------*/
7950 emitcode ("xch", "a,%s", x);
7951 emitcode ("rlc", "a");
7952 emitcode ("xch", "a,%s", x);
7953 emitcode ("rlc", "a");
7956 /*-----------------------------------------------------------------*/
7957 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7958 /*-----------------------------------------------------------------*/
7962 emitcode ("xch", "a,%s", x);
7963 emitcode ("add", "a,acc");
7964 emitcode ("xch", "a,%s", x);
7965 emitcode ("rlc", "a");
7968 /*-----------------------------------------------------------------*/
7969 /* AccAXLsh - left shift a:x by known count (0..7) */
7970 /*-----------------------------------------------------------------*/
7972 AccAXLsh (char *x, int shCount)
7987 case 5: // AAAAABBB:CCCCCDDD
7989 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7991 emitcode ("anl", "a,#0x%02x",
7992 SLMask[shCount]); // BBB00000:CCCCCDDD
7994 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7996 AccRol (shCount); // DDDCCCCC:BBB00000
7998 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
8000 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
8002 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
8004 emitcode ("anl", "a,#0x%02x",
8005 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
8007 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8009 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8012 case 6: // AAAAAABB:CCCCCCDD
8013 emitcode ("anl", "a,#0x%02x",
8014 SRMask[shCount]); // 000000BB:CCCCCCDD
8015 emitcode ("mov", "c,acc.0"); // c = B
8016 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8018 AccAXRrl1 (x); // BCCCCCCD:D000000B
8019 AccAXRrl1 (x); // BBCCCCCC:DD000000
8021 emitcode("rrc","a");
8022 emitcode("xch","a,%s", x);
8023 emitcode("rrc","a");
8024 emitcode("mov","c,acc.0"); //<< get correct bit
8025 emitcode("xch","a,%s", x);
8027 emitcode("rrc","a");
8028 emitcode("xch","a,%s", x);
8029 emitcode("rrc","a");
8030 emitcode("xch","a,%s", x);
8033 case 7: // a:x <<= 7
8035 emitcode ("anl", "a,#0x%02x",
8036 SRMask[shCount]); // 0000000B:CCCCCCCD
8038 emitcode ("mov", "c,acc.0"); // c = B
8040 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8042 AccAXRrl1 (x); // BCCCCCCC:D0000000
8050 /*-----------------------------------------------------------------*/
8051 /* AccAXRsh - right shift a:x known count (0..7) */
8052 /*-----------------------------------------------------------------*/
8054 AccAXRsh (char *x, int shCount)
8062 AccAXRrl1 (x); // 0->a:x
8067 AccAXRrl1 (x); // 0->a:x
8070 AccAXRrl1 (x); // 0->a:x
8075 case 5: // AAAAABBB:CCCCCDDD = a:x
8077 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8079 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8081 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8083 emitcode ("anl", "a,#0x%02x",
8084 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8086 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8088 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8090 emitcode ("anl", "a,#0x%02x",
8091 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8093 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8095 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8097 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8100 case 6: // AABBBBBB:CCDDDDDD
8102 emitcode ("mov", "c,acc.7");
8103 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8105 emitcode ("mov", "c,acc.7");
8106 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8108 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8110 emitcode ("anl", "a,#0x%02x",
8111 SRMask[shCount]); // 000000AA:BBBBBBCC
8114 case 7: // ABBBBBBB:CDDDDDDD
8116 emitcode ("mov", "c,acc.7"); // c = A
8118 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8120 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8122 emitcode ("anl", "a,#0x%02x",
8123 SRMask[shCount]); // 0000000A:BBBBBBBC
8131 /*-----------------------------------------------------------------*/
8132 /* AccAXRshS - right shift signed a:x known count (0..7) */
8133 /*-----------------------------------------------------------------*/
8135 AccAXRshS (char *x, int shCount)
8143 emitcode ("mov", "c,acc.7");
8144 AccAXRrl1 (x); // s->a:x
8148 emitcode ("mov", "c,acc.7");
8149 AccAXRrl1 (x); // s->a:x
8151 emitcode ("mov", "c,acc.7");
8152 AccAXRrl1 (x); // s->a:x
8157 case 5: // AAAAABBB:CCCCCDDD = a:x
8159 tlbl = newiTempLabel (NULL);
8160 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8162 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8164 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8166 emitcode ("anl", "a,#0x%02x",
8167 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8169 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8171 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8173 emitcode ("anl", "a,#0x%02x",
8174 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8176 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8178 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8180 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8182 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8183 emitcode ("orl", "a,#0x%02x",
8184 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8186 emitcode ("", "%05d$:", tlbl->key + 100);
8187 break; // SSSSAAAA:BBBCCCCC
8189 case 6: // AABBBBBB:CCDDDDDD
8191 tlbl = newiTempLabel (NULL);
8192 emitcode ("mov", "c,acc.7");
8193 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8195 emitcode ("mov", "c,acc.7");
8196 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8198 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8200 emitcode ("anl", "a,#0x%02x",
8201 SRMask[shCount]); // 000000AA:BBBBBBCC
8203 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8204 emitcode ("orl", "a,#0x%02x",
8205 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8207 emitcode ("", "%05d$:", tlbl->key + 100);
8209 case 7: // ABBBBBBB:CDDDDDDD
8211 tlbl = newiTempLabel (NULL);
8212 emitcode ("mov", "c,acc.7"); // c = A
8214 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8216 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8218 emitcode ("anl", "a,#0x%02x",
8219 SRMask[shCount]); // 0000000A:BBBBBBBC
8221 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8222 emitcode ("orl", "a,#0x%02x",
8223 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8225 emitcode ("", "%05d$:", tlbl->key + 100);
8232 /*-----------------------------------------------------------------*/
8233 /* shiftL2Left2Result - shift left two bytes from left to result */
8234 /*-----------------------------------------------------------------*/
8236 shiftL2Left2Result (operand * left, int offl,
8237 operand * result, int offr, int shCount)
8240 bool pushedB = FALSE;
8243 if (sameRegs (AOP (result), AOP (left)) &&
8244 ((offl + MSB16) == offr))
8246 /* don't crash result[offr] */
8247 MOVA (aopGet (left, offl, FALSE, FALSE));
8248 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8249 x = aopGet (result, offr, FALSE, FALSE);
8251 else if (aopGetUsesAcc (result, offr))
8253 movLeft2Result (left, offl, result, offr, 0);
8256 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8257 MOVA (aopGet (result, offr, FALSE, FALSE));
8258 emitcode ("xch", "a,b");
8263 movLeft2Result (left, offl, result, offr, 0);
8264 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8265 x = aopGet (result, offr, FALSE, FALSE);
8267 /* ax << shCount (x = lsb(result)) */
8268 AccAXLsh (x, shCount);
8271 emitcode ("xch", "a,b");
8272 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8273 aopPut (result, "b", offr + MSB16, isOperandVolatile (result, FALSE));
8278 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8283 /*-----------------------------------------------------------------*/
8284 /* shiftR2Left2Result - shift right two bytes from left to result */
8285 /*-----------------------------------------------------------------*/
8287 shiftR2Left2Result (operand * left, int offl,
8288 operand * result, int offr,
8289 int shCount, int sign)
8292 bool pushedB = FALSE;
8295 if (sameRegs (AOP (result), AOP (left)) &&
8296 ((offl + MSB16) == offr))
8298 /* don't crash result[offr] */
8299 MOVA (aopGet (left, offl, FALSE, FALSE));
8300 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8301 x = aopGet (result, offr, FALSE, FALSE);
8303 else if (aopGetUsesAcc (result, offr))
8305 movLeft2Result (left, offl, result, offr, 0);
8308 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8309 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8314 movLeft2Result (left, offl, result, offr, 0);
8315 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8316 x = aopGet (result, offr, FALSE, FALSE);
8318 /* a:x >> shCount (x = lsb(result)) */
8320 AccAXRshS (x, shCount);
8322 AccAXRsh (x, shCount);
8325 emitcode ("xch", "a,b");
8326 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8327 emitcode ("xch", "a,b");
8330 if (getDataSize (result) > 1)
8331 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8334 /*-----------------------------------------------------------------*/
8335 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8336 /*-----------------------------------------------------------------*/
8338 shiftLLeftOrResult (operand * left, int offl,
8339 operand * result, int offr, int shCount)
8341 MOVA (aopGet (left, offl, FALSE, FALSE));
8342 /* shift left accumulator */
8344 /* or with result */
8345 if (aopGetUsesAcc (result, offr))
8347 emitcode ("xch", "a,b");
8348 MOVA (aopGet (result, offr, FALSE, FALSE));
8349 emitcode ("orl", "a,b");
8353 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8355 /* back to result */
8356 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8359 /*-----------------------------------------------------------------*/
8360 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8361 /*-----------------------------------------------------------------*/
8363 shiftRLeftOrResult (operand * left, int offl,
8364 operand * result, int offr, int shCount)
8366 MOVA (aopGet (left, offl, FALSE, FALSE));
8367 /* shift right accumulator */
8369 /* or with result */
8370 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8371 /* back to result */
8372 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8375 /*-----------------------------------------------------------------*/
8376 /* genlshOne - left shift a one byte quantity by known count */
8377 /*-----------------------------------------------------------------*/
8379 genlshOne (operand * result, operand * left, int shCount)
8381 D(emitcode ("; genlshOne",""));
8383 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8386 /*-----------------------------------------------------------------*/
8387 /* genlshTwo - left shift two bytes by known amount != 0 */
8388 /*-----------------------------------------------------------------*/
8390 genlshTwo (operand * result, operand * left, int shCount)
8394 D(emitcode ("; genlshTwo",""));
8396 size = getDataSize (result);
8398 /* if shCount >= 8 */
8406 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8408 movLeft2Result (left, LSB, result, MSB16, 0);
8410 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8413 /* 1 <= shCount <= 7 */
8417 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8419 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8423 /*-----------------------------------------------------------------*/
8424 /* shiftLLong - shift left one long from left to result */
8425 /* offl = LSB or MSB16 */
8426 /*-----------------------------------------------------------------*/
8428 shiftLLong (operand * left, operand * result, int offr)
8431 int size = AOP_SIZE (result);
8433 if (size >= LSB + offr)
8435 l = aopGet (left, LSB, FALSE, FALSE);
8437 emitcode ("add", "a,acc");
8438 if (sameRegs (AOP (left), AOP (result)) &&
8439 size >= MSB16 + offr && offr != LSB)
8440 emitcode ("xch", "a,%s",
8441 aopGet (left, LSB + offr, FALSE, FALSE));
8443 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8446 if (size >= MSB16 + offr)
8448 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8450 l = aopGet (left, MSB16, FALSE, FALSE);
8453 emitcode ("rlc", "a");
8454 if (sameRegs (AOP (left), AOP (result)) &&
8455 size >= MSB24 + offr && offr != LSB)
8456 emitcode ("xch", "a,%s",
8457 aopGet (left, MSB16 + offr, FALSE, FALSE));
8459 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8462 if (size >= MSB24 + offr)
8464 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8466 l = aopGet (left, MSB24, FALSE, FALSE);
8469 emitcode ("rlc", "a");
8470 if (sameRegs (AOP (left), AOP (result)) &&
8471 size >= MSB32 + offr && offr != LSB)
8472 emitcode ("xch", "a,%s",
8473 aopGet (left, MSB24 + offr, FALSE, FALSE));
8475 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8478 if (size > MSB32 + offr)
8480 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8482 l = aopGet (left, MSB32, FALSE, FALSE);
8485 emitcode ("rlc", "a");
8486 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8489 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8492 /*-----------------------------------------------------------------*/
8493 /* genlshFour - shift four byte by a known amount != 0 */
8494 /*-----------------------------------------------------------------*/
8496 genlshFour (operand * result, operand * left, int shCount)
8500 D(emitcode ("; genlshFour",""));
8502 size = AOP_SIZE (result);
8504 /* if shifting more that 3 bytes */
8509 /* lowest order of left goes to the highest
8510 order of the destination */
8511 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8513 movLeft2Result (left, LSB, result, MSB32, 0);
8514 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8515 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8516 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8520 /* more than two bytes */
8521 else if (shCount >= 16)
8523 /* lower order two bytes goes to higher order two bytes */
8525 /* if some more remaining */
8527 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8530 movLeft2Result (left, MSB16, result, MSB32, 0);
8531 movLeft2Result (left, LSB, result, MSB24, 0);
8533 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8534 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8538 /* if more than 1 byte */
8539 else if (shCount >= 8)
8541 /* lower order three bytes goes to higher order three bytes */
8546 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8548 movLeft2Result (left, LSB, result, MSB16, 0);
8554 movLeft2Result (left, MSB24, result, MSB32, 0);
8555 movLeft2Result (left, MSB16, result, MSB24, 0);
8556 movLeft2Result (left, LSB, result, MSB16, 0);
8557 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8559 else if (shCount == 1)
8560 shiftLLong (left, result, MSB16);
8563 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8564 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8565 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8566 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8571 /* 1 <= shCount <= 7 */
8572 else if (shCount <= 2)
8574 shiftLLong (left, result, LSB);
8576 shiftLLong (result, result, LSB);
8578 /* 3 <= shCount <= 7, optimize */
8581 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8582 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8583 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8587 /*-----------------------------------------------------------------*/
8588 /* genLeftShiftLiteral - left shifting by known count */
8589 /*-----------------------------------------------------------------*/
8591 genLeftShiftLiteral (operand * left,
8596 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8599 D(emitcode ("; genLeftShiftLiteral",""));
8601 freeAsmop (right, NULL, ic, TRUE);
8603 aopOp (left, ic, FALSE);
8604 aopOp (result, ic, FALSE);
8606 size = getSize (operandType (result));
8609 emitcode ("; shift left ", "result %d, left %d", size,
8613 /* I suppose that the left size >= result size */
8618 movLeft2Result (left, size, result, size, 0);
8622 else if (shCount >= (size * 8))
8624 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8630 genlshOne (result, left, shCount);
8634 genlshTwo (result, left, shCount);
8638 genlshFour (result, left, shCount);
8641 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8642 "*** ack! mystery literal shift!\n");
8646 freeAsmop (result, NULL, ic, TRUE);
8647 freeAsmop (left, NULL, ic, TRUE);
8650 /*-----------------------------------------------------------------*/
8651 /* genLeftShift - generates code for left shifting */
8652 /*-----------------------------------------------------------------*/
8654 genLeftShift (iCode * ic)
8656 operand *left, *right, *result;
8659 symbol *tlbl, *tlbl1;
8662 D(emitcode ("; genLeftShift",""));
8664 right = IC_RIGHT (ic);
8665 left = IC_LEFT (ic);
8666 result = IC_RESULT (ic);
8668 aopOp (right, ic, FALSE);
8670 /* if the shift count is known then do it
8671 as efficiently as possible */
8672 if (AOP_TYPE (right) == AOP_LIT)
8674 genLeftShiftLiteral (left, right, result, ic);
8678 /* shift count is unknown then we have to form
8679 a loop get the loop count in B : Note: we take
8680 only the lower order byte since shifting
8681 more that 32 bits make no sense anyway, ( the
8682 largest size of an object can be only 32 bits ) */
8685 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8686 emitcode ("inc", "b");
8687 freeAsmop (right, NULL, ic, TRUE);
8688 aopOp (left, ic, FALSE);
8689 aopOp (result, ic, FALSE);
8691 /* now move the left to the result if they are not the same */
8692 if (!sameRegs (AOP (left), AOP (result)) &&
8693 AOP_SIZE (result) > 1)
8696 size = AOP_SIZE (result);
8700 l = aopGet (left, offset, FALSE, TRUE);
8701 if (*l == '@' && (IS_AOP_PREG (result)))
8704 emitcode ("mov", "a,%s", l);
8705 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8708 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8713 tlbl = newiTempLabel (NULL);
8714 size = AOP_SIZE (result);
8716 tlbl1 = newiTempLabel (NULL);
8718 /* if it is only one byte then */
8721 symbol *tlbl1 = newiTempLabel (NULL);
8723 l = aopGet (left, 0, FALSE, FALSE);
8725 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8726 emitcode ("", "%05d$:", tlbl->key + 100);
8727 emitcode ("add", "a,acc");
8728 emitcode ("", "%05d$:", tlbl1->key + 100);
8729 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8731 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8735 reAdjustPreg (AOP (result));
8737 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8738 emitcode ("", "%05d$:", tlbl->key + 100);
8739 l = aopGet (result, offset, FALSE, FALSE);
8741 emitcode ("add", "a,acc");
8742 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8745 l = aopGet (result, offset, FALSE, FALSE);
8747 emitcode ("rlc", "a");
8748 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8750 reAdjustPreg (AOP (result));
8752 emitcode ("", "%05d$:", tlbl1->key + 100);
8753 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8756 freeAsmop (result, NULL, ic, TRUE);
8757 freeAsmop (left, NULL, ic, TRUE);
8760 /*-----------------------------------------------------------------*/
8761 /* genrshOne - right shift a one byte quantity by known count */
8762 /*-----------------------------------------------------------------*/
8764 genrshOne (operand * result, operand * left,
8765 int shCount, int sign)
8767 D(emitcode ("; genrshOne",""));
8769 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8772 /*-----------------------------------------------------------------*/
8773 /* genrshTwo - right shift two bytes by known amount != 0 */
8774 /*-----------------------------------------------------------------*/
8776 genrshTwo (operand * result, operand * left,
8777 int shCount, int sign)
8779 D(emitcode ("; genrshTwo",""));
8781 /* if shCount >= 8 */
8786 shiftR1Left2Result (left, MSB16, result, LSB,
8789 movLeft2Result (left, MSB16, result, LSB, sign);
8790 addSign (result, MSB16, sign);
8793 /* 1 <= shCount <= 7 */
8795 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8798 /*-----------------------------------------------------------------*/
8799 /* shiftRLong - shift right one long from left to result */
8800 /* offl = LSB or MSB16 */
8801 /*-----------------------------------------------------------------*/
8803 shiftRLong (operand * left, int offl,
8804 operand * result, int sign)
8806 bool useSameRegs = regsInCommon (left, result);
8808 if (useSameRegs && offl>1)
8810 // we are in big trouble, but this shouldn't happen
8811 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8814 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8821 emitcode ("rlc", "a");
8822 emitcode ("subb", "a,acc");
8823 if (useSameRegs && sameReg (AOP (left), MSB32, AOP (result), MSB32))
8825 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8829 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8830 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8835 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8841 emitcode ("clr", "c");
8845 emitcode ("mov", "c,acc.7");
8848 emitcode ("rrc", "a");
8850 if (useSameRegs && offl==MSB16 &&
8851 sameReg (AOP (left), MSB24, AOP (result), MSB32-offl))
8853 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8857 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8858 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8861 emitcode ("rrc", "a");
8862 if (useSameRegs && offl==1 &&
8863 sameReg (AOP (left), MSB16, AOP (result), MSB24-offl))
8865 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8869 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8870 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8872 emitcode ("rrc", "a");
8875 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8880 sameReg (AOP (left), LSB, AOP (result), MSB16-offl))
8882 emitcode ("xch", "a,%s",aopGet (left, LSB, FALSE, FALSE));
8886 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8887 MOVA (aopGet (left, LSB, FALSE, FALSE));
8889 emitcode ("rrc", "a");
8890 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8894 /*-----------------------------------------------------------------*/
8895 /* genrshFour - shift four byte by a known amount != 0 */
8896 /*-----------------------------------------------------------------*/
8898 genrshFour (operand * result, operand * left,
8899 int shCount, int sign)
8901 D(emitcode ("; genrshFour",""));
8903 /* if shifting more that 3 bytes */
8908 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8910 movLeft2Result (left, MSB32, result, LSB, sign);
8911 addSign (result, MSB16, sign);
8913 else if (shCount >= 16)
8917 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8920 movLeft2Result (left, MSB24, result, LSB, 0);
8921 movLeft2Result (left, MSB32, result, MSB16, sign);
8923 addSign (result, MSB24, sign);
8925 else if (shCount >= 8)
8929 shiftRLong (left, MSB16, result, sign);
8930 else if (shCount == 0)
8932 movLeft2Result (left, MSB16, result, LSB, 0);
8933 movLeft2Result (left, MSB24, result, MSB16, 0);
8934 movLeft2Result (left, MSB32, result, MSB24, sign);
8935 addSign (result, MSB32, sign);
8939 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8940 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8941 /* the last shift is signed */
8942 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8943 addSign (result, MSB32, sign);
8947 { /* 1 <= shCount <= 7 */
8950 shiftRLong (left, LSB, result, sign);
8952 shiftRLong (result, LSB, result, sign);
8956 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8957 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8958 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8963 /*-----------------------------------------------------------------*/
8964 /* genRightShiftLiteral - right shifting by known count */
8965 /*-----------------------------------------------------------------*/
8967 genRightShiftLiteral (operand * left,
8973 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8976 D(emitcode ("; genRightShiftLiteral",""));
8978 freeAsmop (right, NULL, ic, TRUE);
8980 aopOp (left, ic, FALSE);
8981 aopOp (result, ic, FALSE);
8984 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8988 size = getDataSize (left);
8989 /* test the LEFT size !!! */
8991 /* I suppose that the left size >= result size */
8994 size = getDataSize (result);
8996 movLeft2Result (left, size, result, size, 0);
8999 else if (shCount >= (size * 8))
9002 /* get sign in acc.7 */
9003 MOVA (aopGet (left, size - 1, FALSE, FALSE));
9005 addSign (result, LSB, sign);
9012 genrshOne (result, left, shCount, sign);
9016 genrshTwo (result, left, shCount, sign);
9020 genrshFour (result, left, shCount, sign);
9026 freeAsmop (result, NULL, ic, TRUE);
9027 freeAsmop (left, NULL, ic, TRUE);
9030 /*-----------------------------------------------------------------*/
9031 /* genSignedRightShift - right shift of signed number */
9032 /*-----------------------------------------------------------------*/
9034 genSignedRightShift (iCode * ic)
9036 operand *right, *left, *result;
9039 symbol *tlbl, *tlbl1;
9042 D(emitcode ("; genSignedRightShift",""));
9044 /* we do it the hard way put the shift count in b
9045 and loop thru preserving the sign */
9047 right = IC_RIGHT (ic);
9048 left = IC_LEFT (ic);
9049 result = IC_RESULT (ic);
9051 aopOp (right, ic, FALSE);
9054 if (AOP_TYPE (right) == AOP_LIT)
9056 genRightShiftLiteral (left, right, result, ic, 1);
9059 /* shift count is unknown then we have to form
9060 a loop get the loop count in B : Note: we take
9061 only the lower order byte since shifting
9062 more that 32 bits make no sense anyway, ( the
9063 largest size of an object can be only 32 bits ) */
9066 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9067 emitcode ("inc", "b");
9068 freeAsmop (right, NULL, ic, TRUE);
9069 aopOp (left, ic, FALSE);
9070 aopOp (result, ic, FALSE);
9072 /* now move the left to the result if they are not the
9074 if (!sameRegs (AOP (left), AOP (result)) &&
9075 AOP_SIZE (result) > 1)
9078 size = AOP_SIZE (result);
9082 l = aopGet (left, offset, FALSE, TRUE);
9083 if (*l == '@' && IS_AOP_PREG (result))
9086 emitcode ("mov", "a,%s", l);
9087 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9090 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9095 /* mov the highest order bit to OVR */
9096 tlbl = newiTempLabel (NULL);
9097 tlbl1 = newiTempLabel (NULL);
9099 size = AOP_SIZE (result);
9101 MOVA (aopGet (left, offset, FALSE, FALSE));
9102 emitcode ("rlc", "a");
9103 emitcode ("mov", "ov,c");
9104 /* if it is only one byte then */
9107 l = aopGet (left, 0, FALSE, FALSE);
9109 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9110 emitcode ("", "%05d$:", tlbl->key + 100);
9111 emitcode ("mov", "c,ov");
9112 emitcode ("rrc", "a");
9113 emitcode ("", "%05d$:", tlbl1->key + 100);
9114 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9116 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9120 reAdjustPreg (AOP (result));
9121 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9122 emitcode ("", "%05d$:", tlbl->key + 100);
9123 emitcode ("mov", "c,ov");
9126 l = aopGet (result, offset, FALSE, FALSE);
9128 emitcode ("rrc", "a");
9129 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9131 reAdjustPreg (AOP (result));
9132 emitcode ("", "%05d$:", tlbl1->key + 100);
9133 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9137 freeAsmop (result, NULL, ic, TRUE);
9138 freeAsmop (left, NULL, ic, TRUE);
9141 /*-----------------------------------------------------------------*/
9142 /* genRightShift - generate code for right shifting */
9143 /*-----------------------------------------------------------------*/
9145 genRightShift (iCode * ic)
9147 operand *right, *left, *result;
9151 symbol *tlbl, *tlbl1;
9154 D(emitcode ("; genRightShift",""));
9156 /* if signed then we do it the hard way preserve the
9157 sign bit moving it inwards */
9158 letype = getSpec (operandType (IC_LEFT (ic)));
9160 if (!SPEC_USIGN (letype))
9162 genSignedRightShift (ic);
9166 /* signed & unsigned types are treated the same : i.e. the
9167 signed is NOT propagated inwards : quoting from the
9168 ANSI - standard : "for E1 >> E2, is equivalent to division
9169 by 2**E2 if unsigned or if it has a non-negative value,
9170 otherwise the result is implementation defined ", MY definition
9171 is that the sign does not get propagated */
9173 right = IC_RIGHT (ic);
9174 left = IC_LEFT (ic);
9175 result = IC_RESULT (ic);
9177 aopOp (right, ic, FALSE);
9179 /* if the shift count is known then do it
9180 as efficiently as possible */
9181 if (AOP_TYPE (right) == AOP_LIT)
9183 genRightShiftLiteral (left, right, result, ic, 0);
9187 /* shift count is unknown then we have to form
9188 a loop get the loop count in B : Note: we take
9189 only the lower order byte since shifting
9190 more that 32 bits make no sense anyway, ( the
9191 largest size of an object can be only 32 bits ) */
9194 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9195 emitcode ("inc", "b");
9196 freeAsmop (right, NULL, ic, TRUE);
9197 aopOp (left, ic, FALSE);
9198 aopOp (result, ic, FALSE);
9200 /* now move the left to the result if they are not the
9202 if (!sameRegs (AOP (left), AOP (result)) &&
9203 AOP_SIZE (result) > 1)
9206 size = AOP_SIZE (result);
9210 l = aopGet (left, offset, FALSE, TRUE);
9211 if (*l == '@' && IS_AOP_PREG (result))
9214 emitcode ("mov", "a,%s", l);
9215 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9218 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9223 tlbl = newiTempLabel (NULL);
9224 tlbl1 = newiTempLabel (NULL);
9225 size = AOP_SIZE (result);
9228 /* if it is only one byte then */
9231 l = aopGet (left, 0, FALSE, FALSE);
9233 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9234 emitcode ("", "%05d$:", tlbl->key + 100);
9236 emitcode ("rrc", "a");
9237 emitcode ("", "%05d$:", tlbl1->key + 100);
9238 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9240 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9244 reAdjustPreg (AOP (result));
9245 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9246 emitcode ("", "%05d$:", tlbl->key + 100);
9250 l = aopGet (result, offset, FALSE, FALSE);
9252 emitcode ("rrc", "a");
9253 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9255 reAdjustPreg (AOP (result));
9257 emitcode ("", "%05d$:", tlbl1->key + 100);
9258 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9262 freeAsmop (result, NULL, ic, TRUE);
9263 freeAsmop (left, NULL, ic, TRUE);
9266 /*-----------------------------------------------------------------*/
9267 /* emitPtrByteGet - emits code to get a byte into A through a */
9268 /* pointer register (R0, R1, or DPTR). The */
9269 /* original value of A can be preserved in B. */
9270 /*-----------------------------------------------------------------*/
9272 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9279 emitcode ("mov", "b,a");
9280 emitcode ("mov", "a,@%s", rname);
9285 emitcode ("mov", "b,a");
9286 emitcode ("movx", "a,@%s", rname);
9291 emitcode ("mov", "b,a");
9292 emitcode ("movx", "a,@dptr");
9297 emitcode ("mov", "b,a");
9298 emitcode ("clr", "a");
9299 emitcode ("movc", "a,@a+dptr");
9305 emitcode ("push", "b");
9306 emitcode ("push", "acc");
9308 emitcode ("lcall", "__gptrget");
9310 emitcode ("pop", "b");
9315 /*-----------------------------------------------------------------*/
9316 /* emitPtrByteSet - emits code to set a byte from src through a */
9317 /* pointer register (R0, R1, or DPTR). */
9318 /*-----------------------------------------------------------------*/
9320 emitPtrByteSet (char *rname, int p_type, char *src)
9329 emitcode ("mov", "@%s,a", rname);
9332 emitcode ("mov", "@%s,%s", rname, src);
9337 emitcode ("movx", "@%s,a", rname);
9342 emitcode ("movx", "@dptr,a");
9347 emitcode ("lcall", "__gptrput");
9352 /*-----------------------------------------------------------------*/
9353 /* genUnpackBits - generates code for unpacking bits */
9354 /*-----------------------------------------------------------------*/
9356 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9358 int offset = 0; /* result byte offset */
9359 int rsize; /* result size */
9360 int rlen = 0; /* remaining bitfield length */
9361 sym_link *etype; /* bitfield type information */
9362 int blen; /* bitfield length */
9363 int bstr; /* bitfield starting bit within byte */
9366 D(emitcode ("; genUnpackBits",""));
9368 etype = getSpec (operandType (result));
9369 rsize = getSize (operandType (result));
9370 blen = SPEC_BLEN (etype);
9371 bstr = SPEC_BSTR (etype);
9373 if (ifx && blen <= 8)
9375 emitPtrByteGet (rname, ptype, FALSE);
9378 SNPRINTF (buffer, sizeof(buffer),
9380 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9385 emitcode ("anl", "a,#0x%02x",
9386 (((unsigned char) -1) >> (8 - blen)) << bstr);
9387 genIfxJump (ifx, "a", NULL, NULL, NULL);
9393 /* If the bitfield length is less than a byte */
9396 emitPtrByteGet (rname, ptype, FALSE);
9398 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9399 if (!SPEC_USIGN (etype))
9401 /* signed bitfield */
9402 symbol *tlbl = newiTempLabel (NULL);
9404 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9405 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9406 emitcode ("", "%05d$:", tlbl->key + 100);
9408 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9412 /* Bit field did not fit in a byte. Copy all
9413 but the partial byte at the end. */
9414 for (rlen=blen;rlen>=8;rlen-=8)
9416 emitPtrByteGet (rname, ptype, FALSE);
9417 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9419 emitcode ("inc", "%s", rname);
9422 /* Handle the partial byte at the end */
9425 emitPtrByteGet (rname, ptype, FALSE);
9426 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9427 if (!SPEC_USIGN (etype))
9429 /* signed bitfield */
9430 symbol *tlbl = newiTempLabel (NULL);
9432 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9433 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9434 emitcode ("", "%05d$:", tlbl->key + 100);
9436 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9444 if (SPEC_USIGN (etype))
9448 /* signed bitfield: sign extension with 0x00 or 0xff */
9449 emitcode ("rlc", "a");
9450 emitcode ("subb", "a,acc");
9456 aopPut (result, source, offset++, isOperandVolatile (result, FALSE));
9461 /*-----------------------------------------------------------------*/
9462 /* genDataPointerGet - generates code when ptr offset is known */
9463 /*-----------------------------------------------------------------*/
9465 genDataPointerGet (operand * left,
9471 int size, offset = 0;
9473 D(emitcode ("; genDataPointerGet",""));
9475 aopOp (result, ic, TRUE);
9477 /* get the string representation of the name */
9478 l = aopGet (left, 0, FALSE, TRUE);
9479 size = AOP_SIZE (result);
9483 sprintf (buffer, "(%s + %d)", l + 1, offset);
9485 sprintf (buffer, "%s", l + 1);
9486 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9489 freeAsmop (result, NULL, ic, TRUE);
9490 freeAsmop (left, NULL, ic, TRUE);
9493 /*-----------------------------------------------------------------*/
9494 /* genNearPointerGet - emitcode for near pointer fetch */
9495 /*-----------------------------------------------------------------*/
9497 genNearPointerGet (operand * left,
9506 sym_link *rtype, *retype;
9507 sym_link *ltype = operandType (left);
9510 D(emitcode ("; genNearPointerGet",""));
9512 rtype = operandType (result);
9513 retype = getSpec (rtype);
9515 aopOp (left, ic, FALSE);
9517 /* if left is rematerialisable and
9518 result is not bitfield variable type and
9519 the left is pointer to data space i.e
9520 lower 128 bytes of space */
9521 if (AOP_TYPE (left) == AOP_IMMD &&
9522 !IS_BITFIELD (retype) &&
9523 DCL_TYPE (ltype) == POINTER)
9525 genDataPointerGet (left, result, ic);
9529 /* if the value is already in a pointer register
9530 then don't need anything more */
9531 if (!AOP_INPREG (AOP (left)))
9533 if (IS_AOP_PREG (left))
9535 // Aha, it is a pointer, just in disguise.
9536 rname = aopGet (left, 0, FALSE, FALSE);
9539 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9540 __FILE__, __LINE__);
9545 emitcode ("mov", "a%s,%s", rname + 1, rname);
9546 rname++; // skip the '@'.
9551 /* otherwise get a free pointer register */
9553 preg = getFreePtr (ic, &aop, FALSE);
9554 emitcode ("mov", "%s,%s",
9556 aopGet (left, 0, FALSE, TRUE));
9561 rname = aopGet (left, 0, FALSE, FALSE);
9563 //aopOp (result, ic, FALSE);
9564 aopOp (result, ic, result?TRUE:FALSE);
9566 /* if bitfield then unpack the bits */
9567 if (IS_BITFIELD (retype))
9568 genUnpackBits (result, rname, POINTER, ifx);
9571 /* we have can just get the values */
9572 int size = AOP_SIZE (result);
9577 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9580 emitcode ("mov", "a,@%s", rname);
9582 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9586 sprintf (buffer, "@%s", rname);
9587 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9591 emitcode ("inc", "%s", rname);
9595 /* now some housekeeping stuff */
9596 if (aop) /* we had to allocate for this iCode */
9598 if (pi) { /* post increment present */
9599 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9601 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9605 /* we did not allocate which means left
9606 already in a pointer register, then
9607 if size > 0 && this could be used again
9608 we have to point it back to where it
9610 if ((AOP_SIZE (result) > 1 &&
9611 !OP_SYMBOL (left)->remat &&
9612 (OP_SYMBOL (left)->liveTo > ic->seq ||
9616 int size = AOP_SIZE (result) - 1;
9618 emitcode ("dec", "%s", rname);
9622 if (ifx && !ifx->generated)
9624 genIfxJump (ifx, "a", left, NULL, result);
9628 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9629 freeAsmop (left, NULL, ic, TRUE);
9630 if (pi) pi->generated = 1;
9633 /*-----------------------------------------------------------------*/
9634 /* genPagedPointerGet - emitcode for paged pointer fetch */
9635 /*-----------------------------------------------------------------*/
9637 genPagedPointerGet (operand * left,
9646 sym_link *rtype, *retype;
9648 D(emitcode ("; genPagedPointerGet",""));
9650 rtype = operandType (result);
9651 retype = getSpec (rtype);
9653 aopOp (left, ic, FALSE);
9655 /* if the value is already in a pointer register
9656 then don't need anything more */
9657 if (!AOP_INPREG (AOP (left)))
9659 /* otherwise get a free pointer register */
9661 preg = getFreePtr (ic, &aop, FALSE);
9662 emitcode ("mov", "%s,%s",
9664 aopGet (left, 0, FALSE, TRUE));
9668 rname = aopGet (left, 0, FALSE, FALSE);
9670 aopOp (result, ic, FALSE);
9672 /* if bitfield then unpack the bits */
9673 if (IS_BITFIELD (retype))
9674 genUnpackBits (result, rname, PPOINTER, ifx);
9677 /* we have can just get the values */
9678 int size = AOP_SIZE (result);
9684 emitcode ("movx", "a,@%s", rname);
9686 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9691 emitcode ("inc", "%s", rname);
9695 /* now some housekeeping stuff */
9696 if (aop) /* we had to allocate for this iCode */
9698 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9699 freeAsmop (NULL, aop, ic, TRUE);
9703 /* we did not allocate which means left
9704 already in a pointer register, then
9705 if size > 0 && this could be used again
9706 we have to point it back to where it
9708 if ((AOP_SIZE (result) > 1 &&
9709 !OP_SYMBOL (left)->remat &&
9710 (OP_SYMBOL (left)->liveTo > ic->seq ||
9714 int size = AOP_SIZE (result) - 1;
9716 emitcode ("dec", "%s", rname);
9720 if (ifx && !ifx->generated)
9722 genIfxJump (ifx, "a", left, NULL, result);
9726 freeAsmop (result, NULL, ic, TRUE);
9727 freeAsmop (left, NULL, ic, TRUE);
9728 if (pi) pi->generated = 1;
9731 /*--------------------------------------------------------------------*/
9732 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9733 /*--------------------------------------------------------------------*/
9735 loadDptrFromOperand (operand *op, bool loadBToo)
9737 if (AOP_TYPE (op) != AOP_STR)
9739 /* if this is rematerializable */
9740 if (AOP_TYPE (op) == AOP_IMMD)
9742 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9745 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9746 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9749 wassertl(FALSE, "need pointerCode");
9750 emitcode ("", "; mov b,???");
9751 /* genPointerGet and genPointerSet originally did different
9752 ** things for this case. Both seem wrong.
9753 ** from genPointerGet:
9754 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9755 ** from genPointerSet:
9756 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9761 else if (AOP_TYPE (op) == AOP_DPTR)
9765 MOVA (aopGet (op, 0, FALSE, FALSE));
9766 emitcode ("push", "acc");
9767 MOVA (aopGet (op, 1, FALSE, FALSE));
9768 emitcode ("push", "acc");
9769 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9770 emitcode ("pop", "dph");
9771 emitcode ("pop", "dpl");
9775 MOVA (aopGet (op, 0, FALSE, FALSE));
9776 emitcode ("push", "acc");
9777 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9778 emitcode ("pop", "dpl");
9782 { /* we need to get it byte by byte */
9783 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9784 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9786 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9791 /*-----------------------------------------------------------------*/
9792 /* genFarPointerGet - gget value from far space */
9793 /*-----------------------------------------------------------------*/
9795 genFarPointerGet (operand * left,
9796 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9799 sym_link *retype = getSpec (operandType (result));
9801 D(emitcode ("; genFarPointerGet",""));
9803 aopOp (left, ic, FALSE);
9804 loadDptrFromOperand (left, FALSE);
9806 /* so dptr now contains the address */
9807 aopOp (result, ic, FALSE);
9809 /* if bit then unpack */
9810 if (IS_BITFIELD (retype))
9811 genUnpackBits (result, "dptr", FPOINTER, ifx);
9814 size = AOP_SIZE (result);
9819 emitcode ("movx", "a,@dptr");
9821 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9823 emitcode ("inc", "dptr");
9827 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9829 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9830 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9834 if (ifx && !ifx->generated)
9836 genIfxJump (ifx, "a", left, NULL, result);
9839 freeAsmop (result, NULL, ic, TRUE);
9840 freeAsmop (left, NULL, ic, TRUE);
9843 /*-----------------------------------------------------------------*/
9844 /* genCodePointerGet - gget value from code space */
9845 /*-----------------------------------------------------------------*/
9847 genCodePointerGet (operand * left,
9848 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9851 sym_link *retype = getSpec (operandType (result));
9853 D(emitcode ("; genCodePointerGet",""));
9855 aopOp (left, ic, FALSE);
9856 loadDptrFromOperand (left, FALSE);
9858 /* so dptr now contains the address */
9859 aopOp (result, ic, FALSE);
9861 /* if bit then unpack */
9862 if (IS_BITFIELD (retype))
9863 genUnpackBits (result, "dptr", CPOINTER, ifx);
9866 size = AOP_SIZE (result);
9871 emitcode ("clr", "a");
9872 emitcode ("movc", "a,@a+dptr");
9874 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9876 emitcode ("inc", "dptr");
9880 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9882 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9883 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9887 if (ifx && !ifx->generated)
9889 genIfxJump (ifx, "a", left, NULL, result);
9892 freeAsmop (result, NULL, ic, TRUE);
9893 freeAsmop (left, NULL, ic, TRUE);
9896 /*-----------------------------------------------------------------*/
9897 /* genGenPointerGet - gget value from generic pointer space */
9898 /*-----------------------------------------------------------------*/
9900 genGenPointerGet (operand * left,
9901 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9904 sym_link *retype = getSpec (operandType (result));
9906 D(emitcode ("; genGenPointerGet",""));
9908 aopOp (left, ic, FALSE);
9909 loadDptrFromOperand (left, TRUE);
9911 /* so dptr know contains the address */
9912 aopOp (result, ic, FALSE);
9914 /* if bit then unpack */
9915 if (IS_BITFIELD (retype))
9916 genUnpackBits (result, "dptr", GPOINTER, ifx);
9919 size = AOP_SIZE (result);
9924 emitcode ("lcall", "__gptrget");
9926 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9928 emitcode ("inc", "dptr");
9932 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9934 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9935 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9939 if (ifx && !ifx->generated)
9941 genIfxJump (ifx, "a", left, NULL, result);
9944 freeAsmop (result, NULL, ic, TRUE);
9945 freeAsmop (left, NULL, ic, TRUE);
9948 /*-----------------------------------------------------------------*/
9949 /* genPointerGet - generate code for pointer get */
9950 /*-----------------------------------------------------------------*/
9952 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9954 operand *left, *result;
9955 sym_link *type, *etype;
9958 D(emitcode ("; genPointerGet",""));
9960 left = IC_LEFT (ic);
9961 result = IC_RESULT (ic);
9963 if (getSize (operandType (result))>1)
9966 /* depending on the type of pointer we need to
9967 move it to the correct pointer register */
9968 type = operandType (left);
9969 etype = getSpec (type);
9970 /* if left is of type of pointer then it is simple */
9971 if (IS_PTR (type) && !IS_FUNC (type->next))
9972 p_type = DCL_TYPE (type);
9975 /* we have to go by the storage class */
9976 p_type = PTR_TYPE (SPEC_OCLS (etype));
9979 /* special case when cast remat */
9980 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9981 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9982 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9983 type = operandType (left);
9984 p_type = DCL_TYPE (type);
9986 /* now that we have the pointer type we assign
9987 the pointer values */
9993 genNearPointerGet (left, result, ic, pi, ifx);
9997 genPagedPointerGet (left, result, ic, pi, ifx);
10001 genFarPointerGet (left, result, ic, pi, ifx);
10005 genCodePointerGet (left, result, ic, pi, ifx);
10009 genGenPointerGet (left, result, ic, pi, ifx);
10017 /*-----------------------------------------------------------------*/
10018 /* genPackBits - generates code for packed bit storage */
10019 /*-----------------------------------------------------------------*/
10021 genPackBits (sym_link * etype,
10023 char *rname, int p_type)
10025 int offset = 0; /* source byte offset */
10026 int rlen = 0; /* remaining bitfield length */
10027 int blen; /* bitfield length */
10028 int bstr; /* bitfield starting bit within byte */
10029 int litval; /* source literal value (if AOP_LIT) */
10030 unsigned char mask; /* bitmask within current byte */
10032 D(emitcode ("; genPackBits",""));
10034 blen = SPEC_BLEN (etype);
10035 bstr = SPEC_BSTR (etype);
10037 /* If the bitfield length is less than a byte */
10040 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10041 (unsigned char) (0xFF >> (8 - bstr)));
10043 if (AOP_TYPE (right) == AOP_LIT)
10045 /* Case with a bitfield length <8 and literal source
10047 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10049 litval &= (~mask) & 0xff;
10050 emitPtrByteGet (rname, p_type, FALSE);
10051 if ((mask|litval)!=0xff)
10052 emitcode ("anl","a,#0x%02x", mask);
10054 emitcode ("orl","a,#0x%02x", litval);
10058 if ((blen==1) && (p_type!=GPOINTER))
10060 /* Case with a bitfield length == 1 and no generic pointer
10062 if (AOP_TYPE (right) == AOP_CRY)
10063 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10066 MOVA (aopGet (right, 0, FALSE, FALSE));
10067 emitcode ("rrc","a");
10069 emitPtrByteGet (rname, p_type, FALSE);
10070 emitcode ("mov","acc.%d,c",bstr);
10075 /* Case with a bitfield length < 8 and arbitrary source
10077 MOVA (aopGet (right, 0, FALSE, FALSE));
10078 /* shift and mask source value */
10080 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10082 pushedB = pushB ();
10083 /* transfer A to B and get next byte */
10084 emitPtrByteGet (rname, p_type, TRUE);
10086 emitcode ("anl", "a,#0x%02x", mask);
10087 emitcode ("orl", "a,b");
10088 if (p_type == GPOINTER)
10089 emitcode ("pop", "b");
10095 emitPtrByteSet (rname, p_type, "a");
10099 /* Bit length is greater than 7 bits. In this case, copy */
10100 /* all except the partial byte at the end */
10101 for (rlen=blen;rlen>=8;rlen-=8)
10103 emitPtrByteSet (rname, p_type,
10104 aopGet (right, offset++, FALSE, TRUE) );
10106 emitcode ("inc", "%s", rname);
10109 /* If there was a partial byte at the end */
10112 mask = (((unsigned char) -1 << rlen) & 0xff);
10114 if (AOP_TYPE (right) == AOP_LIT)
10116 /* Case with partial byte and literal source
10118 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10119 litval >>= (blen-rlen);
10120 litval &= (~mask) & 0xff;
10121 emitPtrByteGet (rname, p_type, FALSE);
10122 if ((mask|litval)!=0xff)
10123 emitcode ("anl","a,#0x%02x", mask);
10125 emitcode ("orl","a,#0x%02x", litval);
10130 /* Case with partial byte and arbitrary source
10132 MOVA (aopGet (right, offset++, FALSE, FALSE));
10133 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10135 pushedB = pushB ();
10136 /* transfer A to B and get next byte */
10137 emitPtrByteGet (rname, p_type, TRUE);
10139 emitcode ("anl", "a,#0x%02x", mask);
10140 emitcode ("orl", "a,b");
10141 if (p_type == GPOINTER)
10142 emitcode ("pop", "b");
10146 emitPtrByteSet (rname, p_type, "a");
10152 /*-----------------------------------------------------------------*/
10153 /* genDataPointerSet - remat pointer to data space */
10154 /*-----------------------------------------------------------------*/
10156 genDataPointerSet (operand * right,
10160 int size, offset = 0;
10161 char *l, buffer[256];
10163 D(emitcode ("; genDataPointerSet",""));
10165 aopOp (right, ic, FALSE);
10167 l = aopGet (result, 0, FALSE, TRUE);
10168 size = AOP_SIZE (right);
10172 sprintf (buffer, "(%s + %d)", l + 1, offset);
10174 sprintf (buffer, "%s", l + 1);
10175 emitcode ("mov", "%s,%s", buffer,
10176 aopGet (right, offset++, FALSE, FALSE));
10179 freeAsmop (result, NULL, ic, TRUE);
10180 freeAsmop (right, NULL, ic, TRUE);
10183 /*-----------------------------------------------------------------*/
10184 /* genNearPointerSet - emitcode for near pointer put */
10185 /*-----------------------------------------------------------------*/
10187 genNearPointerSet (operand * right,
10195 sym_link *retype, *letype;
10196 sym_link *ptype = operandType (result);
10198 D(emitcode ("; genNearPointerSet",""));
10200 retype = getSpec (operandType (right));
10201 letype = getSpec (ptype);
10202 aopOp (result, ic, FALSE);
10204 /* if the result is rematerializable &
10205 in data space & not a bit variable */
10206 if (AOP_TYPE (result) == AOP_IMMD &&
10207 DCL_TYPE (ptype) == POINTER &&
10208 !IS_BITVAR (retype) &&
10209 !IS_BITVAR (letype))
10211 genDataPointerSet (right, result, ic);
10215 /* if the value is already in a pointer register
10216 then don't need anything more */
10217 if (!AOP_INPREG (AOP (result)))
10220 //AOP_TYPE (result) == AOP_STK
10221 IS_AOP_PREG(result)
10224 // Aha, it is a pointer, just in disguise.
10225 rname = aopGet (result, 0, FALSE, FALSE);
10228 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10229 __FILE__, __LINE__);
10234 emitcode ("mov", "a%s,%s", rname + 1, rname);
10235 rname++; // skip the '@'.
10240 /* otherwise get a free pointer register */
10241 aop = newAsmop (0);
10242 preg = getFreePtr (ic, &aop, FALSE);
10243 emitcode ("mov", "%s,%s",
10245 aopGet (result, 0, FALSE, TRUE));
10246 rname = preg->name;
10251 rname = aopGet (result, 0, FALSE, FALSE);
10254 aopOp (right, ic, FALSE);
10256 /* if bitfield then unpack the bits */
10257 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10258 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10261 /* we have can just get the values */
10262 int size = AOP_SIZE (right);
10267 l = aopGet (right, offset, FALSE, TRUE);
10271 emitcode ("mov", "@%s,a", rname);
10274 emitcode ("mov", "@%s,%s", rname, l);
10276 emitcode ("inc", "%s", rname);
10281 /* now some housekeeping stuff */
10282 if (aop) /* we had to allocate for this iCode */
10285 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10286 freeAsmop (NULL, aop, ic, TRUE);
10290 /* we did not allocate which means left
10291 already in a pointer register, then
10292 if size > 0 && this could be used again
10293 we have to point it back to where it
10295 if ((AOP_SIZE (right) > 1 &&
10296 !OP_SYMBOL (result)->remat &&
10297 (OP_SYMBOL (result)->liveTo > ic->seq ||
10301 int size = AOP_SIZE (right) - 1;
10303 emitcode ("dec", "%s", rname);
10308 if (pi) pi->generated = 1;
10309 freeAsmop (result, NULL, ic, TRUE);
10310 freeAsmop (right, NULL, ic, TRUE);
10313 /*-----------------------------------------------------------------*/
10314 /* genPagedPointerSet - emitcode for Paged pointer put */
10315 /*-----------------------------------------------------------------*/
10317 genPagedPointerSet (operand * right,
10325 sym_link *retype, *letype;
10327 D(emitcode ("; genPagedPointerSet",""));
10329 retype = getSpec (operandType (right));
10330 letype = getSpec (operandType (result));
10332 aopOp (result, ic, FALSE);
10334 /* if the value is already in a pointer register
10335 then don't need anything more */
10336 if (!AOP_INPREG (AOP (result)))
10338 /* otherwise get a free pointer register */
10339 aop = newAsmop (0);
10340 preg = getFreePtr (ic, &aop, FALSE);
10341 emitcode ("mov", "%s,%s",
10343 aopGet (result, 0, FALSE, TRUE));
10344 rname = preg->name;
10347 rname = aopGet (result, 0, FALSE, FALSE);
10349 aopOp (right, ic, FALSE);
10351 /* if bitfield then unpack the bits */
10352 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10353 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10356 /* we have can just get the values */
10357 int size = AOP_SIZE (right);
10362 l = aopGet (right, offset, FALSE, TRUE);
10365 emitcode ("movx", "@%s,a", rname);
10368 emitcode ("inc", "%s", rname);
10374 /* now some housekeeping stuff */
10375 if (aop) /* we had to allocate for this iCode */
10378 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10379 freeAsmop (NULL, aop, ic, TRUE);
10383 /* we did not allocate which means left
10384 already in a pointer register, then
10385 if size > 0 && this could be used again
10386 we have to point it back to where it
10388 if (AOP_SIZE (right) > 1 &&
10389 !OP_SYMBOL (result)->remat &&
10390 (OP_SYMBOL (result)->liveTo > ic->seq ||
10393 int size = AOP_SIZE (right) - 1;
10395 emitcode ("dec", "%s", rname);
10400 if (pi) pi->generated = 1;
10401 freeAsmop (result, NULL, ic, TRUE);
10402 freeAsmop (right, NULL, ic, TRUE);
10405 /*-----------------------------------------------------------------*/
10406 /* genFarPointerSet - set value from far space */
10407 /*-----------------------------------------------------------------*/
10409 genFarPointerSet (operand * right,
10410 operand * result, iCode * ic, iCode * pi)
10413 sym_link *retype = getSpec (operandType (right));
10414 sym_link *letype = getSpec (operandType (result));
10416 D(emitcode ("; genFarPointerSet",""));
10418 aopOp (result, ic, FALSE);
10419 loadDptrFromOperand (result, FALSE);
10421 /* so dptr know contains the address */
10422 aopOp (right, ic, FALSE);
10424 /* if bit then unpack */
10425 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10426 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10429 size = AOP_SIZE (right);
10434 char *l = aopGet (right, offset++, FALSE, FALSE);
10436 emitcode ("movx", "@dptr,a");
10438 emitcode ("inc", "dptr");
10441 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10442 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10443 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10446 freeAsmop (result, NULL, ic, TRUE);
10447 freeAsmop (right, NULL, ic, TRUE);
10450 /*-----------------------------------------------------------------*/
10451 /* genGenPointerSet - set value from generic pointer space */
10452 /*-----------------------------------------------------------------*/
10454 genGenPointerSet (operand * right,
10455 operand * result, iCode * ic, iCode * pi)
10458 sym_link *retype = getSpec (operandType (right));
10459 sym_link *letype = getSpec (operandType (result));
10461 D(emitcode ("; genGenPointerSet",""));
10463 aopOp (result, ic, FALSE);
10464 loadDptrFromOperand (result, TRUE);
10466 /* so dptr know contains the address */
10467 aopOp (right, ic, FALSE);
10469 /* if bit then unpack */
10470 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10471 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10474 size = AOP_SIZE (right);
10479 char *l = aopGet (right, offset++, FALSE, FALSE);
10481 emitcode ("lcall", "__gptrput");
10483 emitcode ("inc", "dptr");
10487 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10488 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10489 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10492 freeAsmop (result, NULL, ic, TRUE);
10493 freeAsmop (right, NULL, ic, TRUE);
10496 /*-----------------------------------------------------------------*/
10497 /* genPointerSet - stores the value into a pointer location */
10498 /*-----------------------------------------------------------------*/
10500 genPointerSet (iCode * ic, iCode *pi)
10502 operand *right, *result;
10503 sym_link *type, *etype;
10506 D(emitcode ("; genPointerSet",""));
10508 right = IC_RIGHT (ic);
10509 result = IC_RESULT (ic);
10511 /* depending on the type of pointer we need to
10512 move it to the correct pointer register */
10513 type = operandType (result);
10514 etype = getSpec (type);
10515 /* if left is of type of pointer then it is simple */
10516 if (IS_PTR (type) && !IS_FUNC (type->next))
10518 p_type = DCL_TYPE (type);
10522 /* we have to go by the storage class */
10523 p_type = PTR_TYPE (SPEC_OCLS (etype));
10526 /* special case when cast remat */
10527 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10528 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10529 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10530 type = operandType (result);
10531 p_type = DCL_TYPE (type);
10533 /* now that we have the pointer type we assign
10534 the pointer values */
10540 genNearPointerSet (right, result, ic, pi);
10544 genPagedPointerSet (right, result, ic, pi);
10548 genFarPointerSet (right, result, ic, pi);
10552 genGenPointerSet (right, result, ic, pi);
10556 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10557 "genPointerSet: illegal pointer type");
10562 /*-----------------------------------------------------------------*/
10563 /* genIfx - generate code for Ifx statement */
10564 /*-----------------------------------------------------------------*/
10566 genIfx (iCode * ic, iCode * popIc)
10568 operand *cond = IC_COND (ic);
10572 D(emitcode ("; genIfx",""));
10574 aopOp (cond, ic, FALSE);
10576 /* get the value into acc */
10577 if (AOP_TYPE (cond) != AOP_CRY)
10582 if (AOP(cond)->aopu.aop_dir)
10583 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10585 /* the result is now in the accumulator or a directly addressable bit */
10586 freeAsmop (cond, NULL, ic, TRUE);
10588 /* if there was something to be popped then do it */
10592 /* if the condition is a bit variable */
10594 genIfxJump(ic, dup, NULL, NULL, NULL);
10595 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10596 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10597 else if (isbit && !IS_ITEMP (cond))
10598 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10600 genIfxJump (ic, "a", NULL, NULL, NULL);
10605 /*-----------------------------------------------------------------*/
10606 /* genAddrOf - generates code for address of */
10607 /*-----------------------------------------------------------------*/
10609 genAddrOf (iCode * ic)
10611 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10614 D(emitcode ("; genAddrOf",""));
10616 aopOp (IC_RESULT (ic), ic, FALSE);
10618 /* if the operand is on the stack then we
10619 need to get the stack offset of this
10623 /* if it has an offset then we need to compute
10627 emitcode ("mov", "a,%s", SYM_BP (sym));
10628 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10629 ((char) (sym->stack - _G.nRegsSaved)) :
10630 ((char) sym->stack)) & 0xff);
10631 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10635 /* we can just move _bp */
10636 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10638 /* fill the result with zero */
10639 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10644 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10650 /* object not on stack then we need the name */
10651 size = AOP_SIZE (IC_RESULT (ic));
10656 char s[SDCC_NAME_MAX];
10658 sprintf (s, "#(%s >> %d)",
10662 sprintf (s, "#%s", sym->rname);
10663 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10667 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10671 /*-----------------------------------------------------------------*/
10672 /* genFarFarAssign - assignment when both are in far space */
10673 /*-----------------------------------------------------------------*/
10675 genFarFarAssign (operand * result, operand * right, iCode * ic)
10677 int size = AOP_SIZE (right);
10681 D(emitcode ("; genFarFarAssign",""));
10683 /* first push the right side on to the stack */
10686 l = aopGet (right, offset++, FALSE, FALSE);
10688 emitcode ("push", "acc");
10691 freeAsmop (right, NULL, ic, FALSE);
10692 /* now assign DPTR to result */
10693 aopOp (result, ic, FALSE);
10694 size = AOP_SIZE (result);
10697 emitcode ("pop", "acc");
10698 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10700 freeAsmop (result, NULL, ic, FALSE);
10703 /*-----------------------------------------------------------------*/
10704 /* genAssign - generate code for assignment */
10705 /*-----------------------------------------------------------------*/
10707 genAssign (iCode * ic)
10709 operand *result, *right;
10711 unsigned long lit = 0L;
10713 D(emitcode("; genAssign",""));
10715 result = IC_RESULT (ic);
10716 right = IC_RIGHT (ic);
10718 /* if they are the same */
10719 if (operandsEqu (result, right) &&
10720 !isOperandVolatile (result, FALSE) &&
10721 !isOperandVolatile (right, FALSE))
10724 aopOp (right, ic, FALSE);
10726 /* special case both in far space */
10727 if (AOP_TYPE (right) == AOP_DPTR &&
10728 IS_TRUE_SYMOP (result) &&
10729 isOperandInFarSpace (result))
10732 genFarFarAssign (result, right, ic);
10736 aopOp (result, ic, TRUE);
10738 /* if they are the same registers */
10739 if (sameRegs (AOP (right), AOP (result)) &&
10740 !isOperandVolatile (result, FALSE) &&
10741 !isOperandVolatile (right, FALSE))
10744 /* if the result is a bit */
10745 if (AOP_TYPE (result) == AOP_CRY)
10748 /* if the right size is a literal then
10749 we know what the value is */
10750 if (AOP_TYPE (right) == AOP_LIT)
10752 if (((int) operandLitValue (right)))
10753 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10755 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10759 /* the right is also a bit variable */
10760 if (AOP_TYPE (right) == AOP_CRY)
10762 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10763 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10767 /* we need to or */
10769 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10773 /* bit variables done */
10775 size = AOP_SIZE (result);
10777 if (AOP_TYPE (right) == AOP_LIT)
10778 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10780 (AOP_TYPE (result) != AOP_REG) &&
10781 (AOP_TYPE (right) == AOP_LIT) &&
10782 !IS_FLOAT (operandType (right)) &&
10785 while ((size) && (lit))
10788 aopGet (right, offset, FALSE, FALSE),
10790 isOperandVolatile (result, FALSE));
10795 emitcode ("clr", "a");
10798 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10807 aopGet (right, offset, FALSE, FALSE),
10809 isOperandVolatile (result, FALSE));
10815 freeAsmop (result, NULL, ic, TRUE);
10816 freeAsmop (right, NULL, ic, TRUE);
10819 /*-----------------------------------------------------------------*/
10820 /* genJumpTab - generates code for jump table */
10821 /*-----------------------------------------------------------------*/
10823 genJumpTab (iCode * ic)
10825 symbol *jtab,*jtablo,*jtabhi;
10827 unsigned int count;
10829 D(emitcode ("; genJumpTab",""));
10831 count = elementsInSet( IC_JTLABELS (ic) );
10835 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10836 if the switch argument is in a register.
10837 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10838 /* Peephole may not convert ljmp to sjmp or ret
10839 labelIsReturnOnly & labelInRange must check
10840 currPl->ic->op != JUMPTABLE */
10841 aopOp (IC_JTCOND (ic), ic, FALSE);
10842 /* get the condition into accumulator */
10843 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10845 /* multiply by three */
10846 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
10848 emitcode ("mov", "b,#3");
10849 emitcode ("mul", "ab");
10853 emitcode ("add", "a,acc");
10854 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10856 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10858 jtab = newiTempLabel (NULL);
10859 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10860 emitcode ("jmp", "@a+dptr");
10861 emitcode ("", "%05d$:", jtab->key + 100);
10862 /* now generate the jump labels */
10863 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10864 jtab = setNextItem (IC_JTLABELS (ic)))
10865 emitcode ("ljmp", "%05d$", jtab->key + 100);
10869 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10870 if the switch argument is in a register.
10871 For n>6 this algorithm may be more compact */
10872 jtablo = newiTempLabel (NULL);
10873 jtabhi = newiTempLabel (NULL);
10875 /* get the condition into accumulator.
10876 Using b as temporary storage, if register push/pop is needed */
10877 aopOp (IC_JTCOND (ic), ic, FALSE);
10878 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10879 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10880 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10882 // (MB) what if B is in use???
10883 wassertl(!BINUSE, "B was in use");
10884 emitcode ("mov", "b,%s", l);
10887 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10891 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10892 emitcode ("movc", "a,@a+pc");
10893 emitcode ("push", "acc");
10896 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10897 emitcode ("movc", "a,@a+pc");
10898 emitcode ("push", "acc");
10902 /* this scales up to n<=255, but needs two more bytes
10903 and changes dptr */
10904 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10905 emitcode ("movc", "a,@a+dptr");
10906 emitcode ("push", "acc");
10909 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10910 emitcode ("movc", "a,@a+dptr");
10911 emitcode ("push", "acc");
10914 emitcode ("ret", "");
10916 /* now generate jump table, LSB */
10917 emitcode ("", "%05d$:", jtablo->key + 100);
10918 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10919 jtab = setNextItem (IC_JTLABELS (ic)))
10920 emitcode (".db", "%05d$", jtab->key + 100);
10922 /* now generate jump table, MSB */
10923 emitcode ("", "%05d$:", jtabhi->key + 100);
10924 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10925 jtab = setNextItem (IC_JTLABELS (ic)))
10926 emitcode (".db", "%05d$>>8", jtab->key + 100);
10930 /*-----------------------------------------------------------------*/
10931 /* genCast - gen code for casting */
10932 /*-----------------------------------------------------------------*/
10934 genCast (iCode * ic)
10936 operand *result = IC_RESULT (ic);
10937 sym_link *ctype = operandType (IC_LEFT (ic));
10938 sym_link *rtype = operandType (IC_RIGHT (ic));
10939 operand *right = IC_RIGHT (ic);
10942 D(emitcode("; genCast",""));
10944 /* if they are equivalent then do nothing */
10945 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10948 aopOp (right, ic, FALSE);
10949 aopOp (result, ic, FALSE);
10951 /* if the result is a bit (and not a bitfield) */
10952 // if (AOP_TYPE (result) == AOP_CRY)
10953 if (IS_BIT (OP_SYMBOL (result)->type))
10954 /* not for bitfields */
10956 /* if the right size is a literal then
10957 we know what the value is */
10958 if (AOP_TYPE (right) == AOP_LIT)
10960 if (((int) operandLitValue (right)))
10961 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10963 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10968 /* the right is also a bit variable */
10969 if (AOP_TYPE (right) == AOP_CRY)
10971 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10972 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10976 /* we need to or */
10978 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10983 /* if they are the same size : or less */
10984 if (AOP_SIZE (result) <= AOP_SIZE (right))
10987 /* if they are in the same place */
10988 if (sameRegs (AOP (right), AOP (result)))
10991 /* if they in different places then copy */
10992 size = AOP_SIZE (result);
10997 aopGet (right, offset, FALSE, FALSE),
10999 isOperandVolatile (result, FALSE));
11006 /* if the result is of type pointer */
11007 if (IS_PTR (ctype))
11011 sym_link *type = operandType (right);
11012 sym_link *etype = getSpec (type);
11014 /* pointer to generic pointer */
11015 if (IS_GENPTR (ctype))
11018 p_type = DCL_TYPE (type);
11021 if (SPEC_SCLS(etype)==S_REGISTER) {
11022 // let's assume it is a generic pointer
11025 /* we have to go by the storage class */
11026 p_type = PTR_TYPE (SPEC_OCLS (etype));
11030 /* the first two bytes are known */
11031 size = GPTRSIZE - 1;
11036 aopGet (right, offset, FALSE, FALSE),
11038 isOperandVolatile (result, FALSE));
11041 /* the last byte depending on type */
11043 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11048 // pointerTypeToGPByte will have bitched.
11052 sprintf(gpValStr, "#0x%x", gpVal);
11053 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
11058 /* just copy the pointers */
11059 size = AOP_SIZE (result);
11064 aopGet (right, offset, FALSE, FALSE),
11066 isOperandVolatile (result, FALSE));
11072 /* so we now know that the size of destination is greater
11073 than the size of the source */
11074 /* we move to result for the size of source */
11075 size = AOP_SIZE (right);
11080 aopGet (right, offset, FALSE, FALSE),
11082 isOperandVolatile (result, FALSE));
11086 /* now depending on the sign of the source && destination */
11087 size = AOP_SIZE (result) - AOP_SIZE (right);
11088 /* if unsigned or not an integral type */
11089 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11092 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
11096 /* we need to extend the sign :{ */
11097 char *l = aopGet (right, AOP_SIZE (right) - 1,
11100 emitcode ("rlc", "a");
11101 emitcode ("subb", "a,acc");
11103 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
11106 /* we are done hurray !!!! */
11109 freeAsmop (result, NULL, ic, TRUE);
11110 freeAsmop (right, NULL, ic, TRUE);
11113 /*-----------------------------------------------------------------*/
11114 /* genDjnz - generate decrement & jump if not zero instrucion */
11115 /*-----------------------------------------------------------------*/
11117 genDjnz (iCode * ic, iCode * ifx)
11119 symbol *lbl, *lbl1;
11123 D(emitcode ("; genDjnz",""));
11125 /* if the if condition has a false label
11126 then we cannot save */
11127 if (IC_FALSE (ifx))
11130 /* if the minus is not of the form
11132 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11133 !IS_OP_LITERAL (IC_RIGHT (ic)))
11136 if (operandLitValue (IC_RIGHT (ic)) != 1)
11139 /* if the size of this greater than one then no
11141 if (getSize (operandType (IC_RESULT (ic))) > 1)
11144 /* otherwise we can save BIG */
11145 lbl = newiTempLabel (NULL);
11146 lbl1 = newiTempLabel (NULL);
11148 aopOp (IC_RESULT (ic), ic, FALSE);
11150 if (AOP_NEEDSACC(IC_RESULT(ic)))
11152 /* If the result is accessed indirectly via
11153 * the accumulator, we must explicitly write
11154 * it back after the decrement.
11156 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11158 if (strcmp(rByte, "a"))
11160 /* Something is hopelessly wrong */
11161 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11162 __FILE__, __LINE__);
11163 /* We can just give up; the generated code will be inefficient,
11164 * but what the hey.
11166 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11169 emitcode ("dec", "%s", rByte);
11170 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
11171 emitcode ("jnz", "%05d$", lbl->key + 100);
11173 else if (IS_AOP_PREG (IC_RESULT (ic)))
11175 emitcode ("dec", "%s",
11176 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11177 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11178 emitcode ("jnz", "%05d$", lbl->key + 100);
11182 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11185 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11186 emitcode ("", "%05d$:", lbl->key + 100);
11187 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11188 emitcode ("", "%05d$:", lbl1->key + 100);
11190 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11191 ifx->generated = 1;
11195 /*-----------------------------------------------------------------*/
11196 /* genReceive - generate code for a receive iCode */
11197 /*-----------------------------------------------------------------*/
11199 genReceive (iCode * ic)
11201 int size = getSize (operandType (IC_RESULT (ic)));
11204 D(emitcode ("; genReceive",""));
11206 if (ic->argreg == 1)
11207 { /* first parameter */
11208 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11209 isOperandInPagedSpace (IC_RESULT (ic))) &&
11210 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11211 IS_TRUE_SYMOP (IC_RESULT (ic))))
11214 int receivingA = 0;
11217 for (offset = 0; offset<size; offset++)
11218 if (!strcmp (fReturn[offset], "a"))
11223 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11225 for (offset = size-1; offset>0; offset--)
11226 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11227 emitcode("mov","a,%s", fReturn[0]);
11229 aopOp (IC_RESULT (ic), ic, FALSE);
11231 aopPut (IC_RESULT (ic), "a", offset,
11232 isOperandVolatile (IC_RESULT (ic), FALSE));
11233 for (offset = 1; offset<size; offset++)
11234 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
11235 isOperandVolatile (IC_RESULT (ic), FALSE));
11241 if (getTempRegs(tempRegs, size, ic))
11243 for (offset = 0; offset<size; offset++)
11244 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11245 aopOp (IC_RESULT (ic), ic, FALSE);
11246 for (offset = 0; offset<size; offset++)
11247 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
11248 isOperandVolatile (IC_RESULT (ic), FALSE));
11253 offset = fReturnSizeMCS51 - size;
11256 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11257 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11260 aopOp (IC_RESULT (ic), ic, FALSE);
11261 size = AOP_SIZE (IC_RESULT (ic));
11265 emitcode ("pop", "acc");
11266 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11272 aopOp (IC_RESULT (ic), ic, FALSE);
11274 assignResultValue (IC_RESULT (ic), NULL);
11277 else if (ic->argreg > 12)
11278 { /* bit parameters */
11279 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11281 aopOp (IC_RESULT (ic), ic, FALSE);
11282 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11283 outBitC(IC_RESULT (ic));
11287 { /* other parameters */
11289 aopOp (IC_RESULT (ic), ic, FALSE);
11290 rb1off = ic->argreg;
11293 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11298 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11301 /*-----------------------------------------------------------------*/
11302 /* genDummyRead - generate code for dummy read of volatiles */
11303 /*-----------------------------------------------------------------*/
11305 genDummyRead (iCode * ic)
11310 D(emitcode("; genDummyRead",""));
11312 op = IC_RIGHT (ic);
11313 if (op && IS_SYMOP (op))
11315 aopOp (op, ic, FALSE);
11317 /* if the result is a bit */
11318 if (AOP_TYPE (op) == AOP_CRY)
11319 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11322 /* bit variables done */
11324 size = AOP_SIZE (op);
11328 MOVA (aopGet (op, offset, FALSE, FALSE));
11333 freeAsmop (op, NULL, ic, TRUE);
11337 if (op && IS_SYMOP (op))
11339 aopOp (op, ic, FALSE);
11341 /* if the result is a bit */
11342 if (AOP_TYPE (op) == AOP_CRY)
11343 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11346 /* bit variables done */
11348 size = AOP_SIZE (op);
11352 MOVA (aopGet (op, offset, FALSE, FALSE));
11357 freeAsmop (op, NULL, ic, TRUE);
11361 /*-----------------------------------------------------------------*/
11362 /* genCritical - generate code for start of a critical sequence */
11363 /*-----------------------------------------------------------------*/
11365 genCritical (iCode *ic)
11367 symbol *tlbl = newiTempLabel (NULL);
11369 D(emitcode("; genCritical",""));
11371 if (IC_RESULT (ic))
11373 aopOp (IC_RESULT (ic), ic, TRUE);
11374 aopPut (IC_RESULT (ic), one, 0, 0);
11375 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11376 aopPut (IC_RESULT (ic), zero, 0, 0);
11377 emitcode ("", "%05d$:", (tlbl->key + 100));
11378 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11382 emitcode ("setb", "c");
11383 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11384 emitcode ("clr", "c");
11385 emitcode ("", "%05d$:", (tlbl->key + 100));
11386 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11390 /*-----------------------------------------------------------------*/
11391 /* genEndCritical - generate code for end of a critical sequence */
11392 /*-----------------------------------------------------------------*/
11394 genEndCritical (iCode *ic)
11396 D(emitcode("; genEndCritical",""));
11400 aopOp (IC_RIGHT (ic), ic, FALSE);
11401 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11403 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11404 emitcode ("mov", "ea,c");
11408 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11409 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11410 emitcode ("rrc", "a");
11411 emitcode ("mov", "ea,c");
11413 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11417 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11418 emitcode ("mov", "ea,c");
11422 /*-----------------------------------------------------------------*/
11423 /* gen51Code - generate code for 8051 based controllers */
11424 /*-----------------------------------------------------------------*/
11426 gen51Code (iCode * lic)
11430 /* int cseq = 0; */
11432 _G.currentFunc = NULL;
11433 lineHead = lineCurr = NULL;
11435 /* print the allocation information */
11436 if (allocInfo && currFunc)
11437 printAllocInfo (currFunc, codeOutFile);
11438 /* if debug information required */
11439 if (options.debug && currFunc)
11441 debugFile->writeFunction (currFunc, lic);
11443 /* stack pointer name */
11444 if (options.useXstack)
11450 for (ic = lic; ic; ic = ic->next)
11452 _G.current_iCode = ic;
11454 if (ic->lineno && cln != ic->lineno)
11458 debugFile->writeCLine (ic);
11460 if (!options.noCcodeInAsm) {
11461 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11462 printCLine(ic->filename, ic->lineno));
11467 if (ic->seqPoint && ic->seqPoint != cseq)
11469 emitcode ("", "; sequence point %d", ic->seqPoint);
11470 cseq = ic->seqPoint;
11473 if (options.iCodeInAsm) {
11474 char regsInUse[80];
11478 for (i=0; i<8; i++) {
11479 sprintf (®sInUse[i],
11480 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11483 strcpy (regsInUse, "--------");
11484 for (i=0; i < 8; i++) {
11485 if (bitVectBitValue (ic->rMask, i))
11487 int offset = regs8051[i].offset;
11488 regsInUse[offset] = offset + '0'; /* show rMask */
11492 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11494 /* if the result is marked as
11495 spilt and rematerializable or code for
11496 this has already been generated then
11498 if (resultRemat (ic) || ic->generated)
11501 /* depending on the operation */
11521 /* IPOP happens only when trying to restore a
11522 spilt live range, if there is an ifx statement
11523 following this pop then the if statement might
11524 be using some of the registers being popped which
11525 would destory the contents of the register so
11526 we need to check for this condition and handle it */
11528 ic->next->op == IFX &&
11529 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11530 genIfx (ic->next, ic);
11548 genEndFunction (ic);
11568 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11585 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11589 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11596 /* note these two are xlated by algebraic equivalence
11597 during parsing SDCC.y */
11598 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11599 "got '>=' or '<=' shouldn't have come here");
11603 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11615 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11619 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11623 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11659 genRightShift (ic);
11662 case GET_VALUE_AT_ADDRESS:
11664 hasInc (IC_LEFT (ic), ic,
11665 getSize (operandType (IC_RESULT (ic)))),
11666 ifxForOp (IC_RESULT (ic), ic) );
11670 if (POINTER_SET (ic))
11671 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11697 addSet (&_G.sendSet, ic);
11700 case DUMMY_READ_VOLATILE:
11709 genEndCritical (ic);
11721 _G.current_iCode = NULL;
11723 /* now we are ready to call the
11724 peep hole optimizer */
11725 if (!options.nopeep)
11726 peepHole (&lineHead);
11728 /* now do the actual printing */
11729 printLine (lineHead, codeOutFile);