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);
9873 emitcode ("clr", "a");
9874 emitcode ("movc", "a,@a+dptr");
9876 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9877 emitcode ("inc", "dptr");
9881 emitcode ("mov", "a,#0x%02x", offset);
9882 emitcode ("movc", "a,@a+dptr");
9884 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9889 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9891 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9892 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9896 if (ifx && !ifx->generated)
9898 genIfxJump (ifx, "a", left, NULL, result);
9901 freeAsmop (result, NULL, ic, TRUE);
9902 freeAsmop (left, NULL, ic, TRUE);
9905 /*-----------------------------------------------------------------*/
9906 /* genGenPointerGet - gget value from generic pointer space */
9907 /*-----------------------------------------------------------------*/
9909 genGenPointerGet (operand * left,
9910 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9913 sym_link *retype = getSpec (operandType (result));
9915 D(emitcode ("; genGenPointerGet",""));
9917 aopOp (left, ic, FALSE);
9918 loadDptrFromOperand (left, TRUE);
9920 /* so dptr know contains the address */
9921 aopOp (result, ic, FALSE);
9923 /* if bit then unpack */
9924 if (IS_BITFIELD (retype))
9925 genUnpackBits (result, "dptr", GPOINTER, ifx);
9928 size = AOP_SIZE (result);
9933 emitcode ("lcall", "__gptrget");
9935 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9937 emitcode ("inc", "dptr");
9941 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9943 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9944 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9948 if (ifx && !ifx->generated)
9950 genIfxJump (ifx, "a", left, NULL, result);
9953 freeAsmop (result, NULL, ic, TRUE);
9954 freeAsmop (left, NULL, ic, TRUE);
9957 /*-----------------------------------------------------------------*/
9958 /* genPointerGet - generate code for pointer get */
9959 /*-----------------------------------------------------------------*/
9961 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9963 operand *left, *result;
9964 sym_link *type, *etype;
9967 D(emitcode ("; genPointerGet",""));
9969 left = IC_LEFT (ic);
9970 result = IC_RESULT (ic);
9972 if (getSize (operandType (result))>1)
9975 /* depending on the type of pointer we need to
9976 move it to the correct pointer register */
9977 type = operandType (left);
9978 etype = getSpec (type);
9979 /* if left is of type of pointer then it is simple */
9980 if (IS_PTR (type) && !IS_FUNC (type->next))
9981 p_type = DCL_TYPE (type);
9984 /* we have to go by the storage class */
9985 p_type = PTR_TYPE (SPEC_OCLS (etype));
9988 /* special case when cast remat */
9989 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9990 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9991 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9992 type = operandType (left);
9993 p_type = DCL_TYPE (type);
9995 /* now that we have the pointer type we assign
9996 the pointer values */
10002 genNearPointerGet (left, result, ic, pi, ifx);
10006 genPagedPointerGet (left, result, ic, pi, ifx);
10010 genFarPointerGet (left, result, ic, pi, ifx);
10014 genCodePointerGet (left, result, ic, pi, ifx);
10018 genGenPointerGet (left, result, ic, pi, ifx);
10026 /*-----------------------------------------------------------------*/
10027 /* genPackBits - generates code for packed bit storage */
10028 /*-----------------------------------------------------------------*/
10030 genPackBits (sym_link * etype,
10032 char *rname, int p_type)
10034 int offset = 0; /* source byte offset */
10035 int rlen = 0; /* remaining bitfield length */
10036 int blen; /* bitfield length */
10037 int bstr; /* bitfield starting bit within byte */
10038 int litval; /* source literal value (if AOP_LIT) */
10039 unsigned char mask; /* bitmask within current byte */
10041 D(emitcode ("; genPackBits",""));
10043 blen = SPEC_BLEN (etype);
10044 bstr = SPEC_BSTR (etype);
10046 /* If the bitfield length is less than a byte */
10049 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10050 (unsigned char) (0xFF >> (8 - bstr)));
10052 if (AOP_TYPE (right) == AOP_LIT)
10054 /* Case with a bitfield length <8 and literal source
10056 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10058 litval &= (~mask) & 0xff;
10059 emitPtrByteGet (rname, p_type, FALSE);
10060 if ((mask|litval)!=0xff)
10061 emitcode ("anl","a,#0x%02x", mask);
10063 emitcode ("orl","a,#0x%02x", litval);
10067 if ((blen==1) && (p_type!=GPOINTER))
10069 /* Case with a bitfield length == 1 and no generic pointer
10071 if (AOP_TYPE (right) == AOP_CRY)
10072 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10075 MOVA (aopGet (right, 0, FALSE, FALSE));
10076 emitcode ("rrc","a");
10078 emitPtrByteGet (rname, p_type, FALSE);
10079 emitcode ("mov","acc.%d,c",bstr);
10084 /* Case with a bitfield length < 8 and arbitrary source
10086 MOVA (aopGet (right, 0, FALSE, FALSE));
10087 /* shift and mask source value */
10089 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10091 pushedB = pushB ();
10092 /* transfer A to B and get next byte */
10093 emitPtrByteGet (rname, p_type, TRUE);
10095 emitcode ("anl", "a,#0x%02x", mask);
10096 emitcode ("orl", "a,b");
10097 if (p_type == GPOINTER)
10098 emitcode ("pop", "b");
10104 emitPtrByteSet (rname, p_type, "a");
10108 /* Bit length is greater than 7 bits. In this case, copy */
10109 /* all except the partial byte at the end */
10110 for (rlen=blen;rlen>=8;rlen-=8)
10112 emitPtrByteSet (rname, p_type,
10113 aopGet (right, offset++, FALSE, TRUE) );
10115 emitcode ("inc", "%s", rname);
10118 /* If there was a partial byte at the end */
10121 mask = (((unsigned char) -1 << rlen) & 0xff);
10123 if (AOP_TYPE (right) == AOP_LIT)
10125 /* Case with partial byte and literal source
10127 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10128 litval >>= (blen-rlen);
10129 litval &= (~mask) & 0xff;
10130 emitPtrByteGet (rname, p_type, FALSE);
10131 if ((mask|litval)!=0xff)
10132 emitcode ("anl","a,#0x%02x", mask);
10134 emitcode ("orl","a,#0x%02x", litval);
10139 /* Case with partial byte and arbitrary source
10141 MOVA (aopGet (right, offset++, FALSE, FALSE));
10142 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10144 pushedB = pushB ();
10145 /* transfer A to B and get next byte */
10146 emitPtrByteGet (rname, p_type, TRUE);
10148 emitcode ("anl", "a,#0x%02x", mask);
10149 emitcode ("orl", "a,b");
10150 if (p_type == GPOINTER)
10151 emitcode ("pop", "b");
10155 emitPtrByteSet (rname, p_type, "a");
10161 /*-----------------------------------------------------------------*/
10162 /* genDataPointerSet - remat pointer to data space */
10163 /*-----------------------------------------------------------------*/
10165 genDataPointerSet (operand * right,
10169 int size, offset = 0;
10170 char *l, buffer[256];
10172 D(emitcode ("; genDataPointerSet",""));
10174 aopOp (right, ic, FALSE);
10176 l = aopGet (result, 0, FALSE, TRUE);
10177 size = AOP_SIZE (right);
10181 sprintf (buffer, "(%s + %d)", l + 1, offset);
10183 sprintf (buffer, "%s", l + 1);
10184 emitcode ("mov", "%s,%s", buffer,
10185 aopGet (right, offset++, FALSE, FALSE));
10188 freeAsmop (result, NULL, ic, TRUE);
10189 freeAsmop (right, NULL, ic, TRUE);
10192 /*-----------------------------------------------------------------*/
10193 /* genNearPointerSet - emitcode for near pointer put */
10194 /*-----------------------------------------------------------------*/
10196 genNearPointerSet (operand * right,
10204 sym_link *retype, *letype;
10205 sym_link *ptype = operandType (result);
10207 D(emitcode ("; genNearPointerSet",""));
10209 retype = getSpec (operandType (right));
10210 letype = getSpec (ptype);
10211 aopOp (result, ic, FALSE);
10213 /* if the result is rematerializable &
10214 in data space & not a bit variable */
10215 if (AOP_TYPE (result) == AOP_IMMD &&
10216 DCL_TYPE (ptype) == POINTER &&
10217 !IS_BITVAR (retype) &&
10218 !IS_BITVAR (letype))
10220 genDataPointerSet (right, result, ic);
10224 /* if the value is already in a pointer register
10225 then don't need anything more */
10226 if (!AOP_INPREG (AOP (result)))
10229 //AOP_TYPE (result) == AOP_STK
10230 IS_AOP_PREG(result)
10233 // Aha, it is a pointer, just in disguise.
10234 rname = aopGet (result, 0, FALSE, FALSE);
10237 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10238 __FILE__, __LINE__);
10243 emitcode ("mov", "a%s,%s", rname + 1, rname);
10244 rname++; // skip the '@'.
10249 /* otherwise get a free pointer register */
10250 aop = newAsmop (0);
10251 preg = getFreePtr (ic, &aop, FALSE);
10252 emitcode ("mov", "%s,%s",
10254 aopGet (result, 0, FALSE, TRUE));
10255 rname = preg->name;
10260 rname = aopGet (result, 0, FALSE, FALSE);
10263 aopOp (right, ic, FALSE);
10265 /* if bitfield then unpack the bits */
10266 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10267 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10270 /* we have can just get the values */
10271 int size = AOP_SIZE (right);
10276 l = aopGet (right, offset, FALSE, TRUE);
10280 emitcode ("mov", "@%s,a", rname);
10283 emitcode ("mov", "@%s,%s", rname, l);
10285 emitcode ("inc", "%s", rname);
10290 /* now some housekeeping stuff */
10291 if (aop) /* we had to allocate for this iCode */
10294 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10295 freeAsmop (NULL, aop, ic, TRUE);
10299 /* we did not allocate which means left
10300 already in a pointer register, then
10301 if size > 0 && this could be used again
10302 we have to point it back to where it
10304 if ((AOP_SIZE (right) > 1 &&
10305 !OP_SYMBOL (result)->remat &&
10306 (OP_SYMBOL (result)->liveTo > ic->seq ||
10310 int size = AOP_SIZE (right) - 1;
10312 emitcode ("dec", "%s", rname);
10317 if (pi) pi->generated = 1;
10318 freeAsmop (result, NULL, ic, TRUE);
10319 freeAsmop (right, NULL, ic, TRUE);
10322 /*-----------------------------------------------------------------*/
10323 /* genPagedPointerSet - emitcode for Paged pointer put */
10324 /*-----------------------------------------------------------------*/
10326 genPagedPointerSet (operand * right,
10334 sym_link *retype, *letype;
10336 D(emitcode ("; genPagedPointerSet",""));
10338 retype = getSpec (operandType (right));
10339 letype = getSpec (operandType (result));
10341 aopOp (result, ic, FALSE);
10343 /* if the value is already in a pointer register
10344 then don't need anything more */
10345 if (!AOP_INPREG (AOP (result)))
10347 /* otherwise get a free pointer register */
10348 aop = newAsmop (0);
10349 preg = getFreePtr (ic, &aop, FALSE);
10350 emitcode ("mov", "%s,%s",
10352 aopGet (result, 0, FALSE, TRUE));
10353 rname = preg->name;
10356 rname = aopGet (result, 0, FALSE, FALSE);
10358 aopOp (right, ic, FALSE);
10360 /* if bitfield then unpack the bits */
10361 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10362 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10365 /* we have can just get the values */
10366 int size = AOP_SIZE (right);
10371 l = aopGet (right, offset, FALSE, TRUE);
10374 emitcode ("movx", "@%s,a", rname);
10377 emitcode ("inc", "%s", rname);
10383 /* now some housekeeping stuff */
10384 if (aop) /* we had to allocate for this iCode */
10387 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10388 freeAsmop (NULL, aop, ic, TRUE);
10392 /* we did not allocate which means left
10393 already in a pointer register, then
10394 if size > 0 && this could be used again
10395 we have to point it back to where it
10397 if (AOP_SIZE (right) > 1 &&
10398 !OP_SYMBOL (result)->remat &&
10399 (OP_SYMBOL (result)->liveTo > ic->seq ||
10402 int size = AOP_SIZE (right) - 1;
10404 emitcode ("dec", "%s", rname);
10409 if (pi) pi->generated = 1;
10410 freeAsmop (result, NULL, ic, TRUE);
10411 freeAsmop (right, NULL, ic, TRUE);
10414 /*-----------------------------------------------------------------*/
10415 /* genFarPointerSet - set value from far space */
10416 /*-----------------------------------------------------------------*/
10418 genFarPointerSet (operand * right,
10419 operand * result, iCode * ic, iCode * pi)
10422 sym_link *retype = getSpec (operandType (right));
10423 sym_link *letype = getSpec (operandType (result));
10425 D(emitcode ("; genFarPointerSet",""));
10427 aopOp (result, ic, FALSE);
10428 loadDptrFromOperand (result, FALSE);
10430 /* so dptr know contains the address */
10431 aopOp (right, ic, FALSE);
10433 /* if bit then unpack */
10434 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10435 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10438 size = AOP_SIZE (right);
10443 char *l = aopGet (right, offset++, FALSE, FALSE);
10445 emitcode ("movx", "@dptr,a");
10447 emitcode ("inc", "dptr");
10450 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10451 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10452 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10455 freeAsmop (result, NULL, ic, TRUE);
10456 freeAsmop (right, NULL, ic, TRUE);
10459 /*-----------------------------------------------------------------*/
10460 /* genGenPointerSet - set value from generic pointer space */
10461 /*-----------------------------------------------------------------*/
10463 genGenPointerSet (operand * right,
10464 operand * result, iCode * ic, iCode * pi)
10467 sym_link *retype = getSpec (operandType (right));
10468 sym_link *letype = getSpec (operandType (result));
10470 D(emitcode ("; genGenPointerSet",""));
10472 aopOp (result, ic, FALSE);
10473 loadDptrFromOperand (result, TRUE);
10475 /* so dptr know contains the address */
10476 aopOp (right, ic, FALSE);
10478 /* if bit then unpack */
10479 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10480 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10483 size = AOP_SIZE (right);
10488 char *l = aopGet (right, offset++, FALSE, FALSE);
10490 emitcode ("lcall", "__gptrput");
10492 emitcode ("inc", "dptr");
10496 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10497 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10498 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10501 freeAsmop (result, NULL, ic, TRUE);
10502 freeAsmop (right, NULL, ic, TRUE);
10505 /*-----------------------------------------------------------------*/
10506 /* genPointerSet - stores the value into a pointer location */
10507 /*-----------------------------------------------------------------*/
10509 genPointerSet (iCode * ic, iCode *pi)
10511 operand *right, *result;
10512 sym_link *type, *etype;
10515 D(emitcode ("; genPointerSet",""));
10517 right = IC_RIGHT (ic);
10518 result = IC_RESULT (ic);
10520 /* depending on the type of pointer we need to
10521 move it to the correct pointer register */
10522 type = operandType (result);
10523 etype = getSpec (type);
10524 /* if left is of type of pointer then it is simple */
10525 if (IS_PTR (type) && !IS_FUNC (type->next))
10527 p_type = DCL_TYPE (type);
10531 /* we have to go by the storage class */
10532 p_type = PTR_TYPE (SPEC_OCLS (etype));
10535 /* special case when cast remat */
10536 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10537 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10538 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10539 type = operandType (result);
10540 p_type = DCL_TYPE (type);
10542 /* now that we have the pointer type we assign
10543 the pointer values */
10549 genNearPointerSet (right, result, ic, pi);
10553 genPagedPointerSet (right, result, ic, pi);
10557 genFarPointerSet (right, result, ic, pi);
10561 genGenPointerSet (right, result, ic, pi);
10565 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10566 "genPointerSet: illegal pointer type");
10571 /*-----------------------------------------------------------------*/
10572 /* genIfx - generate code for Ifx statement */
10573 /*-----------------------------------------------------------------*/
10575 genIfx (iCode * ic, iCode * popIc)
10577 operand *cond = IC_COND (ic);
10581 D(emitcode ("; genIfx",""));
10583 aopOp (cond, ic, FALSE);
10585 /* get the value into acc */
10586 if (AOP_TYPE (cond) != AOP_CRY)
10591 if (AOP(cond)->aopu.aop_dir)
10592 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10594 /* the result is now in the accumulator or a directly addressable bit */
10595 freeAsmop (cond, NULL, ic, TRUE);
10597 /* if there was something to be popped then do it */
10601 /* if the condition is a bit variable */
10603 genIfxJump(ic, dup, NULL, NULL, NULL);
10604 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10605 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10606 else if (isbit && !IS_ITEMP (cond))
10607 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10609 genIfxJump (ic, "a", NULL, NULL, NULL);
10614 /*-----------------------------------------------------------------*/
10615 /* genAddrOf - generates code for address of */
10616 /*-----------------------------------------------------------------*/
10618 genAddrOf (iCode * ic)
10620 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10623 D(emitcode ("; genAddrOf",""));
10625 aopOp (IC_RESULT (ic), ic, FALSE);
10627 /* if the operand is on the stack then we
10628 need to get the stack offset of this
10632 /* if it has an offset then we need to compute
10636 emitcode ("mov", "a,%s", SYM_BP (sym));
10637 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10638 ((char) (sym->stack - _G.nRegsSaved)) :
10639 ((char) sym->stack)) & 0xff);
10640 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10644 /* we can just move _bp */
10645 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10647 /* fill the result with zero */
10648 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10653 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10659 /* object not on stack then we need the name */
10660 size = AOP_SIZE (IC_RESULT (ic));
10665 char s[SDCC_NAME_MAX];
10667 sprintf (s, "#(%s >> %d)",
10671 sprintf (s, "#%s", sym->rname);
10672 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10676 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10680 /*-----------------------------------------------------------------*/
10681 /* genFarFarAssign - assignment when both are in far space */
10682 /*-----------------------------------------------------------------*/
10684 genFarFarAssign (operand * result, operand * right, iCode * ic)
10686 int size = AOP_SIZE (right);
10690 D(emitcode ("; genFarFarAssign",""));
10692 /* first push the right side on to the stack */
10695 l = aopGet (right, offset++, FALSE, FALSE);
10697 emitcode ("push", "acc");
10700 freeAsmop (right, NULL, ic, FALSE);
10701 /* now assign DPTR to result */
10702 aopOp (result, ic, FALSE);
10703 size = AOP_SIZE (result);
10706 emitcode ("pop", "acc");
10707 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10709 freeAsmop (result, NULL, ic, FALSE);
10712 /*-----------------------------------------------------------------*/
10713 /* genAssign - generate code for assignment */
10714 /*-----------------------------------------------------------------*/
10716 genAssign (iCode * ic)
10718 operand *result, *right;
10720 unsigned long lit = 0L;
10722 D(emitcode("; genAssign",""));
10724 result = IC_RESULT (ic);
10725 right = IC_RIGHT (ic);
10727 /* if they are the same */
10728 if (operandsEqu (result, right) &&
10729 !isOperandVolatile (result, FALSE) &&
10730 !isOperandVolatile (right, FALSE))
10733 aopOp (right, ic, FALSE);
10735 /* special case both in far space */
10736 if (AOP_TYPE (right) == AOP_DPTR &&
10737 IS_TRUE_SYMOP (result) &&
10738 isOperandInFarSpace (result))
10741 genFarFarAssign (result, right, ic);
10745 aopOp (result, ic, TRUE);
10747 /* if they are the same registers */
10748 if (sameRegs (AOP (right), AOP (result)) &&
10749 !isOperandVolatile (result, FALSE) &&
10750 !isOperandVolatile (right, FALSE))
10753 /* if the result is a bit */
10754 if (AOP_TYPE (result) == AOP_CRY)
10757 /* if the right size is a literal then
10758 we know what the value is */
10759 if (AOP_TYPE (right) == AOP_LIT)
10761 if (((int) operandLitValue (right)))
10762 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10764 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10768 /* the right is also a bit variable */
10769 if (AOP_TYPE (right) == AOP_CRY)
10771 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10772 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10776 /* we need to or */
10778 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10782 /* bit variables done */
10784 size = AOP_SIZE (result);
10786 if (AOP_TYPE (right) == AOP_LIT)
10787 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10789 (AOP_TYPE (result) != AOP_REG) &&
10790 (AOP_TYPE (right) == AOP_LIT) &&
10791 !IS_FLOAT (operandType (right)) &&
10794 while ((size) && (lit))
10797 aopGet (right, offset, FALSE, FALSE),
10799 isOperandVolatile (result, FALSE));
10804 emitcode ("clr", "a");
10807 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10816 aopGet (right, offset, FALSE, FALSE),
10818 isOperandVolatile (result, FALSE));
10824 freeAsmop (result, NULL, ic, TRUE);
10825 freeAsmop (right, NULL, ic, TRUE);
10828 /*-----------------------------------------------------------------*/
10829 /* genJumpTab - generates code for jump table */
10830 /*-----------------------------------------------------------------*/
10832 genJumpTab (iCode * ic)
10834 symbol *jtab,*jtablo,*jtabhi;
10836 unsigned int count;
10838 D(emitcode ("; genJumpTab",""));
10840 count = elementsInSet( IC_JTLABELS (ic) );
10844 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10845 if the switch argument is in a register.
10846 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10847 /* Peephole may not convert ljmp to sjmp or ret
10848 labelIsReturnOnly & labelInRange must check
10849 currPl->ic->op != JUMPTABLE */
10850 aopOp (IC_JTCOND (ic), ic, FALSE);
10851 /* get the condition into accumulator */
10852 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10854 /* multiply by three */
10855 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
10857 emitcode ("mov", "b,#3");
10858 emitcode ("mul", "ab");
10862 emitcode ("add", "a,acc");
10863 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10865 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10867 jtab = newiTempLabel (NULL);
10868 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10869 emitcode ("jmp", "@a+dptr");
10870 emitcode ("", "%05d$:", jtab->key + 100);
10871 /* now generate the jump labels */
10872 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10873 jtab = setNextItem (IC_JTLABELS (ic)))
10874 emitcode ("ljmp", "%05d$", jtab->key + 100);
10878 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10879 if the switch argument is in a register.
10880 For n>6 this algorithm may be more compact */
10881 jtablo = newiTempLabel (NULL);
10882 jtabhi = newiTempLabel (NULL);
10884 /* get the condition into accumulator.
10885 Using b as temporary storage, if register push/pop is needed */
10886 aopOp (IC_JTCOND (ic), ic, FALSE);
10887 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10888 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10889 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10891 // (MB) what if B is in use???
10892 wassertl(!BINUSE, "B was in use");
10893 emitcode ("mov", "b,%s", l);
10896 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10900 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10901 emitcode ("movc", "a,@a+pc");
10902 emitcode ("push", "acc");
10905 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10906 emitcode ("movc", "a,@a+pc");
10907 emitcode ("push", "acc");
10911 /* this scales up to n<=255, but needs two more bytes
10912 and changes dptr */
10913 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10914 emitcode ("movc", "a,@a+dptr");
10915 emitcode ("push", "acc");
10918 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10919 emitcode ("movc", "a,@a+dptr");
10920 emitcode ("push", "acc");
10923 emitcode ("ret", "");
10925 /* now generate jump table, LSB */
10926 emitcode ("", "%05d$:", jtablo->key + 100);
10927 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10928 jtab = setNextItem (IC_JTLABELS (ic)))
10929 emitcode (".db", "%05d$", jtab->key + 100);
10931 /* now generate jump table, MSB */
10932 emitcode ("", "%05d$:", jtabhi->key + 100);
10933 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10934 jtab = setNextItem (IC_JTLABELS (ic)))
10935 emitcode (".db", "%05d$>>8", jtab->key + 100);
10939 /*-----------------------------------------------------------------*/
10940 /* genCast - gen code for casting */
10941 /*-----------------------------------------------------------------*/
10943 genCast (iCode * ic)
10945 operand *result = IC_RESULT (ic);
10946 sym_link *ctype = operandType (IC_LEFT (ic));
10947 sym_link *rtype = operandType (IC_RIGHT (ic));
10948 operand *right = IC_RIGHT (ic);
10951 D(emitcode("; genCast",""));
10953 /* if they are equivalent then do nothing */
10954 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10957 aopOp (right, ic, FALSE);
10958 aopOp (result, ic, FALSE);
10960 /* if the result is a bit (and not a bitfield) */
10961 // if (AOP_TYPE (result) == AOP_CRY)
10962 if (IS_BIT (OP_SYMBOL (result)->type))
10963 /* not for bitfields */
10965 /* if the right size is a literal then
10966 we know what the value is */
10967 if (AOP_TYPE (right) == AOP_LIT)
10969 if (((int) operandLitValue (right)))
10970 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10972 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10977 /* the right is also a bit variable */
10978 if (AOP_TYPE (right) == AOP_CRY)
10980 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10981 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10985 /* we need to or */
10987 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10992 /* if they are the same size : or less */
10993 if (AOP_SIZE (result) <= AOP_SIZE (right))
10996 /* if they are in the same place */
10997 if (sameRegs (AOP (right), AOP (result)))
11000 /* if they in different places then copy */
11001 size = AOP_SIZE (result);
11006 aopGet (right, offset, FALSE, FALSE),
11008 isOperandVolatile (result, FALSE));
11015 /* if the result is of type pointer */
11016 if (IS_PTR (ctype))
11020 sym_link *type = operandType (right);
11021 sym_link *etype = getSpec (type);
11023 /* pointer to generic pointer */
11024 if (IS_GENPTR (ctype))
11027 p_type = DCL_TYPE (type);
11030 if (SPEC_SCLS(etype)==S_REGISTER) {
11031 // let's assume it is a generic pointer
11034 /* we have to go by the storage class */
11035 p_type = PTR_TYPE (SPEC_OCLS (etype));
11039 /* the first two bytes are known */
11040 size = GPTRSIZE - 1;
11045 aopGet (right, offset, FALSE, FALSE),
11047 isOperandVolatile (result, FALSE));
11050 /* the last byte depending on type */
11052 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11057 // pointerTypeToGPByte will have bitched.
11061 sprintf(gpValStr, "#0x%x", gpVal);
11062 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
11067 /* just copy the pointers */
11068 size = AOP_SIZE (result);
11073 aopGet (right, offset, FALSE, FALSE),
11075 isOperandVolatile (result, FALSE));
11081 /* so we now know that the size of destination is greater
11082 than the size of the source */
11083 /* we move to result for the size of source */
11084 size = AOP_SIZE (right);
11089 aopGet (right, offset, FALSE, FALSE),
11091 isOperandVolatile (result, FALSE));
11095 /* now depending on the sign of the source && destination */
11096 size = AOP_SIZE (result) - AOP_SIZE (right);
11097 /* if unsigned or not an integral type */
11098 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11101 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
11105 /* we need to extend the sign :{ */
11106 char *l = aopGet (right, AOP_SIZE (right) - 1,
11109 emitcode ("rlc", "a");
11110 emitcode ("subb", "a,acc");
11112 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
11115 /* we are done hurray !!!! */
11118 freeAsmop (result, NULL, ic, TRUE);
11119 freeAsmop (right, NULL, ic, TRUE);
11122 /*-----------------------------------------------------------------*/
11123 /* genDjnz - generate decrement & jump if not zero instrucion */
11124 /*-----------------------------------------------------------------*/
11126 genDjnz (iCode * ic, iCode * ifx)
11128 symbol *lbl, *lbl1;
11132 D(emitcode ("; genDjnz",""));
11134 /* if the if condition has a false label
11135 then we cannot save */
11136 if (IC_FALSE (ifx))
11139 /* if the minus is not of the form
11141 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11142 !IS_OP_LITERAL (IC_RIGHT (ic)))
11145 if (operandLitValue (IC_RIGHT (ic)) != 1)
11148 /* if the size of this greater than one then no
11150 if (getSize (operandType (IC_RESULT (ic))) > 1)
11153 /* otherwise we can save BIG */
11154 lbl = newiTempLabel (NULL);
11155 lbl1 = newiTempLabel (NULL);
11157 aopOp (IC_RESULT (ic), ic, FALSE);
11159 if (AOP_NEEDSACC(IC_RESULT(ic)))
11161 /* If the result is accessed indirectly via
11162 * the accumulator, we must explicitly write
11163 * it back after the decrement.
11165 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11167 if (strcmp(rByte, "a"))
11169 /* Something is hopelessly wrong */
11170 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11171 __FILE__, __LINE__);
11172 /* We can just give up; the generated code will be inefficient,
11173 * but what the hey.
11175 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11178 emitcode ("dec", "%s", rByte);
11179 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
11180 emitcode ("jnz", "%05d$", lbl->key + 100);
11182 else if (IS_AOP_PREG (IC_RESULT (ic)))
11184 emitcode ("dec", "%s",
11185 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11186 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11187 emitcode ("jnz", "%05d$", lbl->key + 100);
11191 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11194 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11195 emitcode ("", "%05d$:", lbl->key + 100);
11196 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11197 emitcode ("", "%05d$:", lbl1->key + 100);
11199 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11200 ifx->generated = 1;
11204 /*-----------------------------------------------------------------*/
11205 /* genReceive - generate code for a receive iCode */
11206 /*-----------------------------------------------------------------*/
11208 genReceive (iCode * ic)
11210 int size = getSize (operandType (IC_RESULT (ic)));
11213 D(emitcode ("; genReceive",""));
11215 if (ic->argreg == 1)
11216 { /* first parameter */
11217 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11218 isOperandInPagedSpace (IC_RESULT (ic))) &&
11219 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11220 IS_TRUE_SYMOP (IC_RESULT (ic))))
11223 int receivingA = 0;
11226 for (offset = 0; offset<size; offset++)
11227 if (!strcmp (fReturn[offset], "a"))
11232 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11234 for (offset = size-1; offset>0; offset--)
11235 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11236 emitcode("mov","a,%s", fReturn[0]);
11238 aopOp (IC_RESULT (ic), ic, FALSE);
11240 aopPut (IC_RESULT (ic), "a", offset,
11241 isOperandVolatile (IC_RESULT (ic), FALSE));
11242 for (offset = 1; offset<size; offset++)
11243 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
11244 isOperandVolatile (IC_RESULT (ic), FALSE));
11250 if (getTempRegs(tempRegs, size, ic))
11252 for (offset = 0; offset<size; offset++)
11253 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11254 aopOp (IC_RESULT (ic), ic, FALSE);
11255 for (offset = 0; offset<size; offset++)
11256 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
11257 isOperandVolatile (IC_RESULT (ic), FALSE));
11262 offset = fReturnSizeMCS51 - size;
11265 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11266 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11269 aopOp (IC_RESULT (ic), ic, FALSE);
11270 size = AOP_SIZE (IC_RESULT (ic));
11274 emitcode ("pop", "acc");
11275 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11281 aopOp (IC_RESULT (ic), ic, FALSE);
11283 assignResultValue (IC_RESULT (ic), NULL);
11286 else if (ic->argreg > 12)
11287 { /* bit parameters */
11288 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11290 aopOp (IC_RESULT (ic), ic, FALSE);
11291 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11292 outBitC(IC_RESULT (ic));
11296 { /* other parameters */
11298 aopOp (IC_RESULT (ic), ic, FALSE);
11299 rb1off = ic->argreg;
11302 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11307 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11310 /*-----------------------------------------------------------------*/
11311 /* genDummyRead - generate code for dummy read of volatiles */
11312 /*-----------------------------------------------------------------*/
11314 genDummyRead (iCode * ic)
11319 D(emitcode("; genDummyRead",""));
11321 op = IC_RIGHT (ic);
11322 if (op && IS_SYMOP (op))
11324 aopOp (op, ic, FALSE);
11326 /* if the result is a bit */
11327 if (AOP_TYPE (op) == AOP_CRY)
11328 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11331 /* bit variables done */
11333 size = AOP_SIZE (op);
11337 MOVA (aopGet (op, offset, FALSE, FALSE));
11342 freeAsmop (op, NULL, ic, TRUE);
11346 if (op && IS_SYMOP (op))
11348 aopOp (op, ic, FALSE);
11350 /* if the result is a bit */
11351 if (AOP_TYPE (op) == AOP_CRY)
11352 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11355 /* bit variables done */
11357 size = AOP_SIZE (op);
11361 MOVA (aopGet (op, offset, FALSE, FALSE));
11366 freeAsmop (op, NULL, ic, TRUE);
11370 /*-----------------------------------------------------------------*/
11371 /* genCritical - generate code for start of a critical sequence */
11372 /*-----------------------------------------------------------------*/
11374 genCritical (iCode *ic)
11376 symbol *tlbl = newiTempLabel (NULL);
11378 D(emitcode("; genCritical",""));
11380 if (IC_RESULT (ic))
11382 aopOp (IC_RESULT (ic), ic, TRUE);
11383 aopPut (IC_RESULT (ic), one, 0, 0);
11384 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11385 aopPut (IC_RESULT (ic), zero, 0, 0);
11386 emitcode ("", "%05d$:", (tlbl->key + 100));
11387 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11391 emitcode ("setb", "c");
11392 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11393 emitcode ("clr", "c");
11394 emitcode ("", "%05d$:", (tlbl->key + 100));
11395 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11399 /*-----------------------------------------------------------------*/
11400 /* genEndCritical - generate code for end of a critical sequence */
11401 /*-----------------------------------------------------------------*/
11403 genEndCritical (iCode *ic)
11405 D(emitcode("; genEndCritical",""));
11409 aopOp (IC_RIGHT (ic), ic, FALSE);
11410 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11412 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11413 emitcode ("mov", "ea,c");
11417 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11418 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11419 emitcode ("rrc", "a");
11420 emitcode ("mov", "ea,c");
11422 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11426 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11427 emitcode ("mov", "ea,c");
11431 /*-----------------------------------------------------------------*/
11432 /* gen51Code - generate code for 8051 based controllers */
11433 /*-----------------------------------------------------------------*/
11435 gen51Code (iCode * lic)
11439 /* int cseq = 0; */
11441 _G.currentFunc = NULL;
11442 lineHead = lineCurr = NULL;
11444 /* print the allocation information */
11445 if (allocInfo && currFunc)
11446 printAllocInfo (currFunc, codeOutFile);
11447 /* if debug information required */
11448 if (options.debug && currFunc)
11450 debugFile->writeFunction (currFunc, lic);
11452 /* stack pointer name */
11453 if (options.useXstack)
11459 for (ic = lic; ic; ic = ic->next)
11461 _G.current_iCode = ic;
11463 if (ic->lineno && cln != ic->lineno)
11467 debugFile->writeCLine (ic);
11469 if (!options.noCcodeInAsm) {
11470 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11471 printCLine(ic->filename, ic->lineno));
11476 if (ic->seqPoint && ic->seqPoint != cseq)
11478 emitcode ("", "; sequence point %d", ic->seqPoint);
11479 cseq = ic->seqPoint;
11482 if (options.iCodeInAsm) {
11483 char regsInUse[80];
11487 for (i=0; i<8; i++) {
11488 sprintf (®sInUse[i],
11489 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11492 strcpy (regsInUse, "--------");
11493 for (i=0; i < 8; i++) {
11494 if (bitVectBitValue (ic->rMask, i))
11496 int offset = regs8051[i].offset;
11497 regsInUse[offset] = offset + '0'; /* show rMask */
11501 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11503 /* if the result is marked as
11504 spilt and rematerializable or code for
11505 this has already been generated then
11507 if (resultRemat (ic) || ic->generated)
11510 /* depending on the operation */
11530 /* IPOP happens only when trying to restore a
11531 spilt live range, if there is an ifx statement
11532 following this pop then the if statement might
11533 be using some of the registers being popped which
11534 would destory the contents of the register so
11535 we need to check for this condition and handle it */
11537 ic->next->op == IFX &&
11538 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11539 genIfx (ic->next, ic);
11557 genEndFunction (ic);
11577 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11594 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11598 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11605 /* note these two are xlated by algebraic equivalence
11606 during parsing SDCC.y */
11607 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11608 "got '>=' or '<=' shouldn't have come here");
11612 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11624 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11628 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11632 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11668 genRightShift (ic);
11671 case GET_VALUE_AT_ADDRESS:
11673 hasInc (IC_LEFT (ic), ic,
11674 getSize (operandType (IC_RESULT (ic)))),
11675 ifxForOp (IC_RESULT (ic), ic) );
11679 if (POINTER_SET (ic))
11680 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11706 addSet (&_G.sendSet, ic);
11709 case DUMMY_READ_VOLATILE:
11718 genEndCritical (ic);
11730 _G.current_iCode = NULL;
11732 /* now we are ready to call the
11733 peep hole optimizer */
11734 if (!options.nopeep)
11735 peepHole (&lineHead);
11737 /* now do the actual printing */
11738 printLine (lineHead, codeOutFile);