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 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
959 /* force a new aop if sizes differ */
960 sym->usl.spillLoc->aop = NULL;
962 sym->aop = op->aop = aop =
963 aopForSym (ic, sym->usl.spillLoc, result);
964 aop->size = getSize (sym->type);
968 /* else must be a dummy iTemp */
969 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
970 aop->size = getSize (sym->type);
974 /* if the type is a bit register */
975 if (sym->regType == REG_BIT)
977 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
978 aop->size = sym->nRegs;//1???
979 aop->aopu.aop_reg[0] = sym->regs[0];
980 aop->aopu.aop_dir = sym->regs[0]->name;
984 /* must be in a register */
985 sym->aop = op->aop = aop = newAsmop (AOP_REG);
986 aop->size = sym->nRegs;
987 for (i = 0; i < sym->nRegs; i++)
988 aop->aopu.aop_reg[i] = sym->regs[i];
991 /*-----------------------------------------------------------------*/
992 /* freeAsmop - free up the asmop given to an operand */
993 /*----------------------------------------------------------------*/
995 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1012 /* depending on the asmop type only three cases need work
1013 AOP_R0, AOP_R1 & AOP_STK */
1019 emitcode ("mov", "r0,b");
1022 else if (_G.r0Pushed)
1026 emitcode ("pop", "ar0");
1030 bitVectUnSetBit (ic->rUsed, R0_IDX);
1036 emitcode ("mov", "r1,b");
1043 emitcode ("pop", "ar1");
1047 bitVectUnSetBit (ic->rUsed, R1_IDX);
1053 int stk = aop->aopu.aop_stk + aop->size - 1;
1054 bitVectUnSetBit (ic->rUsed, R0_IDX);
1055 bitVectUnSetBit (ic->rUsed, R1_IDX);
1057 getFreePtr (ic, &aop, FALSE);
1061 emitcode ("mov", "a,_bp");
1062 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1063 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1067 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1072 emitcode ("pop", "acc");
1073 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1076 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1079 freeAsmop (op, NULL, ic, TRUE);
1082 emitcode ("pop", "ar1");
1088 emitcode ("pop", "ar0");
1095 /* all other cases just dealloc */
1101 OP_SYMBOL (op)->aop = NULL;
1102 /* if the symbol has a spill */
1104 SPIL_LOC (op)->aop = NULL;
1109 /*------------------------------------------------------------------*/
1110 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1111 /* pop r0 or r1 off stack if pushed */
1112 /*------------------------------------------------------------------*/
1114 freeForBranchAsmop (operand * op)
1126 if (!aop->allocated)
1134 emitcode ("mov", "r0,b");
1136 else if (_G.r0Pushed)
1138 emitcode ("pop", "ar0");
1145 emitcode ("mov", "r1,b");
1147 else if (_G.r1Pushed)
1149 emitcode ("pop", "ar1");
1156 int stk = aop->aopu.aop_stk + aop->size - 1;
1158 emitcode ("mov", "b,r0");
1161 emitcode ("mov", "a,_bp");
1162 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1163 emitcode ("mov", "r0,a");
1167 emitcode ("mov", "r0,_bp");
1172 emitcode ("pop", "acc");
1173 emitcode ("mov", "@r0,a");
1176 emitcode ("dec", "r0");
1178 emitcode ("mov", "r0,b");
1184 /*-----------------------------------------------------------------*/
1185 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1186 /* clobber the accumulator */
1187 /*-----------------------------------------------------------------*/
1189 aopGetUsesAcc (operand * oper, int offset)
1191 asmop * aop = AOP (oper);
1193 if (offset > (aop->size - 1))
1211 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1222 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1228 /* Error case --- will have been caught already */
1234 /*-----------------------------------------------------------------*/
1235 /* aopGet - for fetching value of the aop */
1236 /*-----------------------------------------------------------------*/
1238 aopGet (operand * oper, int offset, bool bit16, bool dname)
1242 asmop * aop = AOP (oper);
1244 /* offset is greater than
1246 if (offset > (aop->size - 1) &&
1247 aop->type != AOP_LIT)
1250 /* depending on type */
1258 /* if we need to increment it */
1259 while (offset > aop->coff)
1261 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1265 while (offset < aop->coff)
1267 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1274 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1275 return (dname ? "acc" : "a");
1277 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1278 rs = Safe_calloc (1, strlen (s) + 1);
1283 if (aop->code && aop->coff==0 && offset>=1) {
1284 emitcode ("mov", "a,#0x%02x", offset);
1285 emitcode ("movc", "a,@a+dptr");
1286 return (dname ? "acc" : "a");
1289 while (offset > aop->coff)
1291 emitcode ("inc", "dptr");
1295 while (offset < aop->coff)
1297 emitcode ("lcall", "__decdptr");
1304 emitcode ("clr", "a");
1305 emitcode ("movc", "a,@a+dptr");
1309 emitcode ("movx", "a,@dptr");
1311 return (dname ? "acc" : "a");
1315 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1316 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1318 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1320 sprintf (s, "#(%s >> %d)",
1321 aop->aopu.aop_immd.aop_immd1,
1325 aop->aopu.aop_immd.aop_immd1);
1326 rs = Safe_calloc (1, strlen (s) + 1);
1331 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1332 sprintf (s, "(%s >> %d)",
1333 aop->aopu.aop_dir, offset * 8);
1335 sprintf (s, "(%s + %d)",
1339 sprintf (s, "%s", aop->aopu.aop_dir);
1340 rs = Safe_calloc (1, strlen (s) + 1);
1346 return aop->aopu.aop_reg[offset]->dname;
1348 return aop->aopu.aop_reg[offset]->name;
1351 emitcode ("clr", "a");
1352 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1353 emitcode ("rlc", "a");
1354 return (dname ? "acc" : "a");
1357 if (!offset && dname)
1359 return aop->aopu.aop_str[offset];
1362 return aopLiteral (aop->aopu.aop_lit, offset);
1366 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1370 return aop->aopu.aop_str[offset];
1374 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1375 "aopget got unsupported aop->type");
1379 /*-----------------------------------------------------------------*/
1380 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1381 /* clobber the accumulator */
1382 /*-----------------------------------------------------------------*/
1384 aopPutUsesAcc (operand * oper, const char *s, int offset)
1386 asmop * aop = AOP (oper);
1388 if (offset > (aop->size - 1))
1398 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1404 return ((aop->paged) || (*s == '@'));
1408 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1416 /* Error case --- will have been caught already */
1422 /*-----------------------------------------------------------------*/
1423 /* aopPut - puts a string for a aop and indicates if acc is in use */
1424 /*-----------------------------------------------------------------*/
1426 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1429 bool accuse = FALSE;
1430 asmop * aop = AOP (result);
1432 if (aop->size && offset > (aop->size - 1))
1434 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1435 "aopPut got offset > aop->size");
1439 /* will assign value to value */
1440 /* depending on where it is ofcourse */
1444 MOVA (s); /* read s in case it was volatile */
1449 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1450 sprintf (d, "(%s >> %d)", aop->aopu.aop_dir, offset * 8);
1452 sprintf (d, "(%s + %d)", aop->aopu.aop_dir, offset);
1454 sprintf (d, "%s", aop->aopu.aop_dir);
1456 if (strcmp (d, s) || bvolatile)
1457 emitcode ("mov", "%s,%s", d, s);
1458 if (!strcmp (d, "acc"))
1464 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1465 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1468 strcmp (s, "r0") == 0 ||
1469 strcmp (s, "r1") == 0 ||
1470 strcmp (s, "r2") == 0 ||
1471 strcmp (s, "r3") == 0 ||
1472 strcmp (s, "r4") == 0 ||
1473 strcmp (s, "r5") == 0 ||
1474 strcmp (s, "r6") == 0 ||
1475 strcmp (s, "r7") == 0)
1476 emitcode ("mov", "%s,%s",
1477 aop->aopu.aop_reg[offset]->dname, s);
1479 emitcode ("mov", "%s,%s",
1480 aop->aopu.aop_reg[offset]->name, s);
1487 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1488 "aopPut writing to code space");
1492 while (offset > aop->coff)
1495 emitcode ("inc", "dptr");
1498 while (offset < aop->coff)
1501 emitcode ("lcall", "__decdptr");
1506 /* if not in accumulator */
1509 emitcode ("movx", "@dptr,a");
1514 while (offset > aop->coff)
1517 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1519 while (offset < aop->coff)
1522 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1529 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1534 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1536 else if (strcmp (s, "r0") == 0 ||
1537 strcmp (s, "r1") == 0 ||
1538 strcmp (s, "r2") == 0 ||
1539 strcmp (s, "r3") == 0 ||
1540 strcmp (s, "r4") == 0 ||
1541 strcmp (s, "r5") == 0 ||
1542 strcmp (s, "r6") == 0 ||
1543 strcmp (s, "r7") == 0)
1546 sprintf (buffer, "a%s", s);
1547 emitcode ("mov", "@%s,%s",
1548 aop->aopu.aop_ptr->name, buffer);
1551 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1556 if (strcmp (s, "a") == 0)
1557 emitcode ("push", "acc");
1561 emitcode ("push", "acc");
1563 emitcode ("push", s);
1569 /* if not bit variable */
1570 if (!aop->aopu.aop_dir)
1572 /* inefficient: move carry into A and use jz/jnz */
1573 emitcode ("clr", "a");
1574 emitcode ("rlc", "a");
1580 emitcode ("clr", "%s", aop->aopu.aop_dir);
1582 emitcode ("setb", "%s", aop->aopu.aop_dir);
1583 else if (!strcmp (s, "c"))
1584 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1585 else if (strcmp (s, aop->aopu.aop_dir))
1588 /* set C, if a >= 1 */
1589 emitcode ("add", "a,#0xff");
1590 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1597 if (strcmp (aop->aopu.aop_str[offset], s) ||
1599 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1605 if (!offset && (strcmp (s, "acc") == 0) &&
1609 if (strcmp (aop->aopu.aop_str[offset], s) &&
1611 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1615 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1616 "aopPut got unsupported aop->type");
1625 /*-----------------------------------------------------------------*/
1626 /* pointToEnd :- points to the last byte of the operand */
1627 /*-----------------------------------------------------------------*/
1629 pointToEnd (asmop * aop)
1635 aop->coff = count = (aop->size - 1);
1641 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1645 emitcode ("inc", "dptr");
1652 /*-----------------------------------------------------------------*/
1653 /* reAdjustPreg - points a register back to where it should */
1654 /*-----------------------------------------------------------------*/
1656 reAdjustPreg (asmop * aop)
1658 if ((aop->coff==0) || aop->size <= 1)
1666 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1671 emitcode ("lcall", "__decdptr");
1678 /*-----------------------------------------------------------------*/
1679 /* opIsGptr: returns non-zero if the passed operand is */
1680 /* a generic pointer type. */
1681 /*-----------------------------------------------------------------*/
1683 opIsGptr (operand * op)
1685 sym_link *type = operandType (op);
1687 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1694 /*-----------------------------------------------------------------*/
1695 /* getDataSize - get the operand data size */
1696 /*-----------------------------------------------------------------*/
1698 getDataSize (operand * op)
1701 size = AOP_SIZE (op);
1702 if (size == GPTRSIZE)
1704 sym_link *type = operandType (op);
1705 if (IS_GENPTR (type))
1707 /* generic pointer; arithmetic operations
1708 * should ignore the high byte (pointer type).
1716 /*-----------------------------------------------------------------*/
1717 /* outAcc - output Acc */
1718 /*-----------------------------------------------------------------*/
1720 outAcc (operand * result)
1723 size = getDataSize (result);
1726 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1729 /* unsigned or positive */
1732 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1737 /*-----------------------------------------------------------------*/
1738 /* outBitC - output a bit C */
1739 /*-----------------------------------------------------------------*/
1741 outBitC (operand * result)
1743 /* if the result is bit */
1744 if (AOP_TYPE (result) == AOP_CRY)
1745 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1748 emitcode ("clr", "a");
1749 emitcode ("rlc", "a");
1754 /*-----------------------------------------------------------------*/
1755 /* toBoolean - emit code for orl a,operator(sizeop) */
1756 /*-----------------------------------------------------------------*/
1758 toBoolean (operand * oper)
1760 int size = AOP_SIZE (oper) - 1;
1762 bool AccUsed = FALSE;
1765 while (!AccUsed && size--)
1767 AccUsed |= aopGetUsesAcc(oper, offset++);
1770 size = AOP_SIZE (oper) - 1;
1772 MOVA (aopGet (oper, 0, FALSE, FALSE));
1773 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1776 emitcode("mov", "b,a");
1779 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1780 emitcode ("orl", "b,a");
1782 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1783 emitcode ("orl", "a,b");
1790 emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1796 /*-----------------------------------------------------------------*/
1797 /* genNot - generate code for ! operation */
1798 /*-----------------------------------------------------------------*/
1804 D(emitcode ("; genNot",""));
1806 /* assign asmOps to operand & result */
1807 aopOp (IC_LEFT (ic), ic, FALSE);
1808 aopOp (IC_RESULT (ic), ic, TRUE);
1810 /* if in bit space then a special case */
1811 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1813 /* if left==result then cpl bit */
1814 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1816 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1820 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1821 emitcode ("cpl", "c");
1822 outBitC (IC_RESULT (ic));
1827 toBoolean (IC_LEFT (ic));
1829 /* set C, if a == 0 */
1830 tlbl = newiTempLabel (NULL);
1831 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1832 emitcode ("", "%05d$:", tlbl->key + 100);
1833 outBitC (IC_RESULT (ic));
1836 /* release the aops */
1837 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1838 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1842 /*-----------------------------------------------------------------*/
1843 /* genCpl - generate code for complement */
1844 /*-----------------------------------------------------------------*/
1851 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1853 D(emitcode (";", "genCpl"));
1855 /* assign asmOps to operand & result */
1856 aopOp (IC_LEFT (ic), ic, FALSE);
1857 aopOp (IC_RESULT (ic), ic, TRUE);
1859 /* special case if in bit space */
1860 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1864 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1865 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1867 /* promotion rules are responsible for this strange result:
1868 bit -> int -> ~int -> bit
1869 uchar -> int -> ~int -> bit
1871 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1875 tlbl=newiTempLabel(NULL);
1876 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1877 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1878 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1879 IS_AOP_PREG (IC_LEFT (ic)))
1881 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1886 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1888 emitcode ("", "%05d$:", tlbl->key + 100);
1889 outBitC (IC_RESULT(ic));
1893 size = AOP_SIZE (IC_RESULT (ic));
1896 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1898 emitcode ("cpl", "a");
1899 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1904 /* release the aops */
1905 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1906 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1909 /*-----------------------------------------------------------------*/
1910 /* genUminusFloat - unary minus for floating points */
1911 /*-----------------------------------------------------------------*/
1913 genUminusFloat (operand * op, operand * result)
1915 int size, offset = 0;
1918 D(emitcode ("; genUminusFloat",""));
1920 /* for this we just copy and then flip the bit */
1922 size = AOP_SIZE (op) - 1;
1927 aopGet (op, offset, FALSE, FALSE),
1929 isOperandVolatile (result, FALSE));
1933 l = aopGet (op, offset, FALSE, FALSE);
1937 emitcode ("cpl", "acc.7");
1938 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1941 /*-----------------------------------------------------------------*/
1942 /* genUminus - unary minus code generation */
1943 /*-----------------------------------------------------------------*/
1945 genUminus (iCode * ic)
1948 sym_link *optype, *rtype;
1951 D(emitcode ("; genUminus",""));
1954 aopOp (IC_LEFT (ic), ic, FALSE);
1955 aopOp (IC_RESULT (ic), ic, TRUE);
1957 /* if both in bit space then special
1959 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1960 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1963 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1964 emitcode ("cpl", "c");
1965 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1969 optype = operandType (IC_LEFT (ic));
1970 rtype = operandType (IC_RESULT (ic));
1972 /* if float then do float stuff */
1973 if (IS_FLOAT (optype))
1975 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1979 /* otherwise subtract from zero */
1980 size = AOP_SIZE (IC_LEFT (ic));
1985 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1986 if (!strcmp (l, "a"))
1990 emitcode ("cpl", "a");
1991 emitcode ("addc", "a,#0");
1997 emitcode ("clr", "a");
1998 emitcode ("subb", "a,%s", l);
2000 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
2003 /* if any remaining bytes in the result */
2004 /* we just need to propagate the sign */
2005 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
2007 emitcode ("rlc", "a");
2008 emitcode ("subb", "a,acc");
2010 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
2014 /* release the aops */
2015 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2016 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2019 /*-----------------------------------------------------------------*/
2020 /* saveRegisters - will look for a call and save the registers */
2021 /*-----------------------------------------------------------------*/
2023 saveRegisters (iCode * lic)
2030 for (ic = lic; ic; ic = ic->next)
2031 if (ic->op == CALL || ic->op == PCALL)
2036 fprintf (stderr, "found parameter push with no function call\n");
2040 /* if the registers have been saved already or don't need to be then
2044 if (IS_SYMOP(IC_LEFT(ic)) &&
2045 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2046 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2049 /* save the registers in use at this time but skip the
2050 ones for the result */
2051 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2052 mcs51_rUmaskForOp (IC_RESULT(ic)));
2055 if (options.useXstack)
2057 int count = bitVectnBitsOn (rsave);
2061 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2062 if (reg->type == REG_BIT)
2064 emitcode ("mov", "a,%s", reg->base);
2068 emitcode ("mov", "a,%s", reg->name);
2070 emitcode ("mov", "r0,%s", spname);
2071 emitcode ("inc", "%s", spname);// allocate before use
2072 emitcode ("movx", "@r0,a");
2073 if (bitVectBitValue (rsave, R0_IDX))
2074 emitcode ("mov", "r0,a");
2076 else if (count != 0)
2078 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2079 int nBits = bitVectnBitsOn (rsavebits);
2083 count = count - nBits + 1;
2084 /* remove all but the first bits as they are pushed all at once */
2085 rsave = bitVectCplAnd (rsave, rsavebits);
2086 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2089 if (bitVectBitValue (rsave, R0_IDX))
2091 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2093 emitcode ("mov", "r0,%s", spname);
2095 emitcode ("add", "a,#%d", count);
2096 emitcode ("mov", "%s,a", spname);
2097 for (i = 0; i < mcs51_nRegs; i++)
2099 if (bitVectBitValue (rsave, i))
2101 regs * reg = mcs51_regWithIdx (i);
2104 emitcode ("pop", "acc");
2105 emitcode ("push", "acc");
2107 else if (reg->type == REG_BIT)
2109 emitcode ("mov", "a,%s", reg->base);
2113 emitcode ("mov", "a,%s", reg->name);
2115 emitcode ("movx", "@r0,a");
2118 emitcode ("inc", "r0");
2122 if (bitVectBitValue (rsave, R0_IDX))
2124 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2130 bool bits_pushed = FALSE;
2131 for (i = 0; i < mcs51_nRegs; i++)
2133 if (bitVectBitValue (rsave, i))
2135 bits_pushed = pushReg (i, bits_pushed);
2141 /*-----------------------------------------------------------------*/
2142 /* unsaveRegisters - pop the pushed registers */
2143 /*-----------------------------------------------------------------*/
2145 unsaveRegisters (iCode * ic)
2150 /* restore the registers in use at this time but skip the
2151 ones for the result */
2152 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2153 mcs51_rUmaskForOp (IC_RESULT(ic)));
2155 if (options.useXstack)
2157 int count = bitVectnBitsOn (rsave);
2161 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2162 emitcode ("mov", "r0,%s", spname);
2163 emitcode ("dec", "r0");
2164 emitcode ("movx", "a,@r0");
2165 if (reg->type == REG_BIT)
2167 emitcode ("mov", "%s,a", reg->base);
2171 emitcode ("mov", "%s,a", reg->name);
2173 emitcode ("dec", "%s", spname);
2175 else if (count != 0)
2177 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2178 int nBits = bitVectnBitsOn (rsavebits);
2182 count = count - nBits + 1;
2183 /* remove all but the first bits as they are popped all at once */
2184 rsave = bitVectCplAnd (rsave, rsavebits);
2185 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2188 emitcode ("mov", "r0,%s", spname);
2189 for (i = mcs51_nRegs; i >= 0; i--)
2191 if (bitVectBitValue (rsave, i))
2193 regs * reg = mcs51_regWithIdx (i);
2194 emitcode ("dec", "r0");
2195 emitcode ("movx", "a,@r0");
2198 emitcode ("push", "acc");
2200 else if (reg->type == REG_BIT)
2202 emitcode ("mov", "%s,a", reg->base);
2206 emitcode ("mov", "%s,a", reg->name);
2210 emitcode ("mov", "%s,r0", spname);
2211 if (bitVectBitValue (rsave, R0_IDX))
2213 emitcode ("pop", "ar0");
2219 bool bits_popped = FALSE;
2220 for (i = mcs51_nRegs; i >= 0; i--)
2222 if (bitVectBitValue (rsave, i))
2224 bits_popped = popReg (i, bits_popped);
2231 /*-----------------------------------------------------------------*/
2233 /*-----------------------------------------------------------------*/
2235 pushSide (operand * oper, int size)
2240 char *l = aopGet (oper, offset++, FALSE, TRUE);
2241 if (AOP_TYPE (oper) != AOP_REG &&
2242 AOP_TYPE (oper) != AOP_DIR &&
2246 emitcode ("push", "acc");
2250 emitcode ("push", "%s", l);
2255 /*-----------------------------------------------------------------*/
2256 /* assignResultValue - also indicates if acc is in use afterwards */
2257 /*-----------------------------------------------------------------*/
2259 assignResultValue (operand * oper, operand * func)
2262 int size = AOP_SIZE (oper);
2263 bool accuse = FALSE;
2264 bool pushedA = FALSE;
2266 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2272 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2274 emitcode ("push", "acc");
2279 if ((offset == 3) && pushedA)
2280 emitcode ("pop", "acc");
2281 accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2288 /*-----------------------------------------------------------------*/
2289 /* genXpush - pushes onto the external stack */
2290 /*-----------------------------------------------------------------*/
2292 genXpush (iCode * ic)
2294 asmop *aop = newAsmop (0);
2296 int size, offset = 0;
2298 D(emitcode ("; genXpush",""));
2300 aopOp (IC_LEFT (ic), ic, FALSE);
2301 r = getFreePtr (ic, &aop, FALSE);
2303 size = AOP_SIZE (IC_LEFT (ic));
2307 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2308 emitcode ("mov", "%s,%s", r->name, spname);
2309 emitcode ("inc", "%s", spname); // allocate space first
2310 emitcode ("movx", "@%s,a", r->name);
2314 // allocate space first
2315 emitcode ("mov", "%s,%s", r->name, spname);
2317 emitcode ("add", "a,#%d", size);
2318 emitcode ("mov", "%s,a", spname);
2322 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2323 emitcode ("movx", "@%s,a", r->name);
2324 emitcode ("inc", "%s", r->name);
2328 freeAsmop (NULL, aop, ic, TRUE);
2329 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2332 /*-----------------------------------------------------------------*/
2333 /* genIpush - generate code for pushing this gets a little complex */
2334 /*-----------------------------------------------------------------*/
2336 genIpush (iCode * ic)
2338 int size, offset = 0;
2342 D(emitcode ("; genIpush",""));
2344 /* if this is not a parm push : ie. it is spill push
2345 and spill push is always done on the local stack */
2349 /* and the item is spilt then do nothing */
2350 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2353 aopOp (IC_LEFT (ic), ic, FALSE);
2354 size = AOP_SIZE (IC_LEFT (ic));
2355 /* push it on the stack */
2358 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2364 emitcode ("push", "%s", l);
2369 /* this is a parameter push: in this case we call
2370 the routine to find the call and save those
2371 registers that need to be saved */
2374 /* if use external stack then call the external
2375 stack pushing routine */
2376 if (options.useXstack)
2382 /* then do the push */
2383 aopOp (IC_LEFT (ic), ic, FALSE);
2385 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2386 size = AOP_SIZE (IC_LEFT (ic));
2390 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2391 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2392 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2395 if (strcmp (l, prev) || *l == '@')
2397 emitcode ("push", "acc");
2401 emitcode ("push", "%s", l);
2406 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2409 /*-----------------------------------------------------------------*/
2410 /* genIpop - recover the registers: can happen only for spilling */
2411 /*-----------------------------------------------------------------*/
2413 genIpop (iCode * ic)
2417 D(emitcode ("; genIpop",""));
2419 /* if the temp was not pushed then */
2420 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2423 aopOp (IC_LEFT (ic), ic, FALSE);
2424 size = AOP_SIZE (IC_LEFT (ic));
2425 offset = (size - 1);
2427 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2430 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2433 /*-----------------------------------------------------------------*/
2434 /* saveRBank - saves an entire register bank on the stack */
2435 /*-----------------------------------------------------------------*/
2437 saveRBank (int bank, iCode * ic, bool pushPsw)
2440 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2444 if (options.useXstack)
2448 /* Assume r0 is available for use. */
2449 r = mcs51_regWithIdx (R0_IDX);;
2454 r = getFreePtr (ic, &aop, FALSE);
2456 // allocate space first
2457 emitcode ("mov", "%s,%s", r->name, spname);
2459 emitcode ("add", "a,#%d", count);
2460 emitcode ("mov", "%s,a", spname);
2463 for (i = 0; i < 8; i++)
2465 if (options.useXstack)
2467 emitcode ("mov", "a,(%s+%d)",
2468 regs8051[i].base, 8 * bank + regs8051[i].offset);
2469 emitcode ("movx", "@%s,a", r->name);
2471 emitcode ("inc", "%s", r->name);
2474 emitcode ("push", "(%s+%d)",
2475 regs8051[i].base, 8 * bank + regs8051[i].offset);
2478 if (mcs51_nRegs > 8)
2480 if (options.useXstack)
2482 emitcode ("mov", "a,bits");
2483 emitcode ("movx", "@%s,a", r->name);
2485 emitcode ("inc", "%s", r->name);
2489 emitcode ("push", "bits");
2496 if (options.useXstack)
2498 emitcode ("mov", "a,psw");
2499 emitcode ("movx", "@%s,a", r->name);
2504 emitcode ("push", "psw");
2507 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2512 freeAsmop (NULL, aop, ic, TRUE);
2521 /*-----------------------------------------------------------------*/
2522 /* unsaveRBank - restores the register bank from stack */
2523 /*-----------------------------------------------------------------*/
2525 unsaveRBank (int bank, iCode * ic, bool popPsw)
2531 if (options.useXstack)
2535 /* Assume r0 is available for use. */
2536 r = mcs51_regWithIdx (R0_IDX);;
2541 r = getFreePtr (ic, &aop, FALSE);
2543 emitcode ("mov", "%s,%s", r->name, spname);
2548 if (options.useXstack)
2550 emitcode ("dec", "%s", r->name);
2551 emitcode ("movx", "a,@%s", r->name);
2552 emitcode ("mov", "psw,a");
2556 emitcode ("pop", "psw");
2560 if (mcs51_nRegs > 8)
2562 if (options.useXstack)
2564 emitcode ("dec", "%s", r->name);
2565 emitcode ("movx", "a,@%s", r->name);
2566 emitcode ("mov", "bits,a");
2570 emitcode ("pop", "bits");
2574 for (i = 7; i >= 0; i--)
2576 if (options.useXstack)
2578 emitcode ("dec", "%s", r->name);
2579 emitcode ("movx", "a,@%s", r->name);
2580 emitcode ("mov", "(%s+%d),a",
2581 regs8051[i].base, 8 * bank + regs8051[i].offset);
2585 emitcode ("pop", "(%s+%d)",
2586 regs8051[i].base, 8 * bank + regs8051[i].offset);
2590 if (options.useXstack)
2592 emitcode ("mov", "%s,%s", spname, r->name);
2597 freeAsmop (NULL, aop, ic, TRUE);
2601 /*-----------------------------------------------------------------*/
2602 /* genSend - gen code for SEND */
2603 /*-----------------------------------------------------------------*/
2604 static void genSend(set *sendSet)
2609 /* first we do all bit parameters */
2610 for (sic = setFirstItem (sendSet); sic;
2611 sic = setNextItem (sendSet))
2613 if (sic->argreg > 12)
2615 int bit = sic->argreg-13;
2617 aopOp (IC_LEFT (sic), sic, FALSE);
2619 /* if left is a literal then
2620 we know what the value is */
2621 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2623 if (((int) operandLitValue (IC_LEFT (sic))))
2624 emitcode ("setb", "b[%d]", bit);
2626 emitcode ("clr", "b[%d]", bit);
2628 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2630 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2631 if (strcmp (l, "c"))
2632 emitcode ("mov", "c,%s", l);
2633 emitcode ("mov", "b[%d],c", bit);
2638 toBoolean (IC_LEFT (sic));
2639 /* set C, if a >= 1 */
2640 emitcode ("add", "a,#0xff");
2641 emitcode ("mov", "b[%d],c", bit);
2646 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2652 saveRegisters (setFirstItem (sendSet));
2653 emitcode ("mov", "bits,b");
2656 /* then we do all other parameters */
2657 for (sic = setFirstItem (sendSet); sic;
2658 sic = setNextItem (sendSet))
2660 if (sic->argreg <= 12)
2662 int size, offset = 0;
2663 aopOp (IC_LEFT (sic), sic, FALSE);
2664 size = AOP_SIZE (IC_LEFT (sic));
2666 if (sic->argreg == 1)
2670 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2671 if (strcmp (l, fReturn[offset]))
2672 emitcode ("mov", "%s,%s", fReturn[offset], l);
2680 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2681 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2685 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2690 /*-----------------------------------------------------------------*/
2691 /* selectRegBank - emit code to select the register bank */
2692 /*-----------------------------------------------------------------*/
2694 selectRegBank (short bank, bool keepFlags)
2696 /* if f.e. result is in carry */
2699 emitcode ("anl", "psw,#0xE7");
2701 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2705 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2709 /*-----------------------------------------------------------------*/
2710 /* genCall - generates a call statement */
2711 /*-----------------------------------------------------------------*/
2713 genCall (iCode * ic)
2717 // bool restoreBank = FALSE;
2718 bool swapBanks = FALSE;
2719 bool accuse = FALSE;
2720 bool accPushed = FALSE;
2721 bool resultInF0 = FALSE;
2722 bool assignResultGenerated = FALSE;
2724 D(emitcode("; genCall",""));
2726 dtype = operandType (IC_LEFT (ic));
2727 etype = getSpec(dtype);
2728 /* if send set is not empty then assign */
2731 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2732 genSend(reverseSet(_G.sendSet));
2734 genSend(_G.sendSet);
2740 /* if we are calling a not _naked function that is not using
2741 the same register bank then we need to save the
2742 destination registers on the stack */
2743 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2744 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2745 !IFFUNC_ISISR (dtype))
2750 /* if caller saves & we have not saved then */
2756 emitcode ("mov", "psw,#0x%02x",
2757 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2761 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2763 if (IFFUNC_CALLEESAVES(dtype))
2765 werror (E_BANKED_WITH_CALLEESAVES);
2769 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2770 OP_SYMBOL (IC_LEFT (ic))->rname :
2771 OP_SYMBOL (IC_LEFT (ic))->name);
2773 emitcode ("mov", "r0,#%s", l);
2774 emitcode ("mov", "r1,#(%s >> 8)", l);
2775 emitcode ("mov", "r2,#(%s >> 16)", l);
2776 emitcode ("lcall", "__sdcc_banked_call");
2781 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2782 OP_SYMBOL (IC_LEFT (ic))->rname :
2783 OP_SYMBOL (IC_LEFT (ic))->name));
2788 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2791 /* if we need assign a result value */
2792 if ((IS_ITEMP (IC_RESULT (ic)) &&
2793 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2794 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2795 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2796 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2797 IS_TRUE_SYMOP (IC_RESULT (ic)))
2801 aopOp (IC_RESULT (ic), ic, FALSE);
2804 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2805 assignResultGenerated = TRUE;
2807 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2810 /* adjust the stack for parameters if required */
2814 if (ic->parmBytes > 3)
2818 emitcode ("push", "acc");
2821 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2822 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2823 !assignResultGenerated)
2825 emitcode ("mov", "F0,c");
2829 emitcode ("mov", "a,%s", spname);
2830 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2831 emitcode ("mov", "%s,a", spname);
2833 /* unsaveRegisters from xstack needs acc, but */
2834 /* unsaveRegisters from stack needs this popped */
2835 if (accPushed && !options.useXstack)
2837 emitcode ("pop", "acc");
2842 for (i = 0; i < ic->parmBytes; i++)
2843 emitcode ("dec", "%s", spname);
2846 /* if we had saved some registers then unsave them */
2847 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2849 if (accuse && !accPushed && options.useXstack)
2851 /* xstack needs acc, but doesn't touch normal stack */
2852 emitcode ("push", "acc");
2855 unsaveRegisters (ic);
2858 // /* if register bank was saved then pop them */
2860 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2862 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) && !assignResultGenerated)
2865 emitcode ("mov", "c,F0");
2867 aopOp (IC_RESULT (ic), ic, FALSE);
2868 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2869 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2873 emitcode ("pop", "acc");
2876 /*-----------------------------------------------------------------*/
2877 /* -10l - generates a call by pointer statement */
2878 /*-----------------------------------------------------------------*/
2880 genPcall (iCode * ic)
2884 symbol *rlbl = newiTempLabel (NULL);
2885 // bool restoreBank=FALSE;
2886 bool swapBanks = FALSE;
2887 bool resultInF0 = FALSE;
2889 D(emitcode("; genPCall",""));
2891 dtype = operandType (IC_LEFT (ic))->next;
2892 etype = getSpec(dtype);
2893 /* if caller saves & we have not saved then */
2897 /* if we are calling a not _naked function that is not using
2898 the same register bank then we need to save the
2899 destination registers on the stack */
2900 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2901 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2902 !IFFUNC_ISISR (dtype))
2904 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2905 // restoreBank=TRUE;
2907 // need caution message to user here
2910 if (IS_LITERAL(etype))
2912 /* if send set is not empty then assign */
2915 genSend(reverseSet(_G.sendSet));
2921 emitcode ("mov", "psw,#0x%02x",
2922 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2925 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2927 if (IFFUNC_CALLEESAVES(dtype))
2929 werror (E_BANKED_WITH_CALLEESAVES);
2933 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2935 emitcode ("mov", "r0,#%s", l);
2936 emitcode ("mov", "r1,#(%s >> 8)", l);
2937 emitcode ("mov", "r2,#(%s >> 16)", l);
2938 emitcode ("lcall", "__sdcc_banked_call");
2943 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2948 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2950 if (IFFUNC_CALLEESAVES(dtype))
2952 werror (E_BANKED_WITH_CALLEESAVES);
2956 aopOp (IC_LEFT (ic), ic, FALSE);
2960 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2961 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2962 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2966 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2967 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2968 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2969 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2972 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2974 /* if send set is not empty then assign */
2977 genSend(reverseSet(_G.sendSet));
2983 emitcode ("mov", "psw,#0x%02x",
2984 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2988 emitcode ("lcall", "__sdcc_banked_call");
2993 /* push the return address on to the stack */
2994 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2995 emitcode ("push", "acc");
2996 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2997 emitcode ("push", "acc");
2999 /* now push the calling address */
3000 aopOp (IC_LEFT (ic), ic, FALSE);
3002 pushSide (IC_LEFT (ic), FPTRSIZE);
3004 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3006 /* if send set is not empty the assign */
3009 genSend(reverseSet(_G.sendSet));
3015 emitcode ("mov", "psw,#0x%02x",
3016 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3020 emitcode ("ret", "");
3021 emitcode ("", "%05d$:", (rlbl->key + 100));
3026 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3029 /* if we need assign a result value */
3030 if ((IS_ITEMP (IC_RESULT (ic)) &&
3031 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3032 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3033 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3034 IS_TRUE_SYMOP (IC_RESULT (ic)))
3038 aopOp (IC_RESULT (ic), ic, FALSE);
3041 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3043 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3046 /* adjust the stack for parameters if required */
3050 if (ic->parmBytes > 3)
3052 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3053 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3055 emitcode ("mov", "F0,c");
3059 emitcode ("mov", "a,%s", spname);
3060 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3061 emitcode ("mov", "%s,a", spname);
3064 for (i = 0; i < ic->parmBytes; i++)
3065 emitcode ("dec", "%s", spname);
3069 // /* if register bank was saved then unsave them */
3071 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3073 /* if we had saved some registers then unsave them */
3074 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3075 unsaveRegisters (ic);
3077 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3080 emitcode ("mov", "c,F0");
3082 aopOp (IC_RESULT (ic), ic, FALSE);
3083 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3084 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3088 /*-----------------------------------------------------------------*/
3089 /* resultRemat - result is rematerializable */
3090 /*-----------------------------------------------------------------*/
3092 resultRemat (iCode * ic)
3094 if (SKIP_IC (ic) || ic->op == IFX)
3097 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3099 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3100 if (sym->remat && !POINTER_SET (ic))
3107 #if defined(__BORLANDC__) || defined(_MSC_VER)
3108 #define STRCASECMP stricmp
3110 #define STRCASECMP strcasecmp
3113 /*-----------------------------------------------------------------*/
3114 /* inExcludeList - return 1 if the string is in exclude Reg list */
3115 /*-----------------------------------------------------------------*/
3117 regsCmp(void *p1, void *p2)
3119 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3123 inExcludeList (char *s)
3125 const char *p = setFirstItem(options.excludeRegsSet);
3127 if (p == NULL || STRCASECMP(p, "none") == 0)
3131 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3134 /*-----------------------------------------------------------------*/
3135 /* genFunction - generated code for function entry */
3136 /*-----------------------------------------------------------------*/
3138 genFunction (iCode * ic)
3140 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3142 bool switchedPSW = FALSE;
3143 int calleesaves_saved_register = -1;
3144 int stackAdjust = sym->stack;
3145 int accIsFree = sym->recvSize < 4;
3146 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3147 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3150 /* create the function header */
3151 emitcode (";", "-----------------------------------------");
3152 emitcode (";", " function %s", sym->name);
3153 emitcode (";", "-----------------------------------------");
3155 emitcode ("", "%s:", sym->rname);
3156 ftype = operandType (IC_LEFT (ic));
3157 _G.currentFunc = sym;
3159 if (IFFUNC_ISNAKED(ftype))
3161 emitcode(";", "naked function: no prologue.");
3165 /* here we need to generate the equates for the
3166 register bank if required */
3167 if (FUNC_REGBANK (ftype) != rbank)
3171 rbank = FUNC_REGBANK (ftype);
3172 for (i = 0; i < mcs51_nRegs; i++)
3174 if (regs8051[i].type != REG_BIT)
3176 if (strcmp (regs8051[i].base, "0") == 0)
3177 emitcode ("", "%s = 0x%02x",
3179 8 * rbank + regs8051[i].offset);
3181 emitcode ("", "%s = %s + 0x%02x",
3184 8 * rbank + regs8051[i].offset);
3189 /* if this is an interrupt service routine then
3190 save acc, b, dpl, dph */
3191 if (IFFUNC_ISISR (sym->type))
3194 if (!inExcludeList ("acc"))
3195 emitcode ("push", "acc");
3196 if (!inExcludeList ("b"))
3197 emitcode ("push", "b");
3198 if (!inExcludeList ("dpl"))
3199 emitcode ("push", "dpl");
3200 if (!inExcludeList ("dph"))
3201 emitcode ("push", "dph");
3202 /* if this isr has no bank i.e. is going to
3203 run with bank 0 , then we need to save more
3205 if (!FUNC_REGBANK (sym->type))
3208 /* if this function does not call any other
3209 function then we can be economical and
3210 save only those registers that are used */
3211 if (!IFFUNC_HASFCALL(sym->type))
3215 /* if any registers used */
3218 bool bits_pushed = FALSE;
3219 /* save the registers used */
3220 for (i = 0; i < sym->regsUsed->size; i++)
3222 if (bitVectBitValue (sym->regsUsed, i))
3223 bits_pushed = pushReg (i, bits_pushed);
3230 /* this function has a function call. We cannot
3231 determines register usage so we will have to push the
3233 saveRBank (0, ic, FALSE);
3234 if (options.parms_in_bank1) {
3236 for (i=0; i < 8 ; i++ ) {
3237 emitcode ("push","%s",rb1regs[i]);
3244 /* This ISR uses a non-zero bank.
3246 * We assume that the bank is available for our
3249 * However, if this ISR calls a function which uses some
3250 * other bank, we must save that bank entirely.
3252 unsigned long banksToSave = 0;
3254 if (IFFUNC_HASFCALL(sym->type))
3257 #define MAX_REGISTER_BANKS 4
3262 for (i = ic; i; i = i->next)
3264 if (i->op == ENDFUNCTION)
3266 /* we got to the end OK. */
3274 dtype = operandType (IC_LEFT(i));
3276 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3278 /* Mark this bank for saving. */
3279 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3281 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3285 banksToSave |= (1 << FUNC_REGBANK(dtype));
3288 /* And note that we don't need to do it in
3296 /* This is a mess; we have no idea what
3297 * register bank the called function might
3300 * The only thing I can think of to do is
3301 * throw a warning and hope.
3303 werror(W_FUNCPTR_IN_USING_ISR);
3307 if (banksToSave && options.useXstack)
3309 /* Since we aren't passing it an ic,
3310 * saveRBank will assume r0 is available to abuse.
3312 * So switch to our (trashable) bank now, so
3313 * the caller's R0 isn't trashed.
3315 emitcode ("push", "psw");
3316 emitcode ("mov", "psw,#0x%02x",
3317 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3321 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3323 if (banksToSave & (1 << ix))
3325 saveRBank(ix, NULL, FALSE);
3329 // TODO: this needs a closer look
3330 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3333 /* Set the register bank to the desired value if nothing else */
3334 /* has done so yet. */
3337 emitcode ("push", "psw");
3338 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3343 /* This is a non-ISR function. The caller has already switched register */
3344 /* banks, if necessary, so just handle the callee-saves option. */
3346 /* if callee-save to be used for this function
3347 then save the registers being used in this function */
3348 if (IFFUNC_CALLEESAVES(sym->type))
3352 /* if any registers used */
3355 bool bits_pushed = FALSE;
3356 /* save the registers used */
3357 for (i = 0; i < sym->regsUsed->size; i++)
3359 if (bitVectBitValue (sym->regsUsed, i))
3361 /* remember one saved register for later usage */
3362 if (calleesaves_saved_register < 0)
3363 calleesaves_saved_register = i;
3364 bits_pushed = pushReg (i, bits_pushed);
3375 if (options.useXstack)
3377 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3379 emitcode ("mov", "r0,%s", spname);
3380 emitcode ("inc", "%s", spname);
3381 emitcode ("xch", "a,_bpx");
3382 emitcode ("movx", "@r0,a");
3383 emitcode ("inc", "r0");
3384 emitcode ("mov", "a,r0");
3385 emitcode ("xch", "a,_bpx");
3389 emitcode ("push", "_bp"); /* save the callers stack */
3390 emitcode ("mov", "_bp,sp");
3395 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3397 /* set up the stack */
3398 emitcode ("push", "_bp"); /* save the callers stack */
3399 emitcode ("mov", "_bp,sp");
3404 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3405 /* before setting up the stack frame completely. */
3406 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3408 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3412 if (rsym && rsym->regType == REG_CND)
3414 if (rsym && (rsym->accuse || rsym->ruonly))
3416 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3417 rsym = rsym->usl.spillLoc;
3420 /* If the RECEIVE operand immediately spills to the first entry on the */
3421 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3422 /* rather than the usual @r0/r1 machinations. */
3423 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3427 _G.current_iCode = ric;
3428 D(emitcode ("; genReceive",""));
3429 for (ofs=0; ofs < sym->recvSize; ofs++)
3431 if (!strcmp (fReturn[ofs], "a"))
3432 emitcode ("push", "acc");
3434 emitcode ("push", fReturn[ofs]);
3436 stackAdjust -= sym->recvSize;
3439 assert (stackAdjust>=0);
3442 _G.current_iCode = ic;
3446 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3447 /* to free up the accumulator. */
3448 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3452 _G.current_iCode = ric;
3453 D(emitcode ("; genReceive",""));
3454 for (ofs=0; ofs < sym->recvSize; ofs++)
3456 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3458 _G.current_iCode = ic;
3464 /* adjust the stack for the function */
3467 int i = stackAdjust;
3469 werror (W_STACK_OVERFLOW, sym->name);
3471 if (i > 3 && accIsFree)
3473 emitcode ("mov", "a,sp");
3474 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3475 emitcode ("mov", "sp,a");
3479 /* The accumulator is not free, so we will need another register */
3480 /* to clobber. No need to worry about a possible conflict with */
3481 /* the above early RECEIVE optimizations since they would have */
3482 /* freed the accumulator if they were generated. */
3484 if (IFFUNC_CALLEESAVES(sym->type))
3486 /* if it's a callee-saves function we need a saved register */
3487 if (calleesaves_saved_register >= 0)
3489 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3490 emitcode ("mov", "a,sp");
3491 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3492 emitcode ("mov", "sp,a");
3493 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3496 /* do it the hard way */
3498 emitcode ("inc", "sp");
3502 /* not callee-saves, we can clobber r0 */
3503 emitcode ("mov", "r0,a");
3504 emitcode ("mov", "a,sp");
3505 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3506 emitcode ("mov", "sp,a");
3507 emitcode ("mov", "a,r0");
3512 emitcode ("inc", "sp");
3517 char i = ((char) sym->xstack & 0xff);
3519 if (i > 3 && accIsFree)
3521 emitcode ("mov", "a,_spx");
3522 emitcode ("add", "a,#0x%02x", i);
3523 emitcode ("mov", "_spx,a");
3527 emitcode ("push", "acc");
3528 emitcode ("mov", "a,_spx");
3529 emitcode ("add", "a,#0x%02x", i);
3530 emitcode ("mov", "_spx,a");
3531 emitcode ("pop", "acc");
3536 emitcode ("inc", "_spx");
3540 /* if critical function then turn interrupts off */
3541 if (IFFUNC_ISCRITICAL (ftype))
3543 symbol *tlbl = newiTempLabel (NULL);
3544 emitcode ("setb", "c");
3545 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3546 emitcode ("clr", "c");
3547 emitcode ("", "%05d$:", (tlbl->key + 100));
3548 emitcode ("push", "psw"); /* save old ea via c in psw */
3552 /*-----------------------------------------------------------------*/
3553 /* genEndFunction - generates epilogue for functions */
3554 /*-----------------------------------------------------------------*/
3556 genEndFunction (iCode * ic)
3558 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3559 lineNode *lnp = lineCurr;
3561 bitVect *regsUsedPrologue;
3562 bitVect *regsUnneeded;
3565 _G.currentFunc = NULL;
3566 if (IFFUNC_ISNAKED(sym->type))
3568 emitcode(";", "naked function: no epilogue.");
3569 if (options.debug && currFunc)
3570 debugFile->writeEndFunction (currFunc, ic, 0);
3574 if (IFFUNC_ISCRITICAL (sym->type))
3576 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3578 emitcode ("rlc", "a"); /* save c in a */
3579 emitcode ("pop", "psw"); /* restore ea via c in psw */
3580 emitcode ("mov", "ea,c");
3581 emitcode ("rrc", "a"); /* restore c from a */
3585 emitcode ("pop", "psw"); /* restore ea via c in psw */
3586 emitcode ("mov", "ea,c");
3590 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3592 if (options.useXstack)
3596 emitcode ("mov", "sp,_bp");
3597 emitcode ("pop", "_bp");
3599 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3601 emitcode ("xch", "a,_bpx");
3602 emitcode ("mov", "r0,a");
3603 emitcode ("dec", "r0");
3604 emitcode ("movx", "a,@r0");
3605 emitcode ("xch", "a,_bpx");
3606 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3609 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3611 emitcode ("mov", "sp,_bp");
3612 emitcode ("pop", "_bp");
3616 /* restore the register bank */
3617 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3619 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3620 || !options.useXstack)
3622 /* Special case of ISR using non-zero bank with useXstack
3625 emitcode ("pop", "psw");
3629 if (IFFUNC_ISISR (sym->type))
3632 /* now we need to restore the registers */
3633 /* if this isr has no bank i.e. is going to
3634 run with bank 0 , then we need to save more
3636 if (!FUNC_REGBANK (sym->type))
3638 /* if this function does not call any other
3639 function then we can be economical and
3640 save only those registers that are used */
3641 if (!IFFUNC_HASFCALL(sym->type))
3645 /* if any registers used */
3648 bool bits_popped = FALSE;
3649 /* save the registers used */
3650 for (i = sym->regsUsed->size; i >= 0; i--)
3652 if (bitVectBitValue (sym->regsUsed, i))
3653 bits_popped = popReg (i, bits_popped);
3659 if (options.parms_in_bank1) {
3661 for (i = 7 ; i >= 0 ; i-- ) {
3662 emitcode ("pop","%s",rb1regs[i]);
3665 /* this function has a function call cannot
3666 determines register usage so we will have to pop the
3668 unsaveRBank (0, ic, FALSE);
3673 /* This ISR uses a non-zero bank.
3675 * Restore any register banks saved by genFunction
3678 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3681 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3683 if (savedBanks & (1 << ix))
3685 unsaveRBank(ix, NULL, FALSE);
3689 if (options.useXstack)
3691 /* Restore bank AFTER calling unsaveRBank,
3692 * since it can trash r0.
3694 emitcode ("pop", "psw");
3698 if (!inExcludeList ("dph"))
3699 emitcode ("pop", "dph");
3700 if (!inExcludeList ("dpl"))
3701 emitcode ("pop", "dpl");
3702 if (!inExcludeList ("b"))
3703 emitcode ("pop", "b");
3704 if (!inExcludeList ("acc"))
3705 emitcode ("pop", "acc");
3707 /* if debug then send end of function */
3708 if (options.debug && currFunc)
3710 debugFile->writeEndFunction (currFunc, ic, 1);
3713 emitcode ("reti", "");
3717 if (IFFUNC_CALLEESAVES(sym->type))
3721 /* if any registers used */
3724 /* save the registers used */
3725 for (i = sym->regsUsed->size; i >= 0; i--)
3727 if (bitVectBitValue (sym->regsUsed, i) ||
3728 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3729 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3732 else if (mcs51_ptrRegReq)
3734 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3735 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3740 /* if debug then send end of function */
3741 if (options.debug && currFunc)
3743 debugFile->writeEndFunction (currFunc, ic, 1);
3746 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3748 emitcode ("ljmp", "__sdcc_banked_ret");
3752 emitcode ("ret", "");
3756 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3759 /* If this was an interrupt handler using bank 0 that called another */
3760 /* function, then all registers must be saved; nothing to optimized. */
3761 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3762 && !FUNC_REGBANK(sym->type))
3765 /* There are no push/pops to optimize if not callee-saves or ISR */
3766 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3769 /* If there were stack parameters, we cannot optimize without also */
3770 /* fixing all of the stack offsets; this is too dificult to consider. */
3771 if (FUNC_HASSTACKPARM(sym->type))
3774 /* Compute the registers actually used */
3775 regsUsed = newBitVect (mcs51_nRegs);
3776 regsUsedPrologue = newBitVect (mcs51_nRegs);
3779 if (lnp->ic && lnp->ic->op == FUNCTION)
3780 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3782 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3784 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3785 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3792 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3793 && !bitVectBitValue (regsUsed, CND_IDX))
3795 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3796 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3797 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3798 bitVectUnSetBit (regsUsed, CND_IDX);
3801 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3803 /* If this was an interrupt handler that called another function */
3804 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3805 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3807 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3808 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3809 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3810 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3811 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3814 /* Remove the unneeded push/pops */
3815 regsUnneeded = newBitVect (mcs51_nRegs);
3818 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3820 if (!strncmp(lnp->line, "push", 4))
3822 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3823 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3825 connectLine (lnp->prev, lnp->next);
3826 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3829 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3831 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3832 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3834 connectLine (lnp->prev, lnp->next);
3835 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3842 for (idx = 0; idx < regsUnneeded->size; idx++)
3843 if (bitVectBitValue (regsUnneeded, idx))
3844 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3846 freeBitVect (regsUnneeded);
3847 freeBitVect (regsUsed);
3848 freeBitVect (regsUsedPrologue);
3851 /*-----------------------------------------------------------------*/
3852 /* genRet - generate code for return statement */
3853 /*-----------------------------------------------------------------*/
3857 int size, offset = 0, pushed = 0;
3859 D(emitcode ("; genRet",""));
3861 /* if we have no return value then
3862 just generate the "ret" */
3866 /* we have something to return then
3867 move the return value into place */
3868 aopOp (IC_LEFT (ic), ic, FALSE);
3869 size = AOP_SIZE (IC_LEFT (ic));
3872 if (IS_BIT(_G.currentFunc->etype))
3874 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3881 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3884 l = aopGet (IC_LEFT (ic), offset++,
3886 emitcode ("push", "%s", l);
3891 l = aopGet (IC_LEFT (ic), offset,
3893 if (strcmp (fReturn[offset], l))
3894 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3901 if (strcmp (fReturn[pushed], "a"))
3902 emitcode ("pop", fReturn[pushed]);
3904 emitcode ("pop", "acc");
3906 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3909 /* generate a jump to the return label
3910 if the next is not the return statement */
3911 if (!(ic->next && ic->next->op == LABEL &&
3912 IC_LABEL (ic->next) == returnLabel))
3914 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3918 /*-----------------------------------------------------------------*/
3919 /* genLabel - generates a label */
3920 /*-----------------------------------------------------------------*/
3922 genLabel (iCode * ic)
3924 /* special case never generate */
3925 if (IC_LABEL (ic) == entryLabel)
3928 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3931 /*-----------------------------------------------------------------*/
3932 /* genGoto - generates a ljmp */
3933 /*-----------------------------------------------------------------*/
3935 genGoto (iCode * ic)
3937 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3940 /*-----------------------------------------------------------------*/
3941 /* findLabelBackwards: walks back through the iCode chain looking */
3942 /* for the given label. Returns number of iCode instructions */
3943 /* between that label and given ic. */
3944 /* Returns zero if label not found. */
3945 /*-----------------------------------------------------------------*/
3947 findLabelBackwards (iCode * ic, int key)
3956 /* If we have any pushes or pops, we cannot predict the distance.
3957 I don't like this at all, this should be dealt with in the
3959 if (ic->op == IPUSH || ic->op == IPOP) {
3963 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3972 /*-----------------------------------------------------------------*/
3973 /* genPlusIncr :- does addition with increment if possible */
3974 /*-----------------------------------------------------------------*/
3976 genPlusIncr (iCode * ic)
3978 unsigned int icount;
3979 unsigned int size = getDataSize (IC_RESULT (ic));
3981 /* will try to generate an increment */
3982 /* if the right side is not a literal
3984 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3987 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3989 D(emitcode ("; genPlusIncr",""));
3991 /* if increment >=16 bits in register or direct space */
3992 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3993 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3994 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
4002 /* If the next instruction is a goto and the goto target
4003 * is < 10 instructions previous to this, we can generate
4004 * jumps straight to that target.
4006 if (ic->next && ic->next->op == GOTO
4007 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4008 && labelRange <= 10)
4010 emitcode (";", "tail increment optimized");
4011 tlbl = IC_LABEL (ic->next);
4016 tlbl = newiTempLabel (NULL);
4019 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4020 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4021 IS_AOP_PREG (IC_RESULT (ic)))
4022 emitcode ("cjne", "%s,#0x00,%05d$",
4023 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4027 emitcode ("clr", "a");
4028 emitcode ("cjne", "a,%s,%05d$",
4029 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4033 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4036 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4037 IS_AOP_PREG (IC_RESULT (ic)))
4038 emitcode ("cjne", "%s,#0x00,%05d$",
4039 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4042 emitcode ("cjne", "a,%s,%05d$",
4043 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4046 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4050 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4051 IS_AOP_PREG (IC_RESULT (ic)))
4052 emitcode ("cjne", "%s,#0x00,%05d$",
4053 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4057 emitcode ("cjne", "a,%s,%05d$",
4058 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4061 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4066 emitcode ("", "%05d$:", tlbl->key + 100);
4071 /* if result is dptr */
4072 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4073 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4074 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4075 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4077 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4083 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4086 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
4087 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
4089 emitcode ("inc", "dptr");
4094 /* if the literal value of the right hand side
4095 is greater than 4 then it is not worth it */
4099 /* if the sizes are greater than 1 then we cannot */
4100 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4101 AOP_SIZE (IC_LEFT (ic)) > 1)
4104 /* we can if the aops of the left & result match or
4105 if they are in registers and the registers are the
4107 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4112 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4113 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4114 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4120 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4129 /*-----------------------------------------------------------------*/
4130 /* outBitAcc - output a bit in acc */
4131 /*-----------------------------------------------------------------*/
4133 outBitAcc (operand * result)
4135 symbol *tlbl = newiTempLabel (NULL);
4136 /* if the result is a bit */
4137 if (AOP_TYPE (result) == AOP_CRY)
4139 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4143 emitcode ("jz", "%05d$", tlbl->key + 100);
4144 emitcode ("mov", "a,%s", one);
4145 emitcode ("", "%05d$:", tlbl->key + 100);
4150 /*-----------------------------------------------------------------*/
4151 /* genPlusBits - generates code for addition of two bits */
4152 /*-----------------------------------------------------------------*/
4154 genPlusBits (iCode * ic)
4156 D(emitcode ("; genPlusBits",""));
4158 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4160 symbol *lbl = newiTempLabel (NULL);
4161 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4162 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4163 emitcode ("cpl", "c");
4164 emitcode ("", "%05d$:", (lbl->key + 100));
4165 outBitC (IC_RESULT (ic));
4169 emitcode ("clr", "a");
4170 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4171 emitcode ("rlc", "a");
4172 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4173 emitcode ("addc", "a,#0x00");
4174 outAcc (IC_RESULT (ic));
4179 /* This is the original version of this code.
4181 * This is being kept around for reference,
4182 * because I am not entirely sure I got it right...
4185 adjustArithmeticResult (iCode * ic)
4187 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4188 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4189 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4190 aopPut (IC_RESULT (ic),
4191 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4193 isOperandVolatile (IC_RESULT (ic), FALSE));
4195 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4196 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4197 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4198 aopPut (IC_RESULT (ic),
4199 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4201 isOperandVolatile (IC_RESULT (ic), FALSE));
4203 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4204 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4205 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4206 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4207 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4210 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4211 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4215 /* This is the pure and virtuous version of this code.
4216 * I'm pretty certain it's right, but not enough to toss the old
4220 adjustArithmeticResult (iCode * ic)
4222 if (opIsGptr (IC_RESULT (ic)) &&
4223 opIsGptr (IC_LEFT (ic)) &&
4224 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4226 aopPut (IC_RESULT (ic),
4227 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4229 isOperandVolatile (IC_RESULT (ic), FALSE));
4232 if (opIsGptr (IC_RESULT (ic)) &&
4233 opIsGptr (IC_RIGHT (ic)) &&
4234 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4236 aopPut (IC_RESULT (ic),
4237 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4239 isOperandVolatile (IC_RESULT (ic), FALSE));
4242 if (opIsGptr (IC_RESULT (ic)) &&
4243 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4244 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4245 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4246 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4249 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4250 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4255 /*-----------------------------------------------------------------*/
4256 /* genPlus - generates code for addition */
4257 /*-----------------------------------------------------------------*/
4259 genPlus (iCode * ic)
4261 int size, offset = 0;
4264 bool swappedLR = FALSE;
4265 operand *leftOp, *rightOp;
4268 /* special cases :- */
4270 D(emitcode ("; genPlus",""));
4272 aopOp (IC_LEFT (ic), ic, FALSE);
4273 aopOp (IC_RIGHT (ic), ic, FALSE);
4274 aopOp (IC_RESULT (ic), ic, TRUE);
4276 /* if literal, literal on the right or
4277 if left requires ACC or right is already
4279 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4280 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4281 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4283 operand *t = IC_RIGHT (ic);
4284 IC_RIGHT (ic) = IC_LEFT (ic);
4289 /* if both left & right are in bit
4291 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4292 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4298 /* if left in bit space & right literal */
4299 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4300 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4302 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4303 /* if result in bit space */
4304 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4306 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4307 emitcode ("cpl", "c");
4308 outBitC (IC_RESULT (ic));
4312 size = getDataSize (IC_RESULT (ic));
4315 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4316 emitcode ("addc", "a,#00");
4317 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4323 /* if I can do an increment instead
4324 of add then GOOD for ME */
4325 if (genPlusIncr (ic) == TRUE)
4328 size = getDataSize (IC_RESULT (ic));
4329 leftOp = IC_LEFT(ic);
4330 rightOp = IC_RIGHT(ic);
4333 /* if this is an add for an array access
4334 at a 256 byte boundary */
4336 && AOP_TYPE (op) == AOP_IMMD
4338 && IS_SPEC (OP_SYM_ETYPE (op))
4339 && SPEC_ABSA (OP_SYM_ETYPE (op))
4340 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4343 D(emitcode ("; genPlus aligned array",""));
4344 aopPut (IC_RESULT (ic),
4345 aopGet (rightOp, 0, FALSE, FALSE),
4347 isOperandVolatile (IC_RESULT (ic), FALSE));
4349 if( 1 == getDataSize (IC_RIGHT (ic)) )
4351 aopPut (IC_RESULT (ic),
4352 aopGet (leftOp, 1, FALSE, FALSE),
4354 isOperandVolatile (IC_RESULT (ic), FALSE));
4358 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4359 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4360 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4365 /* if the lower bytes of a literal are zero skip the addition */
4366 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4368 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4369 (skip_bytes+1 < size))
4374 D(emitcode ("; genPlus shortcut",""));
4379 if( offset >= skip_bytes )
4381 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4384 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4386 emitcode("xch", "a,b");
4387 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4388 emitcode (add, "a,b");
4391 else if (aopGetUsesAcc (leftOp, offset))
4393 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4394 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4398 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4399 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4401 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4402 add = "addc"; /* further adds must propagate carry */
4406 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4407 isOperandVolatile (IC_RESULT (ic), FALSE))
4410 aopPut (IC_RESULT (ic),
4411 aopGet (leftOp, offset, FALSE, FALSE),
4413 isOperandVolatile (IC_RESULT (ic), FALSE));
4419 adjustArithmeticResult (ic);
4422 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4425 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4426 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4430 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4431 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4435 /*-----------------------------------------------------------------*/
4436 /* genMinusDec :- does subtraction with decrement if possible */
4437 /*-----------------------------------------------------------------*/
4439 genMinusDec (iCode * ic)
4441 unsigned int icount;
4442 unsigned int size = getDataSize (IC_RESULT (ic));
4444 /* will try to generate an increment */
4445 /* if the right side is not a literal
4447 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4450 /* if the literal value of the right hand side
4451 is greater than 4 then it is not worth it */
4452 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4455 D(emitcode ("; genMinusDec",""));
4457 /* if decrement >=16 bits in register or direct space */
4458 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4459 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4467 /* If the next instruction is a goto and the goto target
4468 * is <= 10 instructions previous to this, we can generate
4469 * jumps straight to that target.
4471 if (ic->next && ic->next->op == GOTO
4472 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4473 && labelRange <= 10)
4475 emitcode (";", "tail decrement optimized");
4476 tlbl = IC_LABEL (ic->next);
4481 tlbl = newiTempLabel (NULL);
4485 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4486 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4487 IS_AOP_PREG (IC_RESULT (ic)))
4488 emitcode ("cjne", "%s,#0xff,%05d$"
4489 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4493 emitcode ("mov", "a,#0xff");
4494 emitcode ("cjne", "a,%s,%05d$"
4495 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4498 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4501 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4502 IS_AOP_PREG (IC_RESULT (ic)))
4503 emitcode ("cjne", "%s,#0xff,%05d$"
4504 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4508 emitcode ("cjne", "a,%s,%05d$"
4509 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4512 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4516 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4517 IS_AOP_PREG (IC_RESULT (ic)))
4518 emitcode ("cjne", "%s,#0xff,%05d$"
4519 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4523 emitcode ("cjne", "a,%s,%05d$"
4524 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4527 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4531 emitcode ("", "%05d$:", tlbl->key + 100);
4536 /* if the sizes are greater than 1 then we cannot */
4537 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4538 AOP_SIZE (IC_LEFT (ic)) > 1)
4541 /* we can if the aops of the left & result match or
4542 if they are in registers and the registers are the
4544 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4548 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4550 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4555 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4559 emitcode ("dec", "%s", l);
4561 if (AOP_NEEDSACC (IC_RESULT (ic)))
4562 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4570 /*-----------------------------------------------------------------*/
4571 /* addSign - complete with sign */
4572 /*-----------------------------------------------------------------*/
4574 addSign (operand * result, int offset, int sign)
4576 int size = (getDataSize (result) - offset);
4581 emitcode ("rlc", "a");
4582 emitcode ("subb", "a,acc");
4584 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4588 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4592 /*-----------------------------------------------------------------*/
4593 /* genMinusBits - generates code for subtraction of two bits */
4594 /*-----------------------------------------------------------------*/
4596 genMinusBits (iCode * ic)
4598 symbol *lbl = newiTempLabel (NULL);
4600 D(emitcode ("; genMinusBits",""));
4602 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4604 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4605 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4606 emitcode ("cpl", "c");
4607 emitcode ("", "%05d$:", (lbl->key + 100));
4608 outBitC (IC_RESULT (ic));
4612 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4613 emitcode ("subb", "a,acc");
4614 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4615 emitcode ("inc", "a");
4616 emitcode ("", "%05d$:", (lbl->key + 100));
4617 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4618 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4622 /*-----------------------------------------------------------------*/
4623 /* genMinus - generates code for subtraction */
4624 /*-----------------------------------------------------------------*/
4626 genMinus (iCode * ic)
4628 int size, offset = 0;
4630 D(emitcode ("; genMinus",""));
4632 aopOp (IC_LEFT (ic), ic, FALSE);
4633 aopOp (IC_RIGHT (ic), ic, FALSE);
4634 aopOp (IC_RESULT (ic), ic, TRUE);
4636 /* special cases :- */
4637 /* if both left & right are in bit space */
4638 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4639 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4645 /* if I can do an decrement instead
4646 of subtract then GOOD for ME */
4647 if (genMinusDec (ic) == TRUE)
4650 size = getDataSize (IC_RESULT (ic));
4652 /* if literal, add a,#-lit, else normal subb */
4653 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4655 unsigned long lit = 0L;
4656 bool useCarry = FALSE;
4658 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4663 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4665 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4666 if (!offset && !size && lit== (unsigned long) -1)
4668 emitcode ("dec", "a");
4672 /* first add without previous c */
4673 emitcode ("add", "a,#0x%02x",
4674 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4679 emitcode ("addc", "a,#0x%02x",
4680 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4682 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4686 /* no need to add zeroes */
4687 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4689 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4690 offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4698 operand *leftOp, *rightOp;
4700 leftOp = IC_LEFT(ic);
4701 rightOp = IC_RIGHT(ic);
4705 if (aopGetUsesAcc(rightOp, offset)) {
4706 if (aopGetUsesAcc(leftOp, offset)) {
4709 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4711 emitcode ("mov", "b,a");
4714 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4715 emitcode ("subb", "a,b");
4718 /* reverse subtraction with 2's complement */
4720 emitcode( "setb", "c");
4722 emitcode( "cpl", "c");
4723 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4724 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4725 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4726 emitcode("cpl", "a");
4727 if (size) /* skip if last byte */
4728 emitcode( "cpl", "c");
4731 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4734 emitcode ("subb", "a,%s",
4735 aopGet(rightOp, offset, FALSE, TRUE));
4738 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4743 adjustArithmeticResult (ic);
4746 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4747 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4748 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4752 /*-----------------------------------------------------------------*/
4753 /* genMultbits :- multiplication of bits */
4754 /*-----------------------------------------------------------------*/
4756 genMultbits (operand * left,
4760 D(emitcode ("; genMultbits",""));
4762 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4763 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4767 /*-----------------------------------------------------------------*/
4768 /* genMultOneByte : 8*8=8/16 bit multiplication */
4769 /*-----------------------------------------------------------------*/
4771 genMultOneByte (operand * left,
4776 int size = AOP_SIZE (result);
4777 bool runtimeSign, compiletimeSign;
4778 bool lUnsigned, rUnsigned, pushedB;
4780 D(emitcode ("; genMultOneByte",""));
4782 if (size < 1 || size > 2)
4784 /* this should never happen */
4785 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4786 AOP_SIZE(result), __FILE__, lineno);
4790 /* (if two literals: the value is computed before) */
4791 /* if one literal, literal on the right */
4792 if (AOP_TYPE (left) == AOP_LIT)
4797 /* emitcode (";", "swapped left and right"); */
4799 /* if no literal, unsigned on the right: shorter code */
4800 if ( AOP_TYPE (right) != AOP_LIT
4801 && SPEC_USIGN (getSpec (operandType (left))))
4808 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4809 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4813 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4814 no need to take care about the signedness! */
4815 || (lUnsigned && rUnsigned))
4817 /* just an unsigned 8 * 8 = 8 multiply
4819 /* emitcode (";","unsigned"); */
4820 /* TODO: check for accumulator clash between left & right aops? */
4822 if (AOP_TYPE (right) == AOP_LIT)
4824 /* moving to accumulator first helps peepholes */
4825 MOVA (aopGet (left, 0, FALSE, FALSE));
4826 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4830 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4831 MOVA (aopGet (left, 0, FALSE, FALSE));
4834 emitcode ("mul", "ab");
4835 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4837 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4843 /* we have to do a signed multiply */
4844 /* emitcode (";", "signed"); */
4846 /* now sign adjust for both left & right */
4848 /* let's see what's needed: */
4849 /* apply negative sign during runtime */
4850 runtimeSign = FALSE;
4851 /* negative sign from literals */
4852 compiletimeSign = FALSE;
4856 if (AOP_TYPE(left) == AOP_LIT)
4858 /* signed literal */
4859 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4861 compiletimeSign = TRUE;
4864 /* signed but not literal */
4870 if (AOP_TYPE(right) == AOP_LIT)
4872 /* signed literal */
4873 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4875 compiletimeSign ^= TRUE;
4878 /* signed but not literal */
4882 /* initialize F0, which stores the runtime sign */
4885 if (compiletimeSign)
4886 emitcode ("setb", "F0"); /* set sign flag */
4888 emitcode ("clr", "F0"); /* reset sign flag */
4891 /* save the signs of the operands */
4892 if (AOP_TYPE(right) == AOP_LIT)
4894 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4896 if (!rUnsigned && val < 0)
4897 emitcode ("mov", "b,#0x%02x", -val);
4899 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4901 else /* ! literal */
4903 if (rUnsigned) /* emitcode (";", "signed"); */
4905 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4908 MOVA (aopGet (right, 0, FALSE, FALSE));
4909 lbl = newiTempLabel (NULL);
4910 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4911 emitcode ("cpl", "F0"); /* complement sign flag */
4912 emitcode ("cpl", "a"); /* 2's complement */
4913 emitcode ("inc", "a");
4914 emitcode ("", "%05d$:", (lbl->key + 100));
4915 emitcode ("mov", "b,a");
4919 if (AOP_TYPE(left) == AOP_LIT)
4921 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4923 if (!lUnsigned && val < 0)
4924 emitcode ("mov", "a,#0x%02x", -val);
4926 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4928 else /* ! literal */
4930 MOVA (aopGet (left, 0, FALSE, FALSE));
4934 lbl = newiTempLabel (NULL);
4935 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4936 emitcode ("cpl", "F0"); /* complement sign flag */
4937 emitcode ("cpl", "a"); /* 2's complement */
4938 emitcode ("inc", "a");
4939 emitcode ("", "%05d$:", (lbl->key + 100));
4943 /* now the multiplication */
4944 emitcode ("mul", "ab");
4945 if (runtimeSign || compiletimeSign)
4947 lbl = newiTempLabel (NULL);
4949 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4950 emitcode ("cpl", "a"); /* lsb 2's complement */
4952 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4955 emitcode ("add", "a,#1"); /* this sets carry flag */
4956 emitcode ("xch", "a,b");
4957 emitcode ("cpl", "a"); /* msb 2's complement */
4958 emitcode ("addc", "a,#0");
4959 emitcode ("xch", "a,b");
4961 emitcode ("", "%05d$:", (lbl->key + 100));
4963 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4965 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4970 /*-----------------------------------------------------------------*/
4971 /* genMult - generates code for multiplication */
4972 /*-----------------------------------------------------------------*/
4974 genMult (iCode * ic)
4976 operand *left = IC_LEFT (ic);
4977 operand *right = IC_RIGHT (ic);
4978 operand *result = IC_RESULT (ic);
4980 D(emitcode ("; genMult",""));
4982 /* assign the asmops */
4983 aopOp (left, ic, FALSE);
4984 aopOp (right, ic, FALSE);
4985 aopOp (result, ic, TRUE);
4987 /* special cases first */
4989 if (AOP_TYPE (left) == AOP_CRY &&
4990 AOP_TYPE (right) == AOP_CRY)
4992 genMultbits (left, right, result);
4996 /* if both are of size == 1 */
4997 #if 0 // one of them can be a sloc shared with the result
4998 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
5000 if (getSize(operandType(left)) == 1 &&
5001 getSize(operandType(right)) == 1)
5004 genMultOneByte (left, right, result);
5008 /* should have been converted to function call */
5009 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5010 getSize(OP_SYMBOL(right)->type));
5014 freeAsmop (result, NULL, ic, TRUE);
5015 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5016 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5019 /*-----------------------------------------------------------------*/
5020 /* genDivbits :- division of bits */
5021 /*-----------------------------------------------------------------*/
5023 genDivbits (operand * left,
5030 D(emitcode ("; genDivbits",""));
5034 /* the result must be bit */
5035 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5036 l = aopGet (left, 0, FALSE, FALSE);
5040 emitcode ("div", "ab");
5041 emitcode ("rrc", "a");
5045 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5048 /*-----------------------------------------------------------------*/
5049 /* genDivOneByte : 8 bit division */
5050 /*-----------------------------------------------------------------*/
5052 genDivOneByte (operand * left,
5056 bool lUnsigned, rUnsigned, pushedB;
5057 bool runtimeSign, compiletimeSign;
5058 bool accuse = FALSE;
5059 bool pushedA = FALSE;
5063 D(emitcode ("; genDivOneByte",""));
5065 /* Why is it necessary that genDivOneByte() can return an int result?
5068 volatile unsigned char uc;
5069 volatile signed char sc1, sc2;
5082 In all cases a one byte result would overflow, the following cast to int
5083 would return the wrong result.
5085 Two possible solution:
5086 a) cast operands to int, if ((unsigned) / (signed)) or
5087 ((signed) / (signed))
5088 b) return an 16 bit signed int; this is what we're doing here!
5091 size = AOP_SIZE (result) - 1;
5093 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5094 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5098 /* signed or unsigned */
5099 if (lUnsigned && rUnsigned)
5101 /* unsigned is easy */
5102 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5103 MOVA (aopGet (left, 0, FALSE, FALSE));
5104 emitcode ("div", "ab");
5105 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5107 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5113 /* signed is a little bit more difficult */
5115 /* now sign adjust for both left & right */
5117 /* let's see what's needed: */
5118 /* apply negative sign during runtime */
5119 runtimeSign = FALSE;
5120 /* negative sign from literals */
5121 compiletimeSign = FALSE;
5125 if (AOP_TYPE(left) == AOP_LIT)
5127 /* signed literal */
5128 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5130 compiletimeSign = TRUE;
5133 /* signed but not literal */
5139 if (AOP_TYPE(right) == AOP_LIT)
5141 /* signed literal */
5142 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5144 compiletimeSign ^= TRUE;
5147 /* signed but not literal */
5151 /* initialize F0, which stores the runtime sign */
5154 if (compiletimeSign)
5155 emitcode ("setb", "F0"); /* set sign flag */
5157 emitcode ("clr", "F0"); /* reset sign flag */
5160 /* save the signs of the operands */
5161 if (AOP_TYPE(right) == AOP_LIT)
5163 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5165 if (!rUnsigned && val < 0)
5166 emitcode ("mov", "b,#0x%02x", -val);
5168 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5170 else /* ! literal */
5173 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5176 MOVA (aopGet (right, 0, FALSE, FALSE));
5177 lbl = newiTempLabel (NULL);
5178 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5179 emitcode ("cpl", "F0"); /* complement sign flag */
5180 emitcode ("cpl", "a"); /* 2's complement */
5181 emitcode ("inc", "a");
5182 emitcode ("", "%05d$:", (lbl->key + 100));
5183 emitcode ("mov", "b,a");
5187 if (AOP_TYPE(left) == AOP_LIT)
5189 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5191 if (!lUnsigned && val < 0)
5192 emitcode ("mov", "a,#0x%02x", -val);
5194 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5196 else /* ! literal */
5198 MOVA (aopGet (left, 0, FALSE, FALSE));
5202 lbl = newiTempLabel (NULL);
5203 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5204 emitcode ("cpl", "F0"); /* complement sign flag */
5205 emitcode ("cpl", "a"); /* 2's complement */
5206 emitcode ("inc", "a");
5207 emitcode ("", "%05d$:", (lbl->key + 100));
5211 /* now the division */
5212 emitcode ("div", "ab");
5214 if (runtimeSign || compiletimeSign)
5216 lbl = newiTempLabel (NULL);
5218 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5219 emitcode ("cpl", "a"); /* lsb 2's complement */
5220 emitcode ("inc", "a");
5221 emitcode ("", "%05d$:", (lbl->key + 100));
5223 accuse = aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5226 /* msb is 0x00 or 0xff depending on the sign */
5231 emitcode ("push", "acc");
5234 emitcode ("mov", "c,F0");
5235 emitcode ("subb", "a,acc");
5237 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5239 else /* compiletimeSign */
5241 if (aopPutUsesAcc (result, "#0xFF", offset))
5243 emitcode ("push", "acc");
5247 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5253 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5255 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5259 emitcode ("pop", "acc");
5263 /*-----------------------------------------------------------------*/
5264 /* genDiv - generates code for division */
5265 /*-----------------------------------------------------------------*/
5269 operand *left = IC_LEFT (ic);
5270 operand *right = IC_RIGHT (ic);
5271 operand *result = IC_RESULT (ic);
5273 D(emitcode ("; genDiv",""));
5275 /* assign the amsops */
5276 aopOp (left, ic, FALSE);
5277 aopOp (right, ic, FALSE);
5278 aopOp (result, ic, TRUE);
5280 /* special cases first */
5282 if (AOP_TYPE (left) == AOP_CRY &&
5283 AOP_TYPE (right) == AOP_CRY)
5285 genDivbits (left, right, result);
5289 /* if both are of size == 1 */
5290 if (AOP_SIZE (left) == 1 &&
5291 AOP_SIZE (right) == 1)
5293 genDivOneByte (left, right, result);
5297 /* should have been converted to function call */
5300 freeAsmop (result, NULL, ic, TRUE);
5301 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5302 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5305 /*-----------------------------------------------------------------*/
5306 /* genModbits :- modulus of bits */
5307 /*-----------------------------------------------------------------*/
5309 genModbits (operand * left,
5316 D(emitcode ("; genModbits",""));
5320 /* the result must be bit */
5321 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5322 l = aopGet (left, 0, FALSE, FALSE);
5326 emitcode ("div", "ab");
5327 emitcode ("mov", "a,b");
5328 emitcode ("rrc", "a");
5332 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5335 /*-----------------------------------------------------------------*/
5336 /* genModOneByte : 8 bit modulus */
5337 /*-----------------------------------------------------------------*/
5339 genModOneByte (operand * left,
5343 bool lUnsigned, rUnsigned, pushedB;
5344 bool runtimeSign, compiletimeSign;
5348 D(emitcode ("; genModOneByte",""));
5350 size = AOP_SIZE (result) - 1;
5352 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5353 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5355 /* if right is a literal, check it for 2^n */
5356 if (AOP_TYPE(right) == AOP_LIT)
5358 unsigned char val = abs((int) operandLitValue(right));
5359 symbol *lbl2 = NULL;
5363 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5372 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5373 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5374 /* because iCode should have been changed to genAnd */
5375 /* see file "SDCCopt.c", function "convertToFcall()" */
5377 MOVA (aopGet (left, 0, FALSE, FALSE));
5378 emitcode ("mov", "c,acc.7");
5379 emitcode ("anl", "a,#0x%02x", val - 1);
5380 lbl = newiTempLabel (NULL);
5381 emitcode ("jz", "%05d$", (lbl->key + 100));
5382 emitcode ("jnc", "%05d$", (lbl->key + 100));
5383 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5389 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5391 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5392 lbl2 = newiTempLabel (NULL);
5393 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5395 emitcode ("", "%05d$:", (lbl->key + 100));
5396 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5398 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5401 emitcode ("", "%05d$:", (lbl2->key + 100));
5412 /* signed or unsigned */
5413 if (lUnsigned && rUnsigned)
5415 /* unsigned is easy */
5416 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5417 MOVA (aopGet (left, 0, FALSE, FALSE));
5418 emitcode ("div", "ab");
5419 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5421 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5427 /* signed is a little bit more difficult */
5429 /* now sign adjust for both left & right */
5431 /* modulus: sign of the right operand has no influence on the result! */
5432 if (AOP_TYPE(right) == AOP_LIT)
5434 signed char val = (char) operandLitValue(right);
5436 if (!rUnsigned && val < 0)
5437 emitcode ("mov", "b,#0x%02x", -val);
5439 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5441 else /* not literal */
5444 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5447 MOVA (aopGet (right, 0, FALSE, FALSE));
5448 lbl = newiTempLabel (NULL);
5449 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5450 emitcode ("cpl", "a"); /* 2's complement */
5451 emitcode ("inc", "a");
5452 emitcode ("", "%05d$:", (lbl->key + 100));
5453 emitcode ("mov", "b,a");
5457 /* let's see what's needed: */
5458 /* apply negative sign during runtime */
5459 runtimeSign = FALSE;
5460 /* negative sign from literals */
5461 compiletimeSign = FALSE;
5463 /* sign adjust left side */
5464 if (AOP_TYPE(left) == AOP_LIT)
5466 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5468 if (!lUnsigned && val < 0)
5470 compiletimeSign = TRUE; /* set sign flag */
5471 emitcode ("mov", "a,#0x%02x", -val);
5474 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5476 else /* ! literal */
5478 MOVA (aopGet (left, 0, FALSE, FALSE));
5483 emitcode ("clr", "F0"); /* clear sign flag */
5485 lbl = newiTempLabel (NULL);
5486 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5487 emitcode ("setb", "F0"); /* set sign flag */
5488 emitcode ("cpl", "a"); /* 2's complement */
5489 emitcode ("inc", "a");
5490 emitcode ("", "%05d$:", (lbl->key + 100));
5494 /* now the modulus */
5495 emitcode ("div", "ab");
5497 if (runtimeSign || compiletimeSign)
5499 emitcode ("mov", "a,b");
5500 lbl = newiTempLabel (NULL);
5502 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5503 emitcode ("cpl", "a"); /* 2's complement */
5504 emitcode ("inc", "a");
5505 emitcode ("", "%05d$:", (lbl->key + 100));
5507 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5510 /* msb is 0x00 or 0xff depending on the sign */
5513 emitcode ("mov", "c,F0");
5514 emitcode ("subb", "a,acc");
5516 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5518 else /* compiletimeSign */
5520 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5525 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5527 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5533 /*-----------------------------------------------------------------*/
5534 /* genMod - generates code for division */
5535 /*-----------------------------------------------------------------*/
5539 operand *left = IC_LEFT (ic);
5540 operand *right = IC_RIGHT (ic);
5541 operand *result = IC_RESULT (ic);
5543 D(emitcode ("; genMod",""));
5545 /* assign the asmops */
5546 aopOp (left, ic, FALSE);
5547 aopOp (right, ic, FALSE);
5548 aopOp (result, ic, TRUE);
5550 /* special cases first */
5552 if (AOP_TYPE (left) == AOP_CRY &&
5553 AOP_TYPE (right) == AOP_CRY)
5555 genModbits (left, right, result);
5559 /* if both are of size == 1 */
5560 if (AOP_SIZE (left) == 1 &&
5561 AOP_SIZE (right) == 1)
5563 genModOneByte (left, right, result);
5567 /* should have been converted to function call */
5571 freeAsmop (result, NULL, ic, TRUE);
5572 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5573 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5576 /*-----------------------------------------------------------------*/
5577 /* genIfxJump :- will create a jump depending on the ifx */
5578 /*-----------------------------------------------------------------*/
5580 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5583 symbol *tlbl = newiTempLabel (NULL);
5586 D(emitcode ("; genIfxJump",""));
5588 /* if true label then we jump if condition
5592 jlbl = IC_TRUE (ic);
5593 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5594 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5598 /* false label is present */
5599 jlbl = IC_FALSE (ic);
5600 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5601 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5603 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5604 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5606 emitcode (inst, "%05d$", tlbl->key + 100);
5607 freeForBranchAsmop (result);
5608 freeForBranchAsmop (right);
5609 freeForBranchAsmop (left);
5610 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5611 emitcode ("", "%05d$:", tlbl->key + 100);
5613 /* mark the icode as generated */
5617 /*-----------------------------------------------------------------*/
5618 /* genCmp :- greater or less than comparison */
5619 /*-----------------------------------------------------------------*/
5621 genCmp (operand * left, operand * right,
5622 operand * result, iCode * ifx, int sign, iCode *ic)
5624 int size, offset = 0;
5625 unsigned long lit = 0L;
5628 D(emitcode ("; genCmp",""));
5630 /* if left & right are bit variables */
5631 if (AOP_TYPE (left) == AOP_CRY &&
5632 AOP_TYPE (right) == AOP_CRY)
5634 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5635 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5639 /* subtract right from left if at the
5640 end the carry flag is set then we know that
5641 left is greater than right */
5642 size = max (AOP_SIZE (left), AOP_SIZE (right));
5644 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5645 if ((size == 1) && !sign &&
5646 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5648 symbol *lbl = newiTempLabel (NULL);
5649 emitcode ("cjne", "%s,%s,%05d$",
5650 aopGet (left, offset, FALSE, FALSE),
5651 aopGet (right, offset, FALSE, FALSE),
5653 emitcode ("", "%05d$:", lbl->key + 100);
5657 if (AOP_TYPE (right) == AOP_LIT)
5659 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5660 /* optimize if(x < 0) or if(x >= 0) */
5669 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5670 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5672 genIfxJump (ifx, "acc.7", left, right, result);
5673 freeAsmop (right, NULL, ic, TRUE);
5674 freeAsmop (left, NULL, ic, TRUE);
5679 emitcode ("rlc", "a");
5687 bool pushedB = FALSE;
5688 rightInB = aopGetUsesAcc(right, offset);
5692 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5694 MOVA (aopGet (left, offset, FALSE, FALSE));
5695 if (sign && size == 0)
5697 emitcode ("xrl", "a,#0x80");
5698 if (AOP_TYPE (right) == AOP_LIT)
5700 unsigned long lit = (unsigned long)
5701 floatFromVal (AOP (right)->aopu.aop_lit);
5702 emitcode ("subb", "a,#0x%02x",
5703 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5711 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5713 emitcode ("xrl", "b,#0x80");
5714 emitcode ("subb", "a,b");
5720 emitcode ("subb", "a,b");
5722 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5732 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5733 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5734 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5740 /* if the result is used in the next
5741 ifx conditional branch then generate
5742 code a little differently */
5744 genIfxJump (ifx, "c", NULL, NULL, result);
5747 /* leave the result in acc */
5751 /*-----------------------------------------------------------------*/
5752 /* genCmpGt :- greater than comparison */
5753 /*-----------------------------------------------------------------*/
5755 genCmpGt (iCode * ic, iCode * ifx)
5757 operand *left, *right, *result;
5758 sym_link *letype, *retype;
5761 D(emitcode ("; genCmpGt",""));
5763 left = IC_LEFT (ic);
5764 right = IC_RIGHT (ic);
5765 result = IC_RESULT (ic);
5767 letype = getSpec (operandType (left));
5768 retype = getSpec (operandType (right));
5769 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5770 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5771 /* assign the amsops */
5772 aopOp (result, ic, TRUE);
5773 aopOp (left, ic, FALSE);
5774 aopOp (right, ic, FALSE);
5776 genCmp (right, left, result, ifx, sign, ic);
5778 freeAsmop (result, NULL, ic, TRUE);
5781 /*-----------------------------------------------------------------*/
5782 /* genCmpLt - less than comparisons */
5783 /*-----------------------------------------------------------------*/
5785 genCmpLt (iCode * ic, iCode * ifx)
5787 operand *left, *right, *result;
5788 sym_link *letype, *retype;
5791 D(emitcode ("; genCmpLt",""));
5793 left = IC_LEFT (ic);
5794 right = IC_RIGHT (ic);
5795 result = IC_RESULT (ic);
5797 letype = getSpec (operandType (left));
5798 retype = getSpec (operandType (right));
5799 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5800 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5801 /* assign the amsops */
5802 aopOp (result, ic, TRUE);
5803 aopOp (left, ic, FALSE);
5804 aopOp (right, ic, FALSE);
5806 genCmp (left, right, result, ifx, sign, ic);
5808 freeAsmop (result, NULL, ic, TRUE);
5811 /*-----------------------------------------------------------------*/
5812 /* gencjneshort - compare and jump if not equal */
5813 /*-----------------------------------------------------------------*/
5815 gencjneshort (operand * left, operand * right, symbol * lbl)
5817 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5819 unsigned long lit = 0L;
5821 /* if the left side is a literal or
5822 if the right is in a pointer register and left
5824 if ((AOP_TYPE (left) == AOP_LIT) ||
5825 (AOP_TYPE (left) == AOP_IMMD) ||
5826 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5833 if (AOP_TYPE (right) == AOP_LIT)
5834 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5836 /* if the right side is a literal then anything goes */
5837 if (AOP_TYPE (right) == AOP_LIT &&
5838 AOP_TYPE (left) != AOP_DIR &&
5839 AOP_TYPE (left) != AOP_IMMD)
5843 emitcode ("cjne", "%s,%s,%05d$",
5844 aopGet (left, offset, FALSE, FALSE),
5845 aopGet (right, offset, FALSE, FALSE),
5851 /* if the right side is in a register or in direct space or
5852 if the left is a pointer register & right is not */
5853 else if (AOP_TYPE (right) == AOP_REG ||
5854 AOP_TYPE (right) == AOP_DIR ||
5855 AOP_TYPE (right) == AOP_LIT ||
5856 AOP_TYPE (right) == AOP_IMMD ||
5857 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5858 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5862 MOVA (aopGet (left, offset, FALSE, FALSE));
5863 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5864 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5865 emitcode ("jnz", "%05d$", lbl->key + 100);
5867 emitcode ("cjne", "a,%s,%05d$",
5868 aopGet (right, offset, FALSE, TRUE),
5875 /* right is a pointer reg need both a & b */
5879 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5880 wassertl(!BINUSE, "B was in use");
5881 l = aopGet (left, offset, FALSE, FALSE);
5882 if (strcmp (l, "b"))
5883 emitcode ("mov", "b,%s", l);
5884 MOVA (aopGet (right, offset, FALSE, FALSE));
5885 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5891 /*-----------------------------------------------------------------*/
5892 /* gencjne - compare and jump if not equal */
5893 /*-----------------------------------------------------------------*/
5895 gencjne (operand * left, operand * right, symbol * lbl)
5897 symbol *tlbl = newiTempLabel (NULL);
5899 gencjneshort (left, right, lbl);
5901 emitcode ("mov", "a,%s", one);
5902 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5903 emitcode ("", "%05d$:", lbl->key + 100);
5904 emitcode ("clr", "a");
5905 emitcode ("", "%05d$:", tlbl->key + 100);
5908 /*-----------------------------------------------------------------*/
5909 /* genCmpEq - generates code for equal to */
5910 /*-----------------------------------------------------------------*/
5912 genCmpEq (iCode * ic, iCode * ifx)
5914 bool swappedLR = FALSE;
5915 operand *left, *right, *result;
5917 D(emitcode ("; genCmpEq",""));
5919 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5920 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5921 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5923 /* if literal, literal on the right or
5924 if the right is in a pointer register and left
5926 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5927 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5929 operand *t = IC_RIGHT (ic);
5930 IC_RIGHT (ic) = IC_LEFT (ic);
5935 if (ifx && !AOP_SIZE (result))
5938 /* if they are both bit variables */
5939 if (AOP_TYPE (left) == AOP_CRY &&
5940 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5942 if (AOP_TYPE (right) == AOP_LIT)
5944 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5947 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5948 emitcode ("cpl", "c");
5952 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5956 emitcode ("clr", "c");
5958 /* AOP_TYPE(right) == AOP_CRY */
5962 symbol *lbl = newiTempLabel (NULL);
5963 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5964 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5965 emitcode ("cpl", "c");
5966 emitcode ("", "%05d$:", (lbl->key + 100));
5968 /* if true label then we jump if condition
5970 tlbl = newiTempLabel (NULL);
5973 emitcode ("jnc", "%05d$", tlbl->key + 100);
5974 freeForBranchAsmop (result);
5975 freeForBranchAsmop (right);
5976 freeForBranchAsmop (left);
5977 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5981 emitcode ("jc", "%05d$", tlbl->key + 100);
5982 freeForBranchAsmop (result);
5983 freeForBranchAsmop (right);
5984 freeForBranchAsmop (left);
5985 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5987 emitcode ("", "%05d$:", tlbl->key + 100);
5991 tlbl = newiTempLabel (NULL);
5992 gencjneshort (left, right, tlbl);
5995 freeForBranchAsmop (result);
5996 freeForBranchAsmop (right);
5997 freeForBranchAsmop (left);
5998 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5999 emitcode ("", "%05d$:", tlbl->key + 100);
6003 symbol *lbl = newiTempLabel (NULL);
6004 emitcode ("sjmp", "%05d$", lbl->key + 100);
6005 emitcode ("", "%05d$:", tlbl->key + 100);
6006 freeForBranchAsmop (result);
6007 freeForBranchAsmop (right);
6008 freeForBranchAsmop (left);
6009 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6010 emitcode ("", "%05d$:", lbl->key + 100);
6013 /* mark the icode as generated */
6018 /* if they are both bit variables */
6019 if (AOP_TYPE (left) == AOP_CRY &&
6020 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6022 if (AOP_TYPE (right) == AOP_LIT)
6024 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6027 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6028 emitcode ("cpl", "c");
6032 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6036 emitcode ("clr", "c");
6038 /* AOP_TYPE(right) == AOP_CRY */
6042 symbol *lbl = newiTempLabel (NULL);
6043 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6044 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6045 emitcode ("cpl", "c");
6046 emitcode ("", "%05d$:", (lbl->key + 100));
6049 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6056 genIfxJump (ifx, "c", left, right, result);
6059 /* if the result is used in an arithmetic operation
6060 then put the result in place */
6065 gencjne (left, right, newiTempLabel (NULL));
6066 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6068 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6073 genIfxJump (ifx, "a", left, right, result);
6076 /* if the result is used in an arithmetic operation
6077 then put the result in place */
6078 if (AOP_TYPE (result) != AOP_CRY)
6080 /* leave the result in acc */
6084 freeAsmop (result, NULL, ic, TRUE);
6087 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6088 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6092 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6093 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6097 /*-----------------------------------------------------------------*/
6098 /* ifxForOp - returns the icode containing the ifx for operand */
6099 /*-----------------------------------------------------------------*/
6101 ifxForOp (operand * op, iCode * ic)
6103 /* if true symbol then needs to be assigned */
6104 if (IS_TRUE_SYMOP (op))
6107 /* if this has register type condition and
6108 the next instruction is ifx with the same operand
6109 and live to of the operand is upto the ifx only then */
6111 ic->next->op == IFX &&
6112 IC_COND (ic->next)->key == op->key &&
6113 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6119 /*-----------------------------------------------------------------*/
6120 /* hasInc - operand is incremented before any other use */
6121 /*-----------------------------------------------------------------*/
6123 hasInc (operand *op, iCode *ic,int osize)
6125 sym_link *type = operandType(op);
6126 sym_link *retype = getSpec (type);
6127 iCode *lic = ic->next;
6130 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6131 if (!IS_SYMOP(op)) return NULL;
6133 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6134 if (IS_AGGREGATE(type->next)) return NULL;
6135 if (osize != (isize = getSize(type->next))) return NULL;
6138 /* if operand of the form op = op + <sizeof *op> */
6139 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6140 isOperandEqual(IC_RESULT(lic),op) &&
6141 isOperandLiteral(IC_RIGHT(lic)) &&
6142 operandLitValue(IC_RIGHT(lic)) == isize) {
6145 /* if the operand used or deffed */
6146 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6149 /* if GOTO or IFX */
6150 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6156 /*-----------------------------------------------------------------*/
6157 /* genAndOp - for && operation */
6158 /*-----------------------------------------------------------------*/
6160 genAndOp (iCode * ic)
6162 operand *left, *right, *result;
6165 D(emitcode ("; genAndOp",""));
6167 /* note here that && operations that are in an
6168 if statement are taken away by backPatchLabels
6169 only those used in arthmetic operations remain */
6170 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6171 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6172 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6174 /* if both are bit variables */
6175 if (AOP_TYPE (left) == AOP_CRY &&
6176 AOP_TYPE (right) == AOP_CRY)
6178 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6179 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6184 tlbl = newiTempLabel (NULL);
6186 emitcode ("jz", "%05d$", tlbl->key + 100);
6188 emitcode ("", "%05d$:", tlbl->key + 100);
6192 freeAsmop (result, NULL, ic, TRUE);
6193 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6194 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6198 /*-----------------------------------------------------------------*/
6199 /* genOrOp - for || operation */
6200 /*-----------------------------------------------------------------*/
6202 genOrOp (iCode * ic)
6204 operand *left, *right, *result;
6207 D(emitcode ("; genOrOp",""));
6209 /* note here that || operations that are in an
6210 if statement are taken away by backPatchLabels
6211 only those used in arthmetic operations remain */
6212 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6213 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6214 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6216 /* if both are bit variables */
6217 if (AOP_TYPE (left) == AOP_CRY &&
6218 AOP_TYPE (right) == AOP_CRY)
6220 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6221 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6226 tlbl = newiTempLabel (NULL);
6228 emitcode ("jnz", "%05d$", tlbl->key + 100);
6230 emitcode ("", "%05d$:", tlbl->key + 100);
6234 freeAsmop (result, NULL, ic, TRUE);
6235 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6236 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6239 /*-----------------------------------------------------------------*/
6240 /* isLiteralBit - test if lit == 2^n */
6241 /*-----------------------------------------------------------------*/
6243 isLiteralBit (unsigned long lit)
6245 unsigned long pw[32] =
6246 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6247 0x100L, 0x200L, 0x400L, 0x800L,
6248 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6249 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6250 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6251 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6252 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6255 for (idx = 0; idx < 32; idx++)
6261 /*-----------------------------------------------------------------*/
6262 /* continueIfTrue - */
6263 /*-----------------------------------------------------------------*/
6265 continueIfTrue (iCode * ic)
6268 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6272 /*-----------------------------------------------------------------*/
6274 /*-----------------------------------------------------------------*/
6276 jumpIfTrue (iCode * ic)
6279 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6283 /*-----------------------------------------------------------------*/
6284 /* jmpTrueOrFalse - */
6285 /*-----------------------------------------------------------------*/
6287 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6289 // ugly but optimized by peephole
6292 symbol *nlbl = newiTempLabel (NULL);
6293 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6294 emitcode ("", "%05d$:", tlbl->key + 100);
6295 freeForBranchAsmop (result);
6296 freeForBranchAsmop (right);
6297 freeForBranchAsmop (left);
6298 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6299 emitcode ("", "%05d$:", nlbl->key + 100);
6303 freeForBranchAsmop (result);
6304 freeForBranchAsmop (right);
6305 freeForBranchAsmop (left);
6306 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6307 emitcode ("", "%05d$:", tlbl->key + 100);
6312 /*-----------------------------------------------------------------*/
6313 /* genAnd - code for and */
6314 /*-----------------------------------------------------------------*/
6316 genAnd (iCode * ic, iCode * ifx)
6318 operand *left, *right, *result;
6319 int size, offset = 0;
6320 unsigned long lit = 0L;
6324 D(emitcode ("; genAnd",""));
6326 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6327 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6328 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6331 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6333 AOP_TYPE (left), AOP_TYPE (right));
6334 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6336 AOP_SIZE (left), AOP_SIZE (right));
6339 /* if left is a literal & right is not then exchange them */
6340 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6341 AOP_NEEDSACC (left))
6343 operand *tmp = right;
6348 /* if result = right then exchange left and right */
6349 if (sameRegs (AOP (result), AOP (right)))
6351 operand *tmp = right;
6356 /* if right is bit then exchange them */
6357 if (AOP_TYPE (right) == AOP_CRY &&
6358 AOP_TYPE (left) != AOP_CRY)
6360 operand *tmp = right;
6364 if (AOP_TYPE (right) == AOP_LIT)
6365 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6367 size = AOP_SIZE (result);
6370 // result = bit & yy;
6371 if (AOP_TYPE (left) == AOP_CRY)
6373 // c = bit & literal;
6374 if (AOP_TYPE (right) == AOP_LIT)
6378 if (size && sameRegs (AOP (result), AOP (left)))
6381 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6386 if (size && (AOP_TYPE (result) == AOP_CRY))
6388 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6391 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6396 emitcode ("clr", "c");
6401 if (AOP_TYPE (right) == AOP_CRY)
6404 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6405 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6410 MOVA (aopGet (right, 0, FALSE, FALSE));
6412 emitcode ("rrc", "a");
6413 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6421 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6422 genIfxJump (ifx, "c", left, right, result);
6426 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6427 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6428 if ((AOP_TYPE (right) == AOP_LIT) &&
6429 (AOP_TYPE (result) == AOP_CRY) &&
6430 (AOP_TYPE (left) != AOP_CRY))
6432 int posbit = isLiteralBit (lit);
6437 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6441 switch (posbit & 0x07)
6443 case 0: emitcode ("rrc", "a");
6445 case 7: emitcode ("rlc", "a");
6447 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6456 SNPRINTF (buffer, sizeof(buffer),
6457 "acc.%d", posbit & 0x07);
6458 genIfxJump (ifx, buffer, left, right, result);
6461 {// what is this case? just found it in ds390/gen.c
6462 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6469 symbol *tlbl = newiTempLabel (NULL);
6470 int sizel = AOP_SIZE (left);
6472 emitcode ("setb", "c");
6475 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6477 MOVA (aopGet (left, offset, FALSE, FALSE));
6479 if ((posbit = isLiteralBit (bytelit)) != 0)
6480 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6483 if (bytelit != 0x0FFL)
6484 emitcode ("anl", "a,%s",
6485 aopGet (right, offset, FALSE, TRUE));
6486 emitcode ("jnz", "%05d$", tlbl->key + 100);
6491 // bit = left & literal
6494 emitcode ("clr", "c");
6495 emitcode ("", "%05d$:", tlbl->key + 100);
6497 // if(left & literal)
6501 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6503 emitcode ("", "%05d$:", tlbl->key + 100);
6511 /* if left is same as result */
6512 if (sameRegs (AOP (result), AOP (left)))
6514 for (; size--; offset++)
6516 if (AOP_TYPE (right) == AOP_LIT)
6518 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6519 if (bytelit == 0x0FF)
6521 /* dummy read of volatile operand */
6522 if (isOperandVolatile (left, FALSE))
6523 MOVA (aopGet (left, offset, FALSE, FALSE));
6527 else if (bytelit == 0)
6529 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6531 else if (IS_AOP_PREG (result))
6533 MOVA (aopGet (left, offset, FALSE, TRUE));
6534 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6535 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6538 emitcode ("anl", "%s,%s",
6539 aopGet (left, offset, FALSE, TRUE),
6540 aopGet (right, offset, FALSE, FALSE));
6544 if (AOP_TYPE (left) == AOP_ACC)
6547 emitcode("mov", "a,b");
6548 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6550 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6552 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6553 MOVA (aopGet (right, offset, FALSE, FALSE));
6554 emitcode ("anl", "a,b");
6555 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6557 else if (aopGetUsesAcc (left, offset))
6559 MOVA (aopGet (left, offset, FALSE, FALSE));
6560 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6561 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6565 MOVA (aopGet (right, offset, FALSE, FALSE));
6566 if (IS_AOP_PREG (result))
6568 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6569 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6572 emitcode ("anl", "%s,a",
6573 aopGet (left, offset, FALSE, TRUE));
6580 // left & result in different registers
6581 if (AOP_TYPE (result) == AOP_CRY)
6584 // if(size), result in bit
6585 // if(!size && ifx), conditional oper: if(left & right)
6586 symbol *tlbl = newiTempLabel (NULL);
6587 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6589 emitcode ("setb", "c");
6592 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6593 && AOP_TYPE(left)==AOP_ACC)
6596 emitcode("mov", "a,b");
6597 emitcode ("anl", "a,%s",
6598 aopGet (right, offset, FALSE, FALSE));
6600 if (AOP_TYPE(left)==AOP_ACC)
6604 bool pushedB = pushB ();
6605 emitcode("mov", "b,a");
6606 MOVA (aopGet (right, offset, FALSE, FALSE));
6607 emitcode("anl", "a,b");
6612 MOVA (aopGet (right, offset, FALSE, FALSE));
6613 emitcode("anl", "a,b");
6616 MOVA (aopGet (right, offset, FALSE, FALSE));
6617 emitcode ("anl", "a,%s",
6618 aopGet (left, offset, FALSE, FALSE));
6621 emitcode ("jnz", "%05d$", tlbl->key + 100);
6627 emitcode ("", "%05d$:", tlbl->key + 100);
6631 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6633 emitcode ("", "%05d$:", tlbl->key + 100);
6637 for (; (size--); offset++)
6640 // result = left & right
6641 if (AOP_TYPE (right) == AOP_LIT)
6643 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6644 if (bytelit == 0x0FF)
6647 aopGet (left, offset, FALSE, FALSE),
6649 isOperandVolatile (result, FALSE));
6652 else if (bytelit == 0)
6654 /* dummy read of volatile operand */
6655 if (isOperandVolatile (left, FALSE))
6656 MOVA (aopGet (left, offset, FALSE, FALSE));
6657 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6660 else if (AOP_TYPE (left) == AOP_ACC)
6664 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6665 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6670 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6671 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6676 // faster than result <- left, anl result,right
6677 // and better if result is SFR
6678 if (AOP_TYPE (left) == AOP_ACC)
6681 emitcode("mov", "a,b");
6682 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6684 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6686 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6687 MOVA (aopGet (right, offset, FALSE, FALSE));
6688 emitcode ("anl", "a,b");
6690 else if (aopGetUsesAcc (left, offset))
6692 MOVA (aopGet (left, offset, FALSE, FALSE));
6693 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6697 MOVA (aopGet (right, offset, FALSE, FALSE));
6698 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6700 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6706 freeAsmop (result, NULL, ic, TRUE);
6707 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6708 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6711 /*-----------------------------------------------------------------*/
6712 /* genOr - code for or */
6713 /*-----------------------------------------------------------------*/
6715 genOr (iCode * ic, iCode * ifx)
6717 operand *left, *right, *result;
6718 int size, offset = 0;
6719 unsigned long lit = 0L;
6722 D(emitcode ("; genOr",""));
6724 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6725 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6726 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6729 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6731 AOP_TYPE (left), AOP_TYPE (right));
6732 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6734 AOP_SIZE (left), AOP_SIZE (right));
6737 /* if left is a literal & right is not then exchange them */
6738 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6739 AOP_NEEDSACC (left))
6741 operand *tmp = right;
6746 /* if result = right then exchange them */
6747 if (sameRegs (AOP (result), AOP (right)))
6749 operand *tmp = right;
6754 /* if right is bit then exchange them */
6755 if (AOP_TYPE (right) == AOP_CRY &&
6756 AOP_TYPE (left) != AOP_CRY)
6758 operand *tmp = right;
6762 if (AOP_TYPE (right) == AOP_LIT)
6763 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6765 size = AOP_SIZE (result);
6769 if (AOP_TYPE (left) == AOP_CRY)
6771 if (AOP_TYPE (right) == AOP_LIT)
6773 // c = bit | literal;
6776 // lit != 0 => result = 1
6777 if (AOP_TYPE (result) == AOP_CRY)
6780 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6782 continueIfTrue (ifx);
6785 emitcode ("setb", "c");
6789 // lit == 0 => result = left
6790 if (size && sameRegs (AOP (result), AOP (left)))
6792 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6797 if (AOP_TYPE (right) == AOP_CRY)
6800 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6801 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6806 symbol *tlbl = newiTempLabel (NULL);
6807 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6808 emitcode ("setb", "c");
6809 emitcode ("jb", "%s,%05d$",
6810 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6812 emitcode ("jnz", "%05d$", tlbl->key + 100);
6813 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6815 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6821 emitcode ("", "%05d$:", tlbl->key + 100);
6830 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6831 genIfxJump (ifx, "c", left, right, result);
6835 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6836 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6837 if ((AOP_TYPE (right) == AOP_LIT) &&
6838 (AOP_TYPE (result) == AOP_CRY) &&
6839 (AOP_TYPE (left) != AOP_CRY))
6845 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6847 continueIfTrue (ifx);
6852 // lit = 0, result = boolean(left)
6854 emitcode ("setb", "c");
6858 symbol *tlbl = newiTempLabel (NULL);
6859 emitcode ("jnz", "%05d$", tlbl->key + 100);
6861 emitcode ("", "%05d$:", tlbl->key + 100);
6865 genIfxJump (ifx, "a", left, right, result);
6873 /* if left is same as result */
6874 if (sameRegs (AOP (result), AOP (left)))
6876 for (; size--; offset++)
6878 if (AOP_TYPE (right) == AOP_LIT)
6880 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6883 /* dummy read of volatile operand */
6884 if (isOperandVolatile (left, FALSE))
6885 MOVA (aopGet (left, offset, FALSE, FALSE));
6889 else if (bytelit == 0x0FF)
6891 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6893 else if (IS_AOP_PREG (left))
6895 MOVA (aopGet (left, offset, FALSE, TRUE));
6896 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6897 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6901 emitcode ("orl", "%s,%s",
6902 aopGet (left, offset, FALSE, TRUE),
6903 aopGet (right, offset, FALSE, FALSE));
6908 if (AOP_TYPE (left) == AOP_ACC)
6911 emitcode("mov", "a,b");
6912 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6914 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6916 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6917 MOVA (aopGet (right, offset, FALSE, FALSE));
6918 emitcode ("orl", "a,b");
6919 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6921 else if (aopGetUsesAcc (left, offset))
6923 MOVA (aopGet (left, offset, FALSE, FALSE));
6924 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6925 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6929 MOVA (aopGet (right, offset, FALSE, FALSE));
6930 if (IS_AOP_PREG (left))
6932 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6933 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6937 emitcode ("orl", "%s,a",
6938 aopGet (left, offset, FALSE, TRUE));
6946 // left & result in different registers
6947 if (AOP_TYPE (result) == AOP_CRY)
6950 // if(size), result in bit
6951 // if(!size && ifx), conditional oper: if(left | right)
6952 symbol *tlbl = newiTempLabel (NULL);
6953 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6955 emitcode ("setb", "c");
6958 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6960 emitcode("mov", "a,b");
6961 emitcode ("orl", "a,%s",
6962 aopGet (right, offset, FALSE, FALSE));
6964 MOVA (aopGet (right, offset, FALSE, FALSE));
6965 emitcode ("orl", "a,%s",
6966 aopGet (left, offset, FALSE, FALSE));
6968 emitcode ("jnz", "%05d$", tlbl->key + 100);
6974 emitcode ("", "%05d$:", tlbl->key + 100);
6978 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6980 emitcode ("", "%05d$:", tlbl->key + 100);
6984 for (; (size--); offset++)
6987 // result = left | right
6988 if (AOP_TYPE (right) == AOP_LIT)
6990 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6994 aopGet (left, offset, FALSE, FALSE),
6996 isOperandVolatile (result, FALSE));
6999 else if (bytelit == 0x0FF)
7001 /* dummy read of volatile operand */
7002 if (isOperandVolatile (left, FALSE))
7003 MOVA (aopGet (left, offset, FALSE, FALSE));
7004 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
7008 // faster than result <- left, anl result,right
7009 // and better if result is SFR
7010 if (AOP_TYPE (left) == AOP_ACC)
7013 emitcode("mov", "a,b");
7014 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7016 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7018 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7019 MOVA (aopGet (right, offset, FALSE, FALSE));
7020 emitcode ("orl", "a,b");
7022 else if (aopGetUsesAcc (left, offset))
7024 MOVA (aopGet (left, offset, FALSE, FALSE));
7025 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7029 MOVA (aopGet (right, offset, FALSE, FALSE));
7030 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7032 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7038 freeAsmop (result, NULL, ic, TRUE);
7039 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7040 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7043 /*-----------------------------------------------------------------*/
7044 /* genXor - code for xclusive or */
7045 /*-----------------------------------------------------------------*/
7047 genXor (iCode * ic, iCode * ifx)
7049 operand *left, *right, *result;
7050 int size, offset = 0;
7051 unsigned long lit = 0L;
7054 D(emitcode ("; genXor",""));
7056 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7057 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7058 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7061 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7063 AOP_TYPE (left), AOP_TYPE (right));
7064 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7066 AOP_SIZE (left), AOP_SIZE (right));
7069 /* if left is a literal & right is not ||
7070 if left needs acc & right does not */
7071 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7072 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7074 operand *tmp = right;
7079 /* if result = right then exchange them */
7080 if (sameRegs (AOP (result), AOP (right)))
7082 operand *tmp = right;
7087 /* if right is bit then exchange them */
7088 if (AOP_TYPE (right) == AOP_CRY &&
7089 AOP_TYPE (left) != AOP_CRY)
7091 operand *tmp = right;
7095 if (AOP_TYPE (right) == AOP_LIT)
7096 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7098 size = AOP_SIZE (result);
7102 if (AOP_TYPE (left) == AOP_CRY)
7104 if (AOP_TYPE (right) == AOP_LIT)
7106 // c = bit & literal;
7109 // lit>>1 != 0 => result = 1
7110 if (AOP_TYPE (result) == AOP_CRY)
7113 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7115 continueIfTrue (ifx);
7118 emitcode ("setb", "c");
7125 // lit == 0, result = left
7126 if (size && sameRegs (AOP (result), AOP (left)))
7128 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7132 // lit == 1, result = not(left)
7133 if (size && sameRegs (AOP (result), AOP (left)))
7135 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7140 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7141 emitcode ("cpl", "c");
7150 symbol *tlbl = newiTempLabel (NULL);
7151 if (AOP_TYPE (right) == AOP_CRY)
7154 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7158 int sizer = AOP_SIZE (right);
7160 // if val>>1 != 0, result = 1
7161 emitcode ("setb", "c");
7164 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7166 // test the msb of the lsb
7167 emitcode ("anl", "a,#0xfe");
7168 emitcode ("jnz", "%05d$", tlbl->key + 100);
7172 emitcode ("rrc", "a");
7174 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7175 emitcode ("cpl", "c");
7176 emitcode ("", "%05d$:", (tlbl->key + 100));
7183 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7184 genIfxJump (ifx, "c", left, right, result);
7188 /* if left is same as result */
7189 if (sameRegs (AOP (result), AOP (left)))
7191 for (; size--; offset++)
7193 if (AOP_TYPE (right) == AOP_LIT)
7195 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7198 /* dummy read of volatile operand */
7199 if (isOperandVolatile (left, FALSE))
7200 MOVA (aopGet (left, offset, FALSE, FALSE));
7204 else if (IS_AOP_PREG (left))
7206 MOVA (aopGet (left, offset, FALSE, TRUE));
7207 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7208 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7212 emitcode ("xrl", "%s,%s",
7213 aopGet (left, offset, FALSE, TRUE),
7214 aopGet (right, offset, FALSE, FALSE));
7219 if (AOP_TYPE (left) == AOP_ACC)
7222 emitcode("mov", "a,b");
7223 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7225 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7227 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7228 MOVA (aopGet (right, offset, FALSE, FALSE));
7229 emitcode ("xrl", "a,b");
7230 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7232 else if (aopGetUsesAcc (left, offset))
7234 MOVA (aopGet (left, offset, FALSE, FALSE));
7235 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7236 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7240 MOVA (aopGet (right, offset, FALSE, FALSE));
7241 if (IS_AOP_PREG (left))
7243 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7244 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7247 emitcode ("xrl", "%s,a",
7248 aopGet (left, offset, FALSE, TRUE));
7255 // left & result in different registers
7256 if (AOP_TYPE (result) == AOP_CRY)
7259 // if(size), result in bit
7260 // if(!size && ifx), conditional oper: if(left ^ right)
7261 symbol *tlbl = newiTempLabel (NULL);
7262 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7264 emitcode ("setb", "c");
7267 if ((AOP_TYPE (right) == AOP_LIT) &&
7268 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7270 MOVA (aopGet (left, offset, FALSE, FALSE));
7274 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7276 emitcode("mov", "a,b");
7277 emitcode ("xrl", "a,%s",
7278 aopGet (right, offset, FALSE, FALSE));
7280 MOVA (aopGet (right, offset, FALSE, FALSE));
7281 emitcode ("xrl", "a,%s",
7282 aopGet (left, offset, FALSE, FALSE));
7285 emitcode ("jnz", "%05d$", tlbl->key + 100);
7291 emitcode ("", "%05d$:", tlbl->key + 100);
7295 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7299 for (; (size--); offset++)
7302 // result = left & right
7303 if (AOP_TYPE (right) == AOP_LIT)
7305 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7309 aopGet (left, offset, FALSE, FALSE),
7311 isOperandVolatile (result, FALSE));
7315 // faster than result <- left, anl result,right
7316 // and better if result is SFR
7317 if (AOP_TYPE (left) == AOP_ACC)
7320 emitcode("mov", "a,b");
7321 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7323 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7325 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7326 MOVA (aopGet (right, offset, FALSE, FALSE));
7327 emitcode ("xrl", "a,b");
7329 else if (aopGetUsesAcc (left, offset))
7331 MOVA (aopGet (left, offset, FALSE, FALSE));
7332 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7336 MOVA (aopGet (right, offset, FALSE, FALSE));
7337 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7339 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7345 freeAsmop (result, NULL, ic, TRUE);
7346 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7347 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7350 /*-----------------------------------------------------------------*/
7351 /* genInline - write the inline code out */
7352 /*-----------------------------------------------------------------*/
7354 genInline (iCode * ic)
7356 char *buffer, *bp, *bp1;
7358 D(emitcode ("; genInline",""));
7360 _G.inLine += (!options.asmpeep);
7362 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7363 strcpy (buffer, IC_INLINE (ic));
7365 /* emit each line as a code */
7376 /* Add \n for labels, not dirs such as c:\mydir */
7377 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7391 /* emitcode("",buffer); */
7392 _G.inLine -= (!options.asmpeep);
7395 /*-----------------------------------------------------------------*/
7396 /* genRRC - rotate right with carry */
7397 /*-----------------------------------------------------------------*/
7401 operand *left, *result;
7402 int size, offset = 0;
7405 D(emitcode ("; genRRC",""));
7407 /* rotate right with carry */
7408 left = IC_LEFT (ic);
7409 result = IC_RESULT (ic);
7410 aopOp (left, ic, FALSE);
7411 aopOp (result, ic, FALSE);
7413 /* move it to the result */
7414 size = AOP_SIZE (result);
7416 if (size == 1) { /* special case for 1 byte */
7417 l = aopGet (left, offset, FALSE, FALSE);
7419 emitcode ("rr", "a");
7422 /* no need to clear carry, bit7 will be written later */
7425 l = aopGet (left, offset, FALSE, FALSE);
7427 emitcode ("rrc", "a");
7428 if (AOP_SIZE (result) > 1)
7429 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7431 /* now we need to put the carry into the
7432 highest order byte of the result */
7433 if (AOP_SIZE (result) > 1)
7435 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7438 emitcode ("mov", "acc.7,c");
7440 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7441 freeAsmop (result, NULL, ic, TRUE);
7442 freeAsmop (left, NULL, ic, TRUE);
7445 /*-----------------------------------------------------------------*/
7446 /* genRLC - generate code for rotate left with carry */
7447 /*-----------------------------------------------------------------*/
7451 operand *left, *result;
7452 int size, offset = 0;
7455 D(emitcode ("; genRLC",""));
7457 /* rotate right with carry */
7458 left = IC_LEFT (ic);
7459 result = IC_RESULT (ic);
7460 aopOp (left, ic, FALSE);
7461 aopOp (result, ic, FALSE);
7463 /* move it to the result */
7464 size = AOP_SIZE (result);
7468 l = aopGet (left, offset, FALSE, FALSE);
7470 if (size == 0) { /* special case for 1 byte */
7474 emitcode("rlc","a"); /* bit0 will be written later */
7475 if (AOP_SIZE (result) > 1)
7476 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7479 l = aopGet (left, offset, FALSE, FALSE);
7481 emitcode ("rlc", "a");
7482 if (AOP_SIZE (result) > 1)
7483 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7486 /* now we need to put the carry into the
7487 highest order byte of the result */
7488 if (AOP_SIZE (result) > 1)
7490 l = aopGet (result, 0, FALSE, FALSE);
7493 emitcode ("mov", "acc.0,c");
7495 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7496 freeAsmop (result, NULL, ic, TRUE);
7497 freeAsmop (left, NULL, ic, TRUE);
7500 /*-----------------------------------------------------------------*/
7501 /* genGetHbit - generates code get highest order bit */
7502 /*-----------------------------------------------------------------*/
7504 genGetHbit (iCode * ic)
7506 operand *left, *result;
7508 D(emitcode ("; genGetHbit",""));
7510 left = IC_LEFT (ic);
7511 result = IC_RESULT (ic);
7512 aopOp (left, ic, FALSE);
7513 aopOp (result, ic, FALSE);
7515 /* get the highest order byte into a */
7516 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7517 if (AOP_TYPE (result) == AOP_CRY)
7519 emitcode ("rlc", "a");
7524 emitcode ("rl", "a");
7525 emitcode ("anl", "a,#0x01");
7529 freeAsmop (result, NULL, ic, TRUE);
7530 freeAsmop (left, NULL, ic, TRUE);
7533 /*-----------------------------------------------------------------*/
7534 /* genGetAbit - generates code get a single bit */
7535 /*-----------------------------------------------------------------*/
7537 genGetAbit (iCode * ic)
7539 operand *left, *right, *result;
7542 D(emitcode ("; genGetAbit",""));
7544 left = IC_LEFT (ic);
7545 right = IC_RIGHT (ic);
7546 result = IC_RESULT (ic);
7547 aopOp (left, ic, FALSE);
7548 aopOp (right, ic, FALSE);
7549 aopOp (result, ic, FALSE);
7551 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7553 /* get the needed byte into a */
7554 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7556 if (AOP_TYPE (result) == AOP_CRY)
7559 emitcode ("rlc", "a");
7560 else if ((shCount) == 0)
7561 emitcode ("rrc", "a");
7563 emitcode ("mov", "c,acc[%d]", shCount);
7571 emitcode ("rr", "a");
7574 emitcode ("rr", "a");
7577 emitcode ("anl", "a,#0x01");
7581 emitcode ("mov", "c,acc[%d]", shCount);
7582 emitcode ("clr", "a");
7583 emitcode ("rlc", "a");
7586 emitcode ("swap", "a");
7587 emitcode ("anl", "a,#0x01");
7590 emitcode ("rl", "a");
7593 emitcode ("rl", "a");
7594 emitcode ("anl", "a,#0x01");
7600 freeAsmop (result, NULL, ic, TRUE);
7601 freeAsmop (right, NULL, ic, TRUE);
7602 freeAsmop (left, NULL, ic, TRUE);
7605 /*-----------------------------------------------------------------*/
7606 /* genGetByte - generates code get a single byte */
7607 /*-----------------------------------------------------------------*/
7609 genGetByte (iCode * ic)
7611 operand *left, *right, *result;
7614 D(emitcode ("; genGetByte",""));
7616 left = IC_LEFT (ic);
7617 right = IC_RIGHT (ic);
7618 result = IC_RESULT (ic);
7619 aopOp (left, ic, FALSE);
7620 aopOp (right, ic, FALSE);
7621 aopOp (result, ic, FALSE);
7623 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7625 aopGet (left, offset, FALSE, FALSE),
7627 isOperandVolatile (result, FALSE));
7629 freeAsmop (result, NULL, ic, TRUE);
7630 freeAsmop (right, NULL, ic, TRUE);
7631 freeAsmop (left, NULL, ic, TRUE);
7634 /*-----------------------------------------------------------------*/
7635 /* genGetWord - generates code get two bytes */
7636 /*-----------------------------------------------------------------*/
7638 genGetWord (iCode * ic)
7640 operand *left, *right, *result;
7643 D(emitcode ("; genGetWord",""));
7645 left = IC_LEFT (ic);
7646 right = IC_RIGHT (ic);
7647 result = IC_RESULT (ic);
7648 aopOp (left, ic, FALSE);
7649 aopOp (right, ic, FALSE);
7650 aopOp (result, ic, FALSE);
7652 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7654 aopGet (left, offset, FALSE, FALSE),
7656 isOperandVolatile (result, FALSE));
7658 aopGet (left, offset+1, FALSE, FALSE),
7660 isOperandVolatile (result, FALSE));
7662 freeAsmop (result, NULL, ic, TRUE);
7663 freeAsmop (right, NULL, ic, TRUE);
7664 freeAsmop (left, NULL, ic, TRUE);
7667 /*-----------------------------------------------------------------*/
7668 /* genSwap - generates code to swap nibbles or bytes */
7669 /*-----------------------------------------------------------------*/
7671 genSwap (iCode * ic)
7673 operand *left, *result;
7675 D(emitcode ("; genSwap",""));
7677 left = IC_LEFT (ic);
7678 result = IC_RESULT (ic);
7679 aopOp (left, ic, FALSE);
7680 aopOp (result, ic, FALSE);
7682 switch (AOP_SIZE (left))
7684 case 1: /* swap nibbles in byte */
7685 MOVA (aopGet (left, 0, FALSE, FALSE));
7686 emitcode ("swap", "a");
7687 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7689 case 2: /* swap bytes in word */
7690 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7692 MOVA (aopGet (left, 0, FALSE, FALSE));
7693 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7694 0, isOperandVolatile (result, FALSE));
7695 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7697 else if (operandsEqu (left, result))
7700 bool pushedB = FALSE, leftInB = FALSE;
7702 MOVA (aopGet (left, 0, FALSE, FALSE));
7703 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7706 emitcode ("mov", "b,a");
7710 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7711 0, isOperandVolatile (result, FALSE));
7712 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7719 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7720 0, isOperandVolatile (result, FALSE));
7721 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7722 1, isOperandVolatile (result, FALSE));
7726 wassertl(FALSE, "unsupported SWAP operand size");
7729 freeAsmop (result, NULL, ic, TRUE);
7730 freeAsmop (left, NULL, ic, TRUE);
7734 /*-----------------------------------------------------------------*/
7735 /* AccRol - rotate left accumulator by known count */
7736 /*-----------------------------------------------------------------*/
7738 AccRol (int shCount)
7740 shCount &= 0x0007; // shCount : 0..7
7747 emitcode ("rl", "a");
7750 emitcode ("rl", "a");
7751 emitcode ("rl", "a");
7754 emitcode ("swap", "a");
7755 emitcode ("rr", "a");
7758 emitcode ("swap", "a");
7761 emitcode ("swap", "a");
7762 emitcode ("rl", "a");
7765 emitcode ("rr", "a");
7766 emitcode ("rr", "a");
7769 emitcode ("rr", "a");
7774 /*-----------------------------------------------------------------*/
7775 /* AccLsh - left shift accumulator by known count */
7776 /*-----------------------------------------------------------------*/
7778 AccLsh (int shCount)
7783 emitcode ("add", "a,acc");
7784 else if (shCount == 2)
7786 emitcode ("add", "a,acc");
7787 emitcode ("add", "a,acc");
7791 /* rotate left accumulator */
7793 /* and kill the lower order bits */
7794 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7799 /*-----------------------------------------------------------------*/
7800 /* AccRsh - right shift accumulator by known count */
7801 /*-----------------------------------------------------------------*/
7803 AccRsh (int shCount)
7810 emitcode ("rrc", "a");
7814 /* rotate right accumulator */
7815 AccRol (8 - shCount);
7816 /* and kill the higher order bits */
7817 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7822 /*-----------------------------------------------------------------*/
7823 /* AccSRsh - signed right shift accumulator by known count */
7824 /*-----------------------------------------------------------------*/
7826 AccSRsh (int shCount)
7833 emitcode ("mov", "c,acc.7");
7834 emitcode ("rrc", "a");
7836 else if (shCount == 2)
7838 emitcode ("mov", "c,acc.7");
7839 emitcode ("rrc", "a");
7840 emitcode ("mov", "c,acc.7");
7841 emitcode ("rrc", "a");
7845 tlbl = newiTempLabel (NULL);
7846 /* rotate right accumulator */
7847 AccRol (8 - shCount);
7848 /* and kill the higher order bits */
7849 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7850 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7851 emitcode ("orl", "a,#0x%02x",
7852 (unsigned char) ~SRMask[shCount]);
7853 emitcode ("", "%05d$:", tlbl->key + 100);
7858 /*-----------------------------------------------------------------*/
7859 /* shiftR1Left2Result - shift right one byte from left to result */
7860 /*-----------------------------------------------------------------*/
7862 shiftR1Left2Result (operand * left, int offl,
7863 operand * result, int offr,
7864 int shCount, int sign)
7866 MOVA (aopGet (left, offl, FALSE, FALSE));
7867 /* shift right accumulator */
7872 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7875 /*-----------------------------------------------------------------*/
7876 /* shiftL1Left2Result - shift left one byte from left to result */
7877 /*-----------------------------------------------------------------*/
7879 shiftL1Left2Result (operand * left, int offl,
7880 operand * result, int offr, int shCount)
7883 l = aopGet (left, offl, FALSE, FALSE);
7885 /* shift left accumulator */
7887 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7890 /*-----------------------------------------------------------------*/
7891 /* movLeft2Result - move byte from left to result */
7892 /*-----------------------------------------------------------------*/
7894 movLeft2Result (operand * left, int offl,
7895 operand * result, int offr, int sign)
7898 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7900 l = aopGet (left, offl, FALSE, FALSE);
7902 if (*l == '@' && (IS_AOP_PREG (result)))
7904 emitcode ("mov", "a,%s", l);
7905 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7910 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7913 /* MSB sign in acc.7 ! */
7914 if (getDataSize (left) == offl + 1)
7917 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7924 /*-----------------------------------------------------------------*/
7925 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7926 /*-----------------------------------------------------------------*/
7930 emitcode ("rrc", "a");
7931 emitcode ("xch", "a,%s", x);
7932 emitcode ("rrc", "a");
7933 emitcode ("xch", "a,%s", x);
7936 /*-----------------------------------------------------------------*/
7937 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7938 /*-----------------------------------------------------------------*/
7942 emitcode ("xch", "a,%s", x);
7943 emitcode ("rlc", "a");
7944 emitcode ("xch", "a,%s", x);
7945 emitcode ("rlc", "a");
7948 /*-----------------------------------------------------------------*/
7949 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7950 /*-----------------------------------------------------------------*/
7954 emitcode ("xch", "a,%s", x);
7955 emitcode ("add", "a,acc");
7956 emitcode ("xch", "a,%s", x);
7957 emitcode ("rlc", "a");
7960 /*-----------------------------------------------------------------*/
7961 /* AccAXLsh - left shift a:x by known count (0..7) */
7962 /*-----------------------------------------------------------------*/
7964 AccAXLsh (char *x, int shCount)
7979 case 5: // AAAAABBB:CCCCCDDD
7981 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7983 emitcode ("anl", "a,#0x%02x",
7984 SLMask[shCount]); // BBB00000:CCCCCDDD
7986 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7988 AccRol (shCount); // DDDCCCCC:BBB00000
7990 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7992 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7994 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7996 emitcode ("anl", "a,#0x%02x",
7997 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7999 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
8001 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8004 case 6: // AAAAAABB:CCCCCCDD
8005 emitcode ("anl", "a,#0x%02x",
8006 SRMask[shCount]); // 000000BB:CCCCCCDD
8007 emitcode ("mov", "c,acc.0"); // c = B
8008 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8010 AccAXRrl1 (x); // BCCCCCCD:D000000B
8011 AccAXRrl1 (x); // BBCCCCCC:DD000000
8013 emitcode("rrc","a");
8014 emitcode("xch","a,%s", x);
8015 emitcode("rrc","a");
8016 emitcode("mov","c,acc.0"); //<< get correct bit
8017 emitcode("xch","a,%s", x);
8019 emitcode("rrc","a");
8020 emitcode("xch","a,%s", x);
8021 emitcode("rrc","a");
8022 emitcode("xch","a,%s", x);
8025 case 7: // a:x <<= 7
8027 emitcode ("anl", "a,#0x%02x",
8028 SRMask[shCount]); // 0000000B:CCCCCCCD
8030 emitcode ("mov", "c,acc.0"); // c = B
8032 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8034 AccAXRrl1 (x); // BCCCCCCC:D0000000
8042 /*-----------------------------------------------------------------*/
8043 /* AccAXRsh - right shift a:x known count (0..7) */
8044 /*-----------------------------------------------------------------*/
8046 AccAXRsh (char *x, int shCount)
8054 AccAXRrl1 (x); // 0->a:x
8059 AccAXRrl1 (x); // 0->a:x
8062 AccAXRrl1 (x); // 0->a:x
8067 case 5: // AAAAABBB:CCCCCDDD = a:x
8069 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8071 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8073 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8075 emitcode ("anl", "a,#0x%02x",
8076 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8078 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8080 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8082 emitcode ("anl", "a,#0x%02x",
8083 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8085 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8087 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8089 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8092 case 6: // AABBBBBB:CCDDDDDD
8094 emitcode ("mov", "c,acc.7");
8095 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8097 emitcode ("mov", "c,acc.7");
8098 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8100 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8102 emitcode ("anl", "a,#0x%02x",
8103 SRMask[shCount]); // 000000AA:BBBBBBCC
8106 case 7: // ABBBBBBB:CDDDDDDD
8108 emitcode ("mov", "c,acc.7"); // c = A
8110 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8112 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8114 emitcode ("anl", "a,#0x%02x",
8115 SRMask[shCount]); // 0000000A:BBBBBBBC
8123 /*-----------------------------------------------------------------*/
8124 /* AccAXRshS - right shift signed a:x known count (0..7) */
8125 /*-----------------------------------------------------------------*/
8127 AccAXRshS (char *x, int shCount)
8135 emitcode ("mov", "c,acc.7");
8136 AccAXRrl1 (x); // s->a:x
8140 emitcode ("mov", "c,acc.7");
8141 AccAXRrl1 (x); // s->a:x
8143 emitcode ("mov", "c,acc.7");
8144 AccAXRrl1 (x); // s->a:x
8149 case 5: // AAAAABBB:CCCCCDDD = a:x
8151 tlbl = newiTempLabel (NULL);
8152 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8154 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8156 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8158 emitcode ("anl", "a,#0x%02x",
8159 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8161 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8163 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8165 emitcode ("anl", "a,#0x%02x",
8166 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8168 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8170 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8172 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8174 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8175 emitcode ("orl", "a,#0x%02x",
8176 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8178 emitcode ("", "%05d$:", tlbl->key + 100);
8179 break; // SSSSAAAA:BBBCCCCC
8181 case 6: // AABBBBBB:CCDDDDDD
8183 tlbl = newiTempLabel (NULL);
8184 emitcode ("mov", "c,acc.7");
8185 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8187 emitcode ("mov", "c,acc.7");
8188 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8190 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8192 emitcode ("anl", "a,#0x%02x",
8193 SRMask[shCount]); // 000000AA:BBBBBBCC
8195 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8196 emitcode ("orl", "a,#0x%02x",
8197 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8199 emitcode ("", "%05d$:", tlbl->key + 100);
8201 case 7: // ABBBBBBB:CDDDDDDD
8203 tlbl = newiTempLabel (NULL);
8204 emitcode ("mov", "c,acc.7"); // c = A
8206 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8208 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8210 emitcode ("anl", "a,#0x%02x",
8211 SRMask[shCount]); // 0000000A:BBBBBBBC
8213 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8214 emitcode ("orl", "a,#0x%02x",
8215 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8217 emitcode ("", "%05d$:", tlbl->key + 100);
8224 /*-----------------------------------------------------------------*/
8225 /* shiftL2Left2Result - shift left two bytes from left to result */
8226 /*-----------------------------------------------------------------*/
8228 shiftL2Left2Result (operand * left, int offl,
8229 operand * result, int offr, int shCount)
8232 bool pushedB = FALSE;
8235 if (sameRegs (AOP (result), AOP (left)) &&
8236 ((offl + MSB16) == offr))
8238 /* don't crash result[offr] */
8239 MOVA (aopGet (left, offl, FALSE, FALSE));
8240 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8241 x = aopGet (result, offr, FALSE, FALSE);
8243 else if (aopGetUsesAcc (result, offr))
8245 movLeft2Result (left, offl, result, offr, 0);
8248 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8249 MOVA (aopGet (result, offr, FALSE, FALSE));
8250 emitcode ("xch", "a,b");
8255 movLeft2Result (left, offl, result, offr, 0);
8256 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8257 x = aopGet (result, offr, FALSE, FALSE);
8259 /* ax << shCount (x = lsb(result)) */
8260 AccAXLsh (x, shCount);
8263 emitcode ("xch", "a,b");
8264 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8265 aopPut (result, "b", offr + MSB16, isOperandVolatile (result, FALSE));
8270 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8275 /*-----------------------------------------------------------------*/
8276 /* shiftR2Left2Result - shift right two bytes from left to result */
8277 /*-----------------------------------------------------------------*/
8279 shiftR2Left2Result (operand * left, int offl,
8280 operand * result, int offr,
8281 int shCount, int sign)
8284 bool pushedB = FALSE;
8287 if (sameRegs (AOP (result), AOP (left)) &&
8288 ((offl + MSB16) == offr))
8290 /* don't crash result[offr] */
8291 MOVA (aopGet (left, offl, FALSE, FALSE));
8292 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8293 x = aopGet (result, offr, FALSE, FALSE);
8295 else if (aopGetUsesAcc (result, offr))
8297 movLeft2Result (left, offl, result, offr, 0);
8300 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8301 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8306 movLeft2Result (left, offl, result, offr, 0);
8307 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8308 x = aopGet (result, offr, FALSE, FALSE);
8310 /* a:x >> shCount (x = lsb(result)) */
8312 AccAXRshS (x, shCount);
8314 AccAXRsh (x, shCount);
8317 emitcode ("xch", "a,b");
8318 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8319 emitcode ("xch", "a,b");
8322 if (getDataSize (result) > 1)
8323 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8326 /*-----------------------------------------------------------------*/
8327 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8328 /*-----------------------------------------------------------------*/
8330 shiftLLeftOrResult (operand * left, int offl,
8331 operand * result, int offr, int shCount)
8333 MOVA (aopGet (left, offl, FALSE, FALSE));
8334 /* shift left accumulator */
8336 /* or with result */
8337 if (aopGetUsesAcc (result, offr))
8339 emitcode ("xch", "a,b");
8340 MOVA (aopGet (result, offr, FALSE, FALSE));
8341 emitcode ("orl", "a,b");
8345 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8347 /* back to result */
8348 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8351 /*-----------------------------------------------------------------*/
8352 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8353 /*-----------------------------------------------------------------*/
8355 shiftRLeftOrResult (operand * left, int offl,
8356 operand * result, int offr, int shCount)
8358 MOVA (aopGet (left, offl, FALSE, FALSE));
8359 /* shift right accumulator */
8361 /* or with result */
8362 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8363 /* back to result */
8364 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8367 /*-----------------------------------------------------------------*/
8368 /* genlshOne - left shift a one byte quantity by known count */
8369 /*-----------------------------------------------------------------*/
8371 genlshOne (operand * result, operand * left, int shCount)
8373 D(emitcode ("; genlshOne",""));
8375 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8378 /*-----------------------------------------------------------------*/
8379 /* genlshTwo - left shift two bytes by known amount != 0 */
8380 /*-----------------------------------------------------------------*/
8382 genlshTwo (operand * result, operand * left, int shCount)
8386 D(emitcode ("; genlshTwo",""));
8388 size = getDataSize (result);
8390 /* if shCount >= 8 */
8398 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8400 movLeft2Result (left, LSB, result, MSB16, 0);
8402 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8405 /* 1 <= shCount <= 7 */
8409 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8411 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8415 /*-----------------------------------------------------------------*/
8416 /* shiftLLong - shift left one long from left to result */
8417 /* offl = LSB or MSB16 */
8418 /*-----------------------------------------------------------------*/
8420 shiftLLong (operand * left, operand * result, int offr)
8423 int size = AOP_SIZE (result);
8425 if (size >= LSB + offr)
8427 l = aopGet (left, LSB, FALSE, FALSE);
8429 emitcode ("add", "a,acc");
8430 if (sameRegs (AOP (left), AOP (result)) &&
8431 size >= MSB16 + offr && offr != LSB)
8432 emitcode ("xch", "a,%s",
8433 aopGet (left, LSB + offr, FALSE, FALSE));
8435 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8438 if (size >= MSB16 + offr)
8440 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8442 l = aopGet (left, MSB16, FALSE, FALSE);
8445 emitcode ("rlc", "a");
8446 if (sameRegs (AOP (left), AOP (result)) &&
8447 size >= MSB24 + offr && offr != LSB)
8448 emitcode ("xch", "a,%s",
8449 aopGet (left, MSB16 + offr, FALSE, FALSE));
8451 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8454 if (size >= MSB24 + offr)
8456 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8458 l = aopGet (left, MSB24, FALSE, FALSE);
8461 emitcode ("rlc", "a");
8462 if (sameRegs (AOP (left), AOP (result)) &&
8463 size >= MSB32 + offr && offr != LSB)
8464 emitcode ("xch", "a,%s",
8465 aopGet (left, MSB24 + offr, FALSE, FALSE));
8467 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8470 if (size > MSB32 + offr)
8472 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8474 l = aopGet (left, MSB32, FALSE, FALSE);
8477 emitcode ("rlc", "a");
8478 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8481 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8484 /*-----------------------------------------------------------------*/
8485 /* genlshFour - shift four byte by a known amount != 0 */
8486 /*-----------------------------------------------------------------*/
8488 genlshFour (operand * result, operand * left, int shCount)
8492 D(emitcode ("; genlshFour",""));
8494 size = AOP_SIZE (result);
8496 /* if shifting more that 3 bytes */
8501 /* lowest order of left goes to the highest
8502 order of the destination */
8503 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8505 movLeft2Result (left, LSB, result, MSB32, 0);
8506 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8507 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8508 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8512 /* more than two bytes */
8513 else if (shCount >= 16)
8515 /* lower order two bytes goes to higher order two bytes */
8517 /* if some more remaining */
8519 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8522 movLeft2Result (left, MSB16, result, MSB32, 0);
8523 movLeft2Result (left, LSB, result, MSB24, 0);
8525 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8526 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8530 /* if more than 1 byte */
8531 else if (shCount >= 8)
8533 /* lower order three bytes goes to higher order three bytes */
8538 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8540 movLeft2Result (left, LSB, result, MSB16, 0);
8546 movLeft2Result (left, MSB24, result, MSB32, 0);
8547 movLeft2Result (left, MSB16, result, MSB24, 0);
8548 movLeft2Result (left, LSB, result, MSB16, 0);
8549 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8551 else if (shCount == 1)
8552 shiftLLong (left, result, MSB16);
8555 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8556 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8557 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8558 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8563 /* 1 <= shCount <= 7 */
8564 else if (shCount <= 2)
8566 shiftLLong (left, result, LSB);
8568 shiftLLong (result, result, LSB);
8570 /* 3 <= shCount <= 7, optimize */
8573 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8574 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8575 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8579 /*-----------------------------------------------------------------*/
8580 /* genLeftShiftLiteral - left shifting by known count */
8581 /*-----------------------------------------------------------------*/
8583 genLeftShiftLiteral (operand * left,
8588 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8591 D(emitcode ("; genLeftShiftLiteral",""));
8593 freeAsmop (right, NULL, ic, TRUE);
8595 aopOp (left, ic, FALSE);
8596 aopOp (result, ic, FALSE);
8598 size = getSize (operandType (result));
8601 emitcode ("; shift left ", "result %d, left %d", size,
8605 /* I suppose that the left size >= result size */
8610 movLeft2Result (left, size, result, size, 0);
8614 else if (shCount >= (size * 8))
8616 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8622 genlshOne (result, left, shCount);
8626 genlshTwo (result, left, shCount);
8630 genlshFour (result, left, shCount);
8633 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8634 "*** ack! mystery literal shift!\n");
8638 freeAsmop (result, NULL, ic, TRUE);
8639 freeAsmop (left, NULL, ic, TRUE);
8642 /*-----------------------------------------------------------------*/
8643 /* genLeftShift - generates code for left shifting */
8644 /*-----------------------------------------------------------------*/
8646 genLeftShift (iCode * ic)
8648 operand *left, *right, *result;
8651 symbol *tlbl, *tlbl1;
8654 D(emitcode ("; genLeftShift",""));
8656 right = IC_RIGHT (ic);
8657 left = IC_LEFT (ic);
8658 result = IC_RESULT (ic);
8660 aopOp (right, ic, FALSE);
8662 /* if the shift count is known then do it
8663 as efficiently as possible */
8664 if (AOP_TYPE (right) == AOP_LIT)
8666 genLeftShiftLiteral (left, right, result, ic);
8670 /* shift count is unknown then we have to form
8671 a loop get the loop count in B : Note: we take
8672 only the lower order byte since shifting
8673 more that 32 bits make no sense anyway, ( the
8674 largest size of an object can be only 32 bits ) */
8677 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8678 emitcode ("inc", "b");
8679 freeAsmop (right, NULL, ic, TRUE);
8680 aopOp (left, ic, FALSE);
8681 aopOp (result, ic, FALSE);
8683 /* now move the left to the result if they are not the same */
8684 if (!sameRegs (AOP (left), AOP (result)) &&
8685 AOP_SIZE (result) > 1)
8688 size = AOP_SIZE (result);
8692 l = aopGet (left, offset, FALSE, TRUE);
8693 if (*l == '@' && (IS_AOP_PREG (result)))
8696 emitcode ("mov", "a,%s", l);
8697 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8700 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8705 tlbl = newiTempLabel (NULL);
8706 size = AOP_SIZE (result);
8708 tlbl1 = newiTempLabel (NULL);
8710 /* if it is only one byte then */
8713 symbol *tlbl1 = newiTempLabel (NULL);
8715 l = aopGet (left, 0, FALSE, FALSE);
8717 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8718 emitcode ("", "%05d$:", tlbl->key + 100);
8719 emitcode ("add", "a,acc");
8720 emitcode ("", "%05d$:", tlbl1->key + 100);
8721 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8723 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8727 reAdjustPreg (AOP (result));
8729 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8730 emitcode ("", "%05d$:", tlbl->key + 100);
8731 l = aopGet (result, offset, FALSE, FALSE);
8733 emitcode ("add", "a,acc");
8734 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8737 l = aopGet (result, offset, FALSE, FALSE);
8739 emitcode ("rlc", "a");
8740 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8742 reAdjustPreg (AOP (result));
8744 emitcode ("", "%05d$:", tlbl1->key + 100);
8745 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8748 freeAsmop (result, NULL, ic, TRUE);
8749 freeAsmop (left, NULL, ic, TRUE);
8752 /*-----------------------------------------------------------------*/
8753 /* genrshOne - right shift a one byte quantity by known count */
8754 /*-----------------------------------------------------------------*/
8756 genrshOne (operand * result, operand * left,
8757 int shCount, int sign)
8759 D(emitcode ("; genrshOne",""));
8761 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8764 /*-----------------------------------------------------------------*/
8765 /* genrshTwo - right shift two bytes by known amount != 0 */
8766 /*-----------------------------------------------------------------*/
8768 genrshTwo (operand * result, operand * left,
8769 int shCount, int sign)
8771 D(emitcode ("; genrshTwo",""));
8773 /* if shCount >= 8 */
8778 shiftR1Left2Result (left, MSB16, result, LSB,
8781 movLeft2Result (left, MSB16, result, LSB, sign);
8782 addSign (result, MSB16, sign);
8785 /* 1 <= shCount <= 7 */
8787 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8790 /*-----------------------------------------------------------------*/
8791 /* shiftRLong - shift right one long from left to result */
8792 /* offl = LSB or MSB16 */
8793 /*-----------------------------------------------------------------*/
8795 shiftRLong (operand * left, int offl,
8796 operand * result, int sign)
8798 bool useSameRegs = regsInCommon (left, result);
8800 if (useSameRegs && offl>1)
8802 // we are in big trouble, but this shouldn't happen
8803 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8806 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8813 emitcode ("rlc", "a");
8814 emitcode ("subb", "a,acc");
8815 if (useSameRegs && sameReg (AOP (left), MSB32, AOP (result), MSB32))
8817 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8821 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8822 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8827 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8833 emitcode ("clr", "c");
8837 emitcode ("mov", "c,acc.7");
8840 emitcode ("rrc", "a");
8842 if (useSameRegs && offl==MSB16 &&
8843 sameReg (AOP (left), MSB24, AOP (result), MSB32-offl))
8845 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8849 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8850 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8853 emitcode ("rrc", "a");
8854 if (useSameRegs && offl==1 &&
8855 sameReg (AOP (left), MSB16, AOP (result), MSB24-offl))
8857 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8861 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8862 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8864 emitcode ("rrc", "a");
8867 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8872 sameReg (AOP (left), LSB, AOP (result), MSB16-offl))
8874 emitcode ("xch", "a,%s",aopGet (left, LSB, FALSE, FALSE));
8878 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8879 MOVA (aopGet (left, LSB, FALSE, FALSE));
8881 emitcode ("rrc", "a");
8882 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8886 /*-----------------------------------------------------------------*/
8887 /* genrshFour - shift four byte by a known amount != 0 */
8888 /*-----------------------------------------------------------------*/
8890 genrshFour (operand * result, operand * left,
8891 int shCount, int sign)
8893 D(emitcode ("; genrshFour",""));
8895 /* if shifting more that 3 bytes */
8900 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8902 movLeft2Result (left, MSB32, result, LSB, sign);
8903 addSign (result, MSB16, sign);
8905 else if (shCount >= 16)
8909 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8912 movLeft2Result (left, MSB24, result, LSB, 0);
8913 movLeft2Result (left, MSB32, result, MSB16, sign);
8915 addSign (result, MSB24, sign);
8917 else if (shCount >= 8)
8921 shiftRLong (left, MSB16, result, sign);
8922 else if (shCount == 0)
8924 movLeft2Result (left, MSB16, result, LSB, 0);
8925 movLeft2Result (left, MSB24, result, MSB16, 0);
8926 movLeft2Result (left, MSB32, result, MSB24, sign);
8927 addSign (result, MSB32, sign);
8931 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8932 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8933 /* the last shift is signed */
8934 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8935 addSign (result, MSB32, sign);
8939 { /* 1 <= shCount <= 7 */
8942 shiftRLong (left, LSB, result, sign);
8944 shiftRLong (result, LSB, result, sign);
8948 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8949 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8950 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8955 /*-----------------------------------------------------------------*/
8956 /* genRightShiftLiteral - right shifting by known count */
8957 /*-----------------------------------------------------------------*/
8959 genRightShiftLiteral (operand * left,
8965 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8968 D(emitcode ("; genRightShiftLiteral",""));
8970 freeAsmop (right, NULL, ic, TRUE);
8972 aopOp (left, ic, FALSE);
8973 aopOp (result, ic, FALSE);
8976 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8980 size = getDataSize (left);
8981 /* test the LEFT size !!! */
8983 /* I suppose that the left size >= result size */
8986 size = getDataSize (result);
8988 movLeft2Result (left, size, result, size, 0);
8991 else if (shCount >= (size * 8))
8994 /* get sign in acc.7 */
8995 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8997 addSign (result, LSB, sign);
9004 genrshOne (result, left, shCount, sign);
9008 genrshTwo (result, left, shCount, sign);
9012 genrshFour (result, left, shCount, sign);
9018 freeAsmop (result, NULL, ic, TRUE);
9019 freeAsmop (left, NULL, ic, TRUE);
9022 /*-----------------------------------------------------------------*/
9023 /* genSignedRightShift - right shift of signed number */
9024 /*-----------------------------------------------------------------*/
9026 genSignedRightShift (iCode * ic)
9028 operand *right, *left, *result;
9031 symbol *tlbl, *tlbl1;
9034 D(emitcode ("; genSignedRightShift",""));
9036 /* we do it the hard way put the shift count in b
9037 and loop thru preserving the sign */
9039 right = IC_RIGHT (ic);
9040 left = IC_LEFT (ic);
9041 result = IC_RESULT (ic);
9043 aopOp (right, ic, FALSE);
9046 if (AOP_TYPE (right) == AOP_LIT)
9048 genRightShiftLiteral (left, right, result, ic, 1);
9051 /* shift count is unknown then we have to form
9052 a loop get the loop count in B : Note: we take
9053 only the lower order byte since shifting
9054 more that 32 bits make no sense anyway, ( the
9055 largest size of an object can be only 32 bits ) */
9058 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9059 emitcode ("inc", "b");
9060 freeAsmop (right, NULL, ic, TRUE);
9061 aopOp (left, ic, FALSE);
9062 aopOp (result, ic, FALSE);
9064 /* now move the left to the result if they are not the
9066 if (!sameRegs (AOP (left), AOP (result)) &&
9067 AOP_SIZE (result) > 1)
9070 size = AOP_SIZE (result);
9074 l = aopGet (left, offset, FALSE, TRUE);
9075 if (*l == '@' && IS_AOP_PREG (result))
9078 emitcode ("mov", "a,%s", l);
9079 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9082 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9087 /* mov the highest order bit to OVR */
9088 tlbl = newiTempLabel (NULL);
9089 tlbl1 = newiTempLabel (NULL);
9091 size = AOP_SIZE (result);
9093 MOVA (aopGet (left, offset, FALSE, FALSE));
9094 emitcode ("rlc", "a");
9095 emitcode ("mov", "ov,c");
9096 /* if it is only one byte then */
9099 l = aopGet (left, 0, FALSE, FALSE);
9101 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9102 emitcode ("", "%05d$:", tlbl->key + 100);
9103 emitcode ("mov", "c,ov");
9104 emitcode ("rrc", "a");
9105 emitcode ("", "%05d$:", tlbl1->key + 100);
9106 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9108 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9112 reAdjustPreg (AOP (result));
9113 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9114 emitcode ("", "%05d$:", tlbl->key + 100);
9115 emitcode ("mov", "c,ov");
9118 l = aopGet (result, offset, FALSE, FALSE);
9120 emitcode ("rrc", "a");
9121 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9123 reAdjustPreg (AOP (result));
9124 emitcode ("", "%05d$:", tlbl1->key + 100);
9125 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9129 freeAsmop (result, NULL, ic, TRUE);
9130 freeAsmop (left, NULL, ic, TRUE);
9133 /*-----------------------------------------------------------------*/
9134 /* genRightShift - generate code for right shifting */
9135 /*-----------------------------------------------------------------*/
9137 genRightShift (iCode * ic)
9139 operand *right, *left, *result;
9143 symbol *tlbl, *tlbl1;
9146 D(emitcode ("; genRightShift",""));
9148 /* if signed then we do it the hard way preserve the
9149 sign bit moving it inwards */
9150 letype = getSpec (operandType (IC_LEFT (ic)));
9152 if (!SPEC_USIGN (letype))
9154 genSignedRightShift (ic);
9158 /* signed & unsigned types are treated the same : i.e. the
9159 signed is NOT propagated inwards : quoting from the
9160 ANSI - standard : "for E1 >> E2, is equivalent to division
9161 by 2**E2 if unsigned or if it has a non-negative value,
9162 otherwise the result is implementation defined ", MY definition
9163 is that the sign does not get propagated */
9165 right = IC_RIGHT (ic);
9166 left = IC_LEFT (ic);
9167 result = IC_RESULT (ic);
9169 aopOp (right, ic, FALSE);
9171 /* if the shift count is known then do it
9172 as efficiently as possible */
9173 if (AOP_TYPE (right) == AOP_LIT)
9175 genRightShiftLiteral (left, right, result, ic, 0);
9179 /* shift count is unknown then we have to form
9180 a loop get the loop count in B : Note: we take
9181 only the lower order byte since shifting
9182 more that 32 bits make no sense anyway, ( the
9183 largest size of an object can be only 32 bits ) */
9186 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9187 emitcode ("inc", "b");
9188 freeAsmop (right, NULL, ic, TRUE);
9189 aopOp (left, ic, FALSE);
9190 aopOp (result, ic, FALSE);
9192 /* now move the left to the result if they are not the
9194 if (!sameRegs (AOP (left), AOP (result)) &&
9195 AOP_SIZE (result) > 1)
9198 size = AOP_SIZE (result);
9202 l = aopGet (left, offset, FALSE, TRUE);
9203 if (*l == '@' && IS_AOP_PREG (result))
9206 emitcode ("mov", "a,%s", l);
9207 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9210 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9215 tlbl = newiTempLabel (NULL);
9216 tlbl1 = newiTempLabel (NULL);
9217 size = AOP_SIZE (result);
9220 /* if it is only one byte then */
9223 l = aopGet (left, 0, FALSE, FALSE);
9225 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9226 emitcode ("", "%05d$:", tlbl->key + 100);
9228 emitcode ("rrc", "a");
9229 emitcode ("", "%05d$:", tlbl1->key + 100);
9230 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9232 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9236 reAdjustPreg (AOP (result));
9237 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9238 emitcode ("", "%05d$:", tlbl->key + 100);
9242 l = aopGet (result, offset, FALSE, FALSE);
9244 emitcode ("rrc", "a");
9245 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9247 reAdjustPreg (AOP (result));
9249 emitcode ("", "%05d$:", tlbl1->key + 100);
9250 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9254 freeAsmop (result, NULL, ic, TRUE);
9255 freeAsmop (left, NULL, ic, TRUE);
9258 /*-----------------------------------------------------------------*/
9259 /* emitPtrByteGet - emits code to get a byte into A through a */
9260 /* pointer register (R0, R1, or DPTR). The */
9261 /* original value of A can be preserved in B. */
9262 /*-----------------------------------------------------------------*/
9264 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9271 emitcode ("mov", "b,a");
9272 emitcode ("mov", "a,@%s", rname);
9277 emitcode ("mov", "b,a");
9278 emitcode ("movx", "a,@%s", rname);
9283 emitcode ("mov", "b,a");
9284 emitcode ("movx", "a,@dptr");
9289 emitcode ("mov", "b,a");
9290 emitcode ("clr", "a");
9291 emitcode ("movc", "a,@a+dptr");
9297 emitcode ("push", "b");
9298 emitcode ("push", "acc");
9300 emitcode ("lcall", "__gptrget");
9302 emitcode ("pop", "b");
9307 /*-----------------------------------------------------------------*/
9308 /* emitPtrByteSet - emits code to set a byte from src through a */
9309 /* pointer register (R0, R1, or DPTR). */
9310 /*-----------------------------------------------------------------*/
9312 emitPtrByteSet (char *rname, int p_type, char *src)
9321 emitcode ("mov", "@%s,a", rname);
9324 emitcode ("mov", "@%s,%s", rname, src);
9329 emitcode ("movx", "@%s,a", rname);
9334 emitcode ("movx", "@dptr,a");
9339 emitcode ("lcall", "__gptrput");
9344 /*-----------------------------------------------------------------*/
9345 /* genUnpackBits - generates code for unpacking bits */
9346 /*-----------------------------------------------------------------*/
9348 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9350 int offset = 0; /* result byte offset */
9351 int rsize; /* result size */
9352 int rlen = 0; /* remaining bitfield length */
9353 sym_link *etype; /* bitfield type information */
9354 int blen; /* bitfield length */
9355 int bstr; /* bitfield starting bit within byte */
9358 D(emitcode ("; genUnpackBits",""));
9360 etype = getSpec (operandType (result));
9361 rsize = getSize (operandType (result));
9362 blen = SPEC_BLEN (etype);
9363 bstr = SPEC_BSTR (etype);
9365 if (ifx && blen <= 8)
9367 emitPtrByteGet (rname, ptype, FALSE);
9370 SNPRINTF (buffer, sizeof(buffer),
9372 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9377 emitcode ("anl", "a,#0x%02x",
9378 (((unsigned char) -1) >> (8 - blen)) << bstr);
9379 genIfxJump (ifx, "a", NULL, NULL, NULL);
9385 /* If the bitfield length is less than a byte */
9388 emitPtrByteGet (rname, ptype, FALSE);
9390 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9391 if (!SPEC_USIGN (etype))
9393 /* signed bitfield */
9394 symbol *tlbl = newiTempLabel (NULL);
9396 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9397 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9398 emitcode ("", "%05d$:", tlbl->key + 100);
9400 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9404 /* Bit field did not fit in a byte. Copy all
9405 but the partial byte at the end. */
9406 for (rlen=blen;rlen>=8;rlen-=8)
9408 emitPtrByteGet (rname, ptype, FALSE);
9409 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9411 emitcode ("inc", "%s", rname);
9414 /* Handle the partial byte at the end */
9417 emitPtrByteGet (rname, ptype, FALSE);
9418 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9419 if (!SPEC_USIGN (etype))
9421 /* signed bitfield */
9422 symbol *tlbl = newiTempLabel (NULL);
9424 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9425 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9426 emitcode ("", "%05d$:", tlbl->key + 100);
9428 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9436 if (SPEC_USIGN (etype))
9440 /* signed bitfield: sign extension with 0x00 or 0xff */
9441 emitcode ("rlc", "a");
9442 emitcode ("subb", "a,acc");
9448 aopPut (result, source, offset++, isOperandVolatile (result, FALSE));
9453 /*-----------------------------------------------------------------*/
9454 /* genDataPointerGet - generates code when ptr offset is known */
9455 /*-----------------------------------------------------------------*/
9457 genDataPointerGet (operand * left,
9463 int size, offset = 0;
9465 D(emitcode ("; genDataPointerGet",""));
9467 aopOp (result, ic, TRUE);
9469 /* get the string representation of the name */
9470 l = aopGet (left, 0, FALSE, TRUE);
9471 size = AOP_SIZE (result);
9475 sprintf (buffer, "(%s + %d)", l + 1, offset);
9477 sprintf (buffer, "%s", l + 1);
9478 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9481 freeAsmop (result, NULL, ic, TRUE);
9482 freeAsmop (left, NULL, ic, TRUE);
9485 /*-----------------------------------------------------------------*/
9486 /* genNearPointerGet - emitcode for near pointer fetch */
9487 /*-----------------------------------------------------------------*/
9489 genNearPointerGet (operand * left,
9498 sym_link *rtype, *retype;
9499 sym_link *ltype = operandType (left);
9502 D(emitcode ("; genNearPointerGet",""));
9504 rtype = operandType (result);
9505 retype = getSpec (rtype);
9507 aopOp (left, ic, FALSE);
9509 /* if left is rematerialisable and
9510 result is not bitfield variable type and
9511 the left is pointer to data space i.e
9512 lower 128 bytes of space */
9513 if (AOP_TYPE (left) == AOP_IMMD &&
9514 !IS_BITFIELD (retype) &&
9515 DCL_TYPE (ltype) == POINTER)
9517 genDataPointerGet (left, result, ic);
9521 /* if the value is already in a pointer register
9522 then don't need anything more */
9523 if (!AOP_INPREG (AOP (left)))
9525 if (IS_AOP_PREG (left))
9527 // Aha, it is a pointer, just in disguise.
9528 rname = aopGet (left, 0, FALSE, FALSE);
9531 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9532 __FILE__, __LINE__);
9537 emitcode ("mov", "a%s,%s", rname + 1, rname);
9538 rname++; // skip the '@'.
9543 /* otherwise get a free pointer register */
9545 preg = getFreePtr (ic, &aop, FALSE);
9546 emitcode ("mov", "%s,%s",
9548 aopGet (left, 0, FALSE, TRUE));
9553 rname = aopGet (left, 0, FALSE, FALSE);
9555 //aopOp (result, ic, FALSE);
9556 aopOp (result, ic, result?TRUE:FALSE);
9558 /* if bitfield then unpack the bits */
9559 if (IS_BITFIELD (retype))
9560 genUnpackBits (result, rname, POINTER, ifx);
9563 /* we have can just get the values */
9564 int size = AOP_SIZE (result);
9569 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9572 emitcode ("mov", "a,@%s", rname);
9574 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9578 sprintf (buffer, "@%s", rname);
9579 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9583 emitcode ("inc", "%s", rname);
9587 /* now some housekeeping stuff */
9588 if (aop) /* we had to allocate for this iCode */
9590 if (pi) { /* post increment present */
9591 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9593 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9597 /* we did not allocate which means left
9598 already in a pointer register, then
9599 if size > 0 && this could be used again
9600 we have to point it back to where it
9602 if ((AOP_SIZE (result) > 1 &&
9603 !OP_SYMBOL (left)->remat &&
9604 (OP_SYMBOL (left)->liveTo > ic->seq ||
9608 int size = AOP_SIZE (result) - 1;
9610 emitcode ("dec", "%s", rname);
9614 if (ifx && !ifx->generated)
9616 genIfxJump (ifx, "a", left, NULL, result);
9620 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9621 freeAsmop (left, NULL, ic, TRUE);
9622 if (pi) pi->generated = 1;
9625 /*-----------------------------------------------------------------*/
9626 /* genPagedPointerGet - emitcode for paged pointer fetch */
9627 /*-----------------------------------------------------------------*/
9629 genPagedPointerGet (operand * left,
9638 sym_link *rtype, *retype;
9640 D(emitcode ("; genPagedPointerGet",""));
9642 rtype = operandType (result);
9643 retype = getSpec (rtype);
9645 aopOp (left, ic, FALSE);
9647 /* if the value is already in a pointer register
9648 then don't need anything more */
9649 if (!AOP_INPREG (AOP (left)))
9651 /* otherwise get a free pointer register */
9653 preg = getFreePtr (ic, &aop, FALSE);
9654 emitcode ("mov", "%s,%s",
9656 aopGet (left, 0, FALSE, TRUE));
9660 rname = aopGet (left, 0, FALSE, FALSE);
9662 aopOp (result, ic, FALSE);
9664 /* if bitfield then unpack the bits */
9665 if (IS_BITFIELD (retype))
9666 genUnpackBits (result, rname, PPOINTER, ifx);
9669 /* we have can just get the values */
9670 int size = AOP_SIZE (result);
9676 emitcode ("movx", "a,@%s", rname);
9678 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9683 emitcode ("inc", "%s", rname);
9687 /* now some housekeeping stuff */
9688 if (aop) /* we had to allocate for this iCode */
9690 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9691 freeAsmop (NULL, aop, ic, TRUE);
9695 /* we did not allocate which means left
9696 already in a pointer register, then
9697 if size > 0 && this could be used again
9698 we have to point it back to where it
9700 if ((AOP_SIZE (result) > 1 &&
9701 !OP_SYMBOL (left)->remat &&
9702 (OP_SYMBOL (left)->liveTo > ic->seq ||
9706 int size = AOP_SIZE (result) - 1;
9708 emitcode ("dec", "%s", rname);
9712 if (ifx && !ifx->generated)
9714 genIfxJump (ifx, "a", left, NULL, result);
9718 freeAsmop (result, NULL, ic, TRUE);
9719 freeAsmop (left, NULL, ic, TRUE);
9720 if (pi) pi->generated = 1;
9723 /*--------------------------------------------------------------------*/
9724 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9725 /*--------------------------------------------------------------------*/
9727 loadDptrFromOperand (operand *op, bool loadBToo)
9729 if (AOP_TYPE (op) != AOP_STR)
9731 /* if this is rematerializable */
9732 if (AOP_TYPE (op) == AOP_IMMD)
9734 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9737 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9738 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9741 wassertl(FALSE, "need pointerCode");
9742 emitcode ("", "; mov b,???");
9743 /* genPointerGet and genPointerSet originally did different
9744 ** things for this case. Both seem wrong.
9745 ** from genPointerGet:
9746 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9747 ** from genPointerSet:
9748 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9753 else if (AOP_TYPE (op) == AOP_DPTR)
9757 MOVA (aopGet (op, 0, FALSE, FALSE));
9758 emitcode ("push", "acc");
9759 MOVA (aopGet (op, 1, FALSE, FALSE));
9760 emitcode ("push", "acc");
9761 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9762 emitcode ("pop", "dph");
9763 emitcode ("pop", "dpl");
9767 MOVA (aopGet (op, 0, FALSE, FALSE));
9768 emitcode ("push", "acc");
9769 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9770 emitcode ("pop", "dpl");
9774 { /* we need to get it byte by byte */
9775 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9776 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9778 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9783 /*-----------------------------------------------------------------*/
9784 /* genFarPointerGet - gget value from far space */
9785 /*-----------------------------------------------------------------*/
9787 genFarPointerGet (operand * left,
9788 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9791 sym_link *retype = getSpec (operandType (result));
9793 D(emitcode ("; genFarPointerGet",""));
9795 aopOp (left, ic, FALSE);
9796 loadDptrFromOperand (left, FALSE);
9798 /* so dptr now contains the address */
9799 aopOp (result, ic, FALSE);
9801 /* if bit then unpack */
9802 if (IS_BITFIELD (retype))
9803 genUnpackBits (result, "dptr", FPOINTER, ifx);
9806 size = AOP_SIZE (result);
9811 emitcode ("movx", "a,@dptr");
9813 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9815 emitcode ("inc", "dptr");
9819 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9821 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9822 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9826 if (ifx && !ifx->generated)
9828 genIfxJump (ifx, "a", left, NULL, result);
9831 freeAsmop (result, NULL, ic, TRUE);
9832 freeAsmop (left, NULL, ic, TRUE);
9835 /*-----------------------------------------------------------------*/
9836 /* genCodePointerGet - gget value from code space */
9837 /*-----------------------------------------------------------------*/
9839 genCodePointerGet (operand * left,
9840 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9843 sym_link *retype = getSpec (operandType (result));
9845 D(emitcode ("; genCodePointerGet",""));
9847 aopOp (left, ic, FALSE);
9848 loadDptrFromOperand (left, FALSE);
9850 /* so dptr now contains the address */
9851 aopOp (result, ic, FALSE);
9853 /* if bit then unpack */
9854 if (IS_BITFIELD (retype))
9855 genUnpackBits (result, "dptr", CPOINTER, ifx);
9858 size = AOP_SIZE (result);
9865 emitcode ("clr", "a");
9866 emitcode ("movc", "a,@a+dptr");
9868 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9869 emitcode ("inc", "dptr");
9873 emitcode ("mov", "a,#0x%02x", offset);
9874 emitcode ("movc", "a,@a+dptr");
9876 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9881 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9883 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9884 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9888 if (ifx && !ifx->generated)
9890 genIfxJump (ifx, "a", left, NULL, result);
9893 freeAsmop (result, NULL, ic, TRUE);
9894 freeAsmop (left, NULL, ic, TRUE);
9897 /*-----------------------------------------------------------------*/
9898 /* genGenPointerGet - gget value from generic pointer space */
9899 /*-----------------------------------------------------------------*/
9901 genGenPointerGet (operand * left,
9902 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9905 sym_link *retype = getSpec (operandType (result));
9907 D(emitcode ("; genGenPointerGet",""));
9909 aopOp (left, ic, FALSE);
9910 loadDptrFromOperand (left, TRUE);
9912 /* so dptr know contains the address */
9913 aopOp (result, ic, FALSE);
9915 /* if bit then unpack */
9916 if (IS_BITFIELD (retype))
9917 genUnpackBits (result, "dptr", GPOINTER, ifx);
9920 size = AOP_SIZE (result);
9925 emitcode ("lcall", "__gptrget");
9927 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9929 emitcode ("inc", "dptr");
9933 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9935 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9936 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9940 if (ifx && !ifx->generated)
9942 genIfxJump (ifx, "a", left, NULL, result);
9945 freeAsmop (result, NULL, ic, TRUE);
9946 freeAsmop (left, NULL, ic, TRUE);
9949 /*-----------------------------------------------------------------*/
9950 /* genPointerGet - generate code for pointer get */
9951 /*-----------------------------------------------------------------*/
9953 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9955 operand *left, *result;
9956 sym_link *type, *etype;
9959 D(emitcode ("; genPointerGet",""));
9961 left = IC_LEFT (ic);
9962 result = IC_RESULT (ic);
9964 if (getSize (operandType (result))>1)
9967 /* depending on the type of pointer we need to
9968 move it to the correct pointer register */
9969 type = operandType (left);
9970 etype = getSpec (type);
9971 /* if left is of type of pointer then it is simple */
9972 if (IS_PTR (type) && !IS_FUNC (type->next))
9973 p_type = DCL_TYPE (type);
9976 /* we have to go by the storage class */
9977 p_type = PTR_TYPE (SPEC_OCLS (etype));
9980 /* special case when cast remat */
9981 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9982 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9983 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9984 type = operandType (left);
9985 p_type = DCL_TYPE (type);
9987 /* now that we have the pointer type we assign
9988 the pointer values */
9994 genNearPointerGet (left, result, ic, pi, ifx);
9998 genPagedPointerGet (left, result, ic, pi, ifx);
10002 genFarPointerGet (left, result, ic, pi, ifx);
10006 genCodePointerGet (left, result, ic, pi, ifx);
10010 genGenPointerGet (left, result, ic, pi, ifx);
10018 /*-----------------------------------------------------------------*/
10019 /* genPackBits - generates code for packed bit storage */
10020 /*-----------------------------------------------------------------*/
10022 genPackBits (sym_link * etype,
10024 char *rname, int p_type)
10026 int offset = 0; /* source byte offset */
10027 int rlen = 0; /* remaining bitfield length */
10028 int blen; /* bitfield length */
10029 int bstr; /* bitfield starting bit within byte */
10030 int litval; /* source literal value (if AOP_LIT) */
10031 unsigned char mask; /* bitmask within current byte */
10033 D(emitcode ("; genPackBits",""));
10035 blen = SPEC_BLEN (etype);
10036 bstr = SPEC_BSTR (etype);
10038 /* If the bitfield length is less than a byte */
10041 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10042 (unsigned char) (0xFF >> (8 - bstr)));
10044 if (AOP_TYPE (right) == AOP_LIT)
10046 /* Case with a bitfield length <8 and literal source
10048 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10050 litval &= (~mask) & 0xff;
10051 emitPtrByteGet (rname, p_type, FALSE);
10052 if ((mask|litval)!=0xff)
10053 emitcode ("anl","a,#0x%02x", mask);
10055 emitcode ("orl","a,#0x%02x", litval);
10059 if ((blen==1) && (p_type!=GPOINTER))
10061 /* Case with a bitfield length == 1 and no generic pointer
10063 if (AOP_TYPE (right) == AOP_CRY)
10064 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10067 MOVA (aopGet (right, 0, FALSE, FALSE));
10068 emitcode ("rrc","a");
10070 emitPtrByteGet (rname, p_type, FALSE);
10071 emitcode ("mov","acc.%d,c",bstr);
10076 /* Case with a bitfield length < 8 and arbitrary source
10078 MOVA (aopGet (right, 0, FALSE, FALSE));
10079 /* shift and mask source value */
10081 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10083 pushedB = pushB ();
10084 /* transfer A to B and get next byte */
10085 emitPtrByteGet (rname, p_type, TRUE);
10087 emitcode ("anl", "a,#0x%02x", mask);
10088 emitcode ("orl", "a,b");
10089 if (p_type == GPOINTER)
10090 emitcode ("pop", "b");
10096 emitPtrByteSet (rname, p_type, "a");
10100 /* Bit length is greater than 7 bits. In this case, copy */
10101 /* all except the partial byte at the end */
10102 for (rlen=blen;rlen>=8;rlen-=8)
10104 emitPtrByteSet (rname, p_type,
10105 aopGet (right, offset++, FALSE, TRUE) );
10107 emitcode ("inc", "%s", rname);
10110 /* If there was a partial byte at the end */
10113 mask = (((unsigned char) -1 << rlen) & 0xff);
10115 if (AOP_TYPE (right) == AOP_LIT)
10117 /* Case with partial byte and literal source
10119 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10120 litval >>= (blen-rlen);
10121 litval &= (~mask) & 0xff;
10122 emitPtrByteGet (rname, p_type, FALSE);
10123 if ((mask|litval)!=0xff)
10124 emitcode ("anl","a,#0x%02x", mask);
10126 emitcode ("orl","a,#0x%02x", litval);
10131 /* Case with partial byte and arbitrary source
10133 MOVA (aopGet (right, offset++, FALSE, FALSE));
10134 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10136 pushedB = pushB ();
10137 /* transfer A to B and get next byte */
10138 emitPtrByteGet (rname, p_type, TRUE);
10140 emitcode ("anl", "a,#0x%02x", mask);
10141 emitcode ("orl", "a,b");
10142 if (p_type == GPOINTER)
10143 emitcode ("pop", "b");
10147 emitPtrByteSet (rname, p_type, "a");
10153 /*-----------------------------------------------------------------*/
10154 /* genDataPointerSet - remat pointer to data space */
10155 /*-----------------------------------------------------------------*/
10157 genDataPointerSet (operand * right,
10161 int size, offset = 0;
10162 char *l, buffer[256];
10164 D(emitcode ("; genDataPointerSet",""));
10166 aopOp (right, ic, FALSE);
10168 l = aopGet (result, 0, FALSE, TRUE);
10169 size = AOP_SIZE (right);
10173 sprintf (buffer, "(%s + %d)", l + 1, offset);
10175 sprintf (buffer, "%s", l + 1);
10176 emitcode ("mov", "%s,%s", buffer,
10177 aopGet (right, offset++, FALSE, FALSE));
10180 freeAsmop (result, NULL, ic, TRUE);
10181 freeAsmop (right, NULL, ic, TRUE);
10184 /*-----------------------------------------------------------------*/
10185 /* genNearPointerSet - emitcode for near pointer put */
10186 /*-----------------------------------------------------------------*/
10188 genNearPointerSet (operand * right,
10196 sym_link *retype, *letype;
10197 sym_link *ptype = operandType (result);
10199 D(emitcode ("; genNearPointerSet",""));
10201 retype = getSpec (operandType (right));
10202 letype = getSpec (ptype);
10203 aopOp (result, ic, FALSE);
10205 /* if the result is rematerializable &
10206 in data space & not a bit variable */
10207 if (AOP_TYPE (result) == AOP_IMMD &&
10208 DCL_TYPE (ptype) == POINTER &&
10209 !IS_BITVAR (retype) &&
10210 !IS_BITVAR (letype))
10212 genDataPointerSet (right, result, ic);
10216 /* if the value is already in a pointer register
10217 then don't need anything more */
10218 if (!AOP_INPREG (AOP (result)))
10221 //AOP_TYPE (result) == AOP_STK
10222 IS_AOP_PREG(result)
10225 // Aha, it is a pointer, just in disguise.
10226 rname = aopGet (result, 0, FALSE, FALSE);
10229 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10230 __FILE__, __LINE__);
10235 emitcode ("mov", "a%s,%s", rname + 1, rname);
10236 rname++; // skip the '@'.
10241 /* otherwise get a free pointer register */
10242 aop = newAsmop (0);
10243 preg = getFreePtr (ic, &aop, FALSE);
10244 emitcode ("mov", "%s,%s",
10246 aopGet (result, 0, FALSE, TRUE));
10247 rname = preg->name;
10252 rname = aopGet (result, 0, FALSE, FALSE);
10255 aopOp (right, ic, FALSE);
10257 /* if bitfield then unpack the bits */
10258 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10259 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10262 /* we have can just get the values */
10263 int size = AOP_SIZE (right);
10268 l = aopGet (right, offset, FALSE, TRUE);
10272 emitcode ("mov", "@%s,a", rname);
10275 emitcode ("mov", "@%s,%s", rname, l);
10277 emitcode ("inc", "%s", rname);
10282 /* now some housekeeping stuff */
10283 if (aop) /* we had to allocate for this iCode */
10286 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10287 freeAsmop (NULL, aop, ic, TRUE);
10291 /* we did not allocate which means left
10292 already in a pointer register, then
10293 if size > 0 && this could be used again
10294 we have to point it back to where it
10296 if ((AOP_SIZE (right) > 1 &&
10297 !OP_SYMBOL (result)->remat &&
10298 (OP_SYMBOL (result)->liveTo > ic->seq ||
10302 int size = AOP_SIZE (right) - 1;
10304 emitcode ("dec", "%s", rname);
10309 if (pi) pi->generated = 1;
10310 freeAsmop (result, NULL, ic, TRUE);
10311 freeAsmop (right, NULL, ic, TRUE);
10314 /*-----------------------------------------------------------------*/
10315 /* genPagedPointerSet - emitcode for Paged pointer put */
10316 /*-----------------------------------------------------------------*/
10318 genPagedPointerSet (operand * right,
10326 sym_link *retype, *letype;
10328 D(emitcode ("; genPagedPointerSet",""));
10330 retype = getSpec (operandType (right));
10331 letype = getSpec (operandType (result));
10333 aopOp (result, ic, FALSE);
10335 /* if the value is already in a pointer register
10336 then don't need anything more */
10337 if (!AOP_INPREG (AOP (result)))
10339 /* otherwise get a free pointer register */
10340 aop = newAsmop (0);
10341 preg = getFreePtr (ic, &aop, FALSE);
10342 emitcode ("mov", "%s,%s",
10344 aopGet (result, 0, FALSE, TRUE));
10345 rname = preg->name;
10348 rname = aopGet (result, 0, FALSE, FALSE);
10350 aopOp (right, ic, FALSE);
10352 /* if bitfield then unpack the bits */
10353 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10354 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10357 /* we have can just get the values */
10358 int size = AOP_SIZE (right);
10363 l = aopGet (right, offset, FALSE, TRUE);
10366 emitcode ("movx", "@%s,a", rname);
10369 emitcode ("inc", "%s", rname);
10375 /* now some housekeeping stuff */
10376 if (aop) /* we had to allocate for this iCode */
10379 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10380 freeAsmop (NULL, aop, ic, TRUE);
10384 /* we did not allocate which means left
10385 already in a pointer register, then
10386 if size > 0 && this could be used again
10387 we have to point it back to where it
10389 if (AOP_SIZE (right) > 1 &&
10390 !OP_SYMBOL (result)->remat &&
10391 (OP_SYMBOL (result)->liveTo > ic->seq ||
10394 int size = AOP_SIZE (right) - 1;
10396 emitcode ("dec", "%s", rname);
10401 if (pi) pi->generated = 1;
10402 freeAsmop (result, NULL, ic, TRUE);
10403 freeAsmop (right, NULL, ic, TRUE);
10406 /*-----------------------------------------------------------------*/
10407 /* genFarPointerSet - set value from far space */
10408 /*-----------------------------------------------------------------*/
10410 genFarPointerSet (operand * right,
10411 operand * result, iCode * ic, iCode * pi)
10414 sym_link *retype = getSpec (operandType (right));
10415 sym_link *letype = getSpec (operandType (result));
10417 D(emitcode ("; genFarPointerSet",""));
10419 aopOp (result, ic, FALSE);
10420 loadDptrFromOperand (result, FALSE);
10422 /* so dptr know contains the address */
10423 aopOp (right, ic, FALSE);
10425 /* if bit then unpack */
10426 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10427 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10430 size = AOP_SIZE (right);
10435 char *l = aopGet (right, offset++, FALSE, FALSE);
10437 emitcode ("movx", "@dptr,a");
10439 emitcode ("inc", "dptr");
10442 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10443 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10444 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10447 freeAsmop (result, NULL, ic, TRUE);
10448 freeAsmop (right, NULL, ic, TRUE);
10451 /*-----------------------------------------------------------------*/
10452 /* genGenPointerSet - set value from generic pointer space */
10453 /*-----------------------------------------------------------------*/
10455 genGenPointerSet (operand * right,
10456 operand * result, iCode * ic, iCode * pi)
10459 sym_link *retype = getSpec (operandType (right));
10460 sym_link *letype = getSpec (operandType (result));
10462 D(emitcode ("; genGenPointerSet",""));
10464 aopOp (result, ic, FALSE);
10465 loadDptrFromOperand (result, TRUE);
10467 /* so dptr know contains the address */
10468 aopOp (right, ic, FALSE);
10470 /* if bit then unpack */
10471 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10472 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10475 size = AOP_SIZE (right);
10480 char *l = aopGet (right, offset++, FALSE, FALSE);
10482 emitcode ("lcall", "__gptrput");
10484 emitcode ("inc", "dptr");
10488 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10489 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10490 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10493 freeAsmop (result, NULL, ic, TRUE);
10494 freeAsmop (right, NULL, ic, TRUE);
10497 /*-----------------------------------------------------------------*/
10498 /* genPointerSet - stores the value into a pointer location */
10499 /*-----------------------------------------------------------------*/
10501 genPointerSet (iCode * ic, iCode *pi)
10503 operand *right, *result;
10504 sym_link *type, *etype;
10507 D(emitcode ("; genPointerSet",""));
10509 right = IC_RIGHT (ic);
10510 result = IC_RESULT (ic);
10512 /* depending on the type of pointer we need to
10513 move it to the correct pointer register */
10514 type = operandType (result);
10515 etype = getSpec (type);
10516 /* if left is of type of pointer then it is simple */
10517 if (IS_PTR (type) && !IS_FUNC (type->next))
10519 p_type = DCL_TYPE (type);
10523 /* we have to go by the storage class */
10524 p_type = PTR_TYPE (SPEC_OCLS (etype));
10527 /* special case when cast remat */
10528 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10529 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10530 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10531 type = operandType (result);
10532 p_type = DCL_TYPE (type);
10534 /* now that we have the pointer type we assign
10535 the pointer values */
10541 genNearPointerSet (right, result, ic, pi);
10545 genPagedPointerSet (right, result, ic, pi);
10549 genFarPointerSet (right, result, ic, pi);
10553 genGenPointerSet (right, result, ic, pi);
10557 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10558 "genPointerSet: illegal pointer type");
10563 /*-----------------------------------------------------------------*/
10564 /* genIfx - generate code for Ifx statement */
10565 /*-----------------------------------------------------------------*/
10567 genIfx (iCode * ic, iCode * popIc)
10569 operand *cond = IC_COND (ic);
10573 D(emitcode ("; genIfx",""));
10575 aopOp (cond, ic, FALSE);
10577 /* get the value into acc */
10578 if (AOP_TYPE (cond) != AOP_CRY)
10583 if (AOP(cond)->aopu.aop_dir)
10584 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10586 /* the result is now in the accumulator or a directly addressable bit */
10587 freeAsmop (cond, NULL, ic, TRUE);
10589 /* if there was something to be popped then do it */
10593 /* if the condition is a bit variable */
10595 genIfxJump(ic, dup, NULL, NULL, NULL);
10596 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10597 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10598 else if (isbit && !IS_ITEMP (cond))
10599 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10601 genIfxJump (ic, "a", NULL, NULL, NULL);
10606 /*-----------------------------------------------------------------*/
10607 /* genAddrOf - generates code for address of */
10608 /*-----------------------------------------------------------------*/
10610 genAddrOf (iCode * ic)
10612 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10615 D(emitcode ("; genAddrOf",""));
10617 aopOp (IC_RESULT (ic), ic, FALSE);
10619 /* if the operand is on the stack then we
10620 need to get the stack offset of this
10624 /* if it has an offset then we need to compute
10628 emitcode ("mov", "a,%s", SYM_BP (sym));
10629 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10630 ((char) (sym->stack - _G.nRegsSaved)) :
10631 ((char) sym->stack)) & 0xff);
10632 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10636 /* we can just move _bp */
10637 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10639 /* fill the result with zero */
10640 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10645 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10651 /* object not on stack then we need the name */
10652 size = AOP_SIZE (IC_RESULT (ic));
10657 char s[SDCC_NAME_MAX];
10659 sprintf (s, "#(%s >> %d)",
10663 sprintf (s, "#%s", sym->rname);
10664 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10668 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10672 /*-----------------------------------------------------------------*/
10673 /* genFarFarAssign - assignment when both are in far space */
10674 /*-----------------------------------------------------------------*/
10676 genFarFarAssign (operand * result, operand * right, iCode * ic)
10678 int size = AOP_SIZE (right);
10682 D(emitcode ("; genFarFarAssign",""));
10684 /* first push the right side on to the stack */
10687 l = aopGet (right, offset++, FALSE, FALSE);
10689 emitcode ("push", "acc");
10692 freeAsmop (right, NULL, ic, FALSE);
10693 /* now assign DPTR to result */
10694 aopOp (result, ic, FALSE);
10695 size = AOP_SIZE (result);
10698 emitcode ("pop", "acc");
10699 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10701 freeAsmop (result, NULL, ic, FALSE);
10704 /*-----------------------------------------------------------------*/
10705 /* genAssign - generate code for assignment */
10706 /*-----------------------------------------------------------------*/
10708 genAssign (iCode * ic)
10710 operand *result, *right;
10712 unsigned long lit = 0L;
10714 D(emitcode("; genAssign",""));
10716 result = IC_RESULT (ic);
10717 right = IC_RIGHT (ic);
10719 /* if they are the same */
10720 if (operandsEqu (result, right) &&
10721 !isOperandVolatile (result, FALSE) &&
10722 !isOperandVolatile (right, FALSE))
10725 aopOp (right, ic, FALSE);
10727 /* special case both in far space */
10728 if (AOP_TYPE (right) == AOP_DPTR &&
10729 IS_TRUE_SYMOP (result) &&
10730 isOperandInFarSpace (result))
10733 genFarFarAssign (result, right, ic);
10737 aopOp (result, ic, TRUE);
10739 /* if they are the same registers */
10740 if (sameRegs (AOP (right), AOP (result)) &&
10741 !isOperandVolatile (result, FALSE) &&
10742 !isOperandVolatile (right, FALSE))
10745 /* if the result is a bit */
10746 if (AOP_TYPE (result) == AOP_CRY)
10749 /* if the right size is a literal then
10750 we know what the value is */
10751 if (AOP_TYPE (right) == AOP_LIT)
10753 if (((int) operandLitValue (right)))
10754 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10756 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10760 /* the right is also a bit variable */
10761 if (AOP_TYPE (right) == AOP_CRY)
10763 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10764 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10768 /* we need to or */
10770 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10774 /* bit variables done */
10776 size = AOP_SIZE (result);
10778 if (AOP_TYPE (right) == AOP_LIT)
10779 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10781 (AOP_TYPE (result) != AOP_REG) &&
10782 (AOP_TYPE (right) == AOP_LIT) &&
10783 !IS_FLOAT (operandType (right)) &&
10786 while ((size) && (lit))
10789 aopGet (right, offset, FALSE, FALSE),
10791 isOperandVolatile (result, FALSE));
10796 emitcode ("clr", "a");
10799 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10808 aopGet (right, offset, FALSE, FALSE),
10810 isOperandVolatile (result, FALSE));
10816 freeAsmop (result, NULL, ic, TRUE);
10817 freeAsmop (right, NULL, ic, TRUE);
10820 /*-----------------------------------------------------------------*/
10821 /* genJumpTab - generates code for jump table */
10822 /*-----------------------------------------------------------------*/
10824 genJumpTab (iCode * ic)
10826 symbol *jtab,*jtablo,*jtabhi;
10828 unsigned int count;
10830 D(emitcode ("; genJumpTab",""));
10832 count = elementsInSet( IC_JTLABELS (ic) );
10836 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10837 if the switch argument is in a register.
10838 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10839 /* Peephole may not convert ljmp to sjmp or ret
10840 labelIsReturnOnly & labelInRange must check
10841 currPl->ic->op != JUMPTABLE */
10842 aopOp (IC_JTCOND (ic), ic, FALSE);
10843 /* get the condition into accumulator */
10844 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10846 /* multiply by three */
10847 if (aopGetUsesAcc (IC_JTCOND (ic), 0))
10849 emitcode ("mov", "b,#3");
10850 emitcode ("mul", "ab");
10854 emitcode ("add", "a,acc");
10855 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10857 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10859 jtab = newiTempLabel (NULL);
10860 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10861 emitcode ("jmp", "@a+dptr");
10862 emitcode ("", "%05d$:", jtab->key + 100);
10863 /* now generate the jump labels */
10864 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10865 jtab = setNextItem (IC_JTLABELS (ic)))
10866 emitcode ("ljmp", "%05d$", jtab->key + 100);
10870 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10871 if the switch argument is in a register.
10872 For n>6 this algorithm may be more compact */
10873 jtablo = newiTempLabel (NULL);
10874 jtabhi = newiTempLabel (NULL);
10876 /* get the condition into accumulator.
10877 Using b as temporary storage, if register push/pop is needed */
10878 aopOp (IC_JTCOND (ic), ic, FALSE);
10879 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10880 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10881 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10883 // (MB) what if B is in use???
10884 wassertl(!BINUSE, "B was in use");
10885 emitcode ("mov", "b,%s", l);
10888 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10892 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10893 emitcode ("movc", "a,@a+pc");
10894 emitcode ("push", "acc");
10897 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10898 emitcode ("movc", "a,@a+pc");
10899 emitcode ("push", "acc");
10903 /* this scales up to n<=255, but needs two more bytes
10904 and changes dptr */
10905 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10906 emitcode ("movc", "a,@a+dptr");
10907 emitcode ("push", "acc");
10910 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10911 emitcode ("movc", "a,@a+dptr");
10912 emitcode ("push", "acc");
10915 emitcode ("ret", "");
10917 /* now generate jump table, LSB */
10918 emitcode ("", "%05d$:", jtablo->key + 100);
10919 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10920 jtab = setNextItem (IC_JTLABELS (ic)))
10921 emitcode (".db", "%05d$", jtab->key + 100);
10923 /* now generate jump table, MSB */
10924 emitcode ("", "%05d$:", jtabhi->key + 100);
10925 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10926 jtab = setNextItem (IC_JTLABELS (ic)))
10927 emitcode (".db", "%05d$>>8", jtab->key + 100);
10931 /*-----------------------------------------------------------------*/
10932 /* genCast - gen code for casting */
10933 /*-----------------------------------------------------------------*/
10935 genCast (iCode * ic)
10937 operand *result = IC_RESULT (ic);
10938 sym_link *ctype = operandType (IC_LEFT (ic));
10939 sym_link *rtype = operandType (IC_RIGHT (ic));
10940 operand *right = IC_RIGHT (ic);
10943 D(emitcode("; genCast",""));
10945 /* if they are equivalent then do nothing */
10946 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10949 aopOp (right, ic, FALSE);
10950 aopOp (result, ic, FALSE);
10952 /* if the result is a bit (and not a bitfield) */
10953 // if (AOP_TYPE (result) == AOP_CRY)
10954 if (IS_BIT (OP_SYMBOL (result)->type))
10955 /* not for bitfields */
10957 /* if the right size is a literal then
10958 we know what the value is */
10959 if (AOP_TYPE (right) == AOP_LIT)
10961 if (((int) operandLitValue (right)))
10962 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10964 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10969 /* the right is also a bit variable */
10970 if (AOP_TYPE (right) == AOP_CRY)
10972 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10973 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10977 /* we need to or */
10979 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10984 /* if they are the same size : or less */
10985 if (AOP_SIZE (result) <= AOP_SIZE (right))
10988 /* if they are in the same place */
10989 if (sameRegs (AOP (right), AOP (result)))
10992 /* if they in different places then copy */
10993 size = AOP_SIZE (result);
10998 aopGet (right, offset, FALSE, FALSE),
11000 isOperandVolatile (result, FALSE));
11007 /* if the result is of type pointer */
11008 if (IS_PTR (ctype))
11012 sym_link *type = operandType (right);
11013 sym_link *etype = getSpec (type);
11015 /* pointer to generic pointer */
11016 if (IS_GENPTR (ctype))
11019 p_type = DCL_TYPE (type);
11022 if (SPEC_SCLS(etype)==S_REGISTER) {
11023 // let's assume it is a generic pointer
11026 /* we have to go by the storage class */
11027 p_type = PTR_TYPE (SPEC_OCLS (etype));
11031 /* the first two bytes are known */
11032 size = GPTRSIZE - 1;
11037 aopGet (right, offset, FALSE, FALSE),
11039 isOperandVolatile (result, FALSE));
11042 /* the last byte depending on type */
11044 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11049 // pointerTypeToGPByte will have bitched.
11053 sprintf(gpValStr, "#0x%x", gpVal);
11054 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
11059 /* just copy the pointers */
11060 size = AOP_SIZE (result);
11065 aopGet (right, offset, FALSE, FALSE),
11067 isOperandVolatile (result, FALSE));
11073 /* so we now know that the size of destination is greater
11074 than the size of the source */
11075 /* we move to result for the size of source */
11076 size = AOP_SIZE (right);
11081 aopGet (right, offset, FALSE, FALSE),
11083 isOperandVolatile (result, FALSE));
11087 /* now depending on the sign of the source && destination */
11088 size = AOP_SIZE (result) - AOP_SIZE (right);
11089 /* if unsigned or not an integral type */
11090 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11093 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
11097 /* we need to extend the sign :{ */
11098 char *l = aopGet (right, AOP_SIZE (right) - 1,
11101 emitcode ("rlc", "a");
11102 emitcode ("subb", "a,acc");
11104 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
11107 /* we are done hurray !!!! */
11110 freeAsmop (result, NULL, ic, TRUE);
11111 freeAsmop (right, NULL, ic, TRUE);
11114 /*-----------------------------------------------------------------*/
11115 /* genDjnz - generate decrement & jump if not zero instrucion */
11116 /*-----------------------------------------------------------------*/
11118 genDjnz (iCode * ic, iCode * ifx)
11120 symbol *lbl, *lbl1;
11124 D(emitcode ("; genDjnz",""));
11126 /* if the if condition has a false label
11127 then we cannot save */
11128 if (IC_FALSE (ifx))
11131 /* if the minus is not of the form
11133 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11134 !IS_OP_LITERAL (IC_RIGHT (ic)))
11137 if (operandLitValue (IC_RIGHT (ic)) != 1)
11140 /* if the size of this greater than one then no
11142 if (getSize (operandType (IC_RESULT (ic))) > 1)
11145 /* otherwise we can save BIG */
11146 lbl = newiTempLabel (NULL);
11147 lbl1 = newiTempLabel (NULL);
11149 aopOp (IC_RESULT (ic), ic, FALSE);
11151 if (AOP_NEEDSACC(IC_RESULT(ic)))
11153 /* If the result is accessed indirectly via
11154 * the accumulator, we must explicitly write
11155 * it back after the decrement.
11157 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11159 if (strcmp(rByte, "a"))
11161 /* Something is hopelessly wrong */
11162 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11163 __FILE__, __LINE__);
11164 /* We can just give up; the generated code will be inefficient,
11165 * but what the hey.
11167 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11170 emitcode ("dec", "%s", rByte);
11171 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
11172 emitcode ("jnz", "%05d$", lbl->key + 100);
11174 else if (IS_AOP_PREG (IC_RESULT (ic)))
11176 emitcode ("dec", "%s",
11177 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11178 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11179 emitcode ("jnz", "%05d$", lbl->key + 100);
11183 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11186 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11187 emitcode ("", "%05d$:", lbl->key + 100);
11188 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11189 emitcode ("", "%05d$:", lbl1->key + 100);
11191 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11192 ifx->generated = 1;
11196 /*-----------------------------------------------------------------*/
11197 /* genReceive - generate code for a receive iCode */
11198 /*-----------------------------------------------------------------*/
11200 genReceive (iCode * ic)
11202 int size = getSize (operandType (IC_RESULT (ic)));
11205 D(emitcode ("; genReceive",""));
11207 if (ic->argreg == 1)
11208 { /* first parameter */
11209 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11210 isOperandInPagedSpace (IC_RESULT (ic))) &&
11211 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11212 IS_TRUE_SYMOP (IC_RESULT (ic))))
11215 int receivingA = 0;
11218 for (offset = 0; offset<size; offset++)
11219 if (!strcmp (fReturn[offset], "a"))
11224 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11226 for (offset = size-1; offset>0; offset--)
11227 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11228 emitcode("mov","a,%s", fReturn[0]);
11230 aopOp (IC_RESULT (ic), ic, FALSE);
11232 aopPut (IC_RESULT (ic), "a", offset,
11233 isOperandVolatile (IC_RESULT (ic), FALSE));
11234 for (offset = 1; offset<size; offset++)
11235 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
11236 isOperandVolatile (IC_RESULT (ic), FALSE));
11242 if (getTempRegs(tempRegs, size, ic))
11244 for (offset = 0; offset<size; offset++)
11245 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11246 aopOp (IC_RESULT (ic), ic, FALSE);
11247 for (offset = 0; offset<size; offset++)
11248 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
11249 isOperandVolatile (IC_RESULT (ic), FALSE));
11254 offset = fReturnSizeMCS51 - size;
11257 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11258 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11261 aopOp (IC_RESULT (ic), ic, FALSE);
11262 size = AOP_SIZE (IC_RESULT (ic));
11266 emitcode ("pop", "acc");
11267 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11273 aopOp (IC_RESULT (ic), ic, FALSE);
11275 assignResultValue (IC_RESULT (ic), NULL);
11278 else if (ic->argreg > 12)
11279 { /* bit parameters */
11280 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11282 aopOp (IC_RESULT (ic), ic, FALSE);
11283 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11284 outBitC(IC_RESULT (ic));
11288 { /* other parameters */
11290 aopOp (IC_RESULT (ic), ic, FALSE);
11291 rb1off = ic->argreg;
11294 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11299 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11302 /*-----------------------------------------------------------------*/
11303 /* genDummyRead - generate code for dummy read of volatiles */
11304 /*-----------------------------------------------------------------*/
11306 genDummyRead (iCode * ic)
11311 D(emitcode("; genDummyRead",""));
11313 op = IC_RIGHT (ic);
11314 if (op && IS_SYMOP (op))
11316 aopOp (op, ic, FALSE);
11318 /* if the result is a bit */
11319 if (AOP_TYPE (op) == AOP_CRY)
11320 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11323 /* bit variables done */
11325 size = AOP_SIZE (op);
11329 MOVA (aopGet (op, offset, FALSE, FALSE));
11334 freeAsmop (op, NULL, ic, TRUE);
11338 if (op && IS_SYMOP (op))
11340 aopOp (op, ic, FALSE);
11342 /* if the result is a bit */
11343 if (AOP_TYPE (op) == AOP_CRY)
11344 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11347 /* bit variables done */
11349 size = AOP_SIZE (op);
11353 MOVA (aopGet (op, offset, FALSE, FALSE));
11358 freeAsmop (op, NULL, ic, TRUE);
11362 /*-----------------------------------------------------------------*/
11363 /* genCritical - generate code for start of a critical sequence */
11364 /*-----------------------------------------------------------------*/
11366 genCritical (iCode *ic)
11368 symbol *tlbl = newiTempLabel (NULL);
11370 D(emitcode("; genCritical",""));
11372 if (IC_RESULT (ic))
11374 aopOp (IC_RESULT (ic), ic, TRUE);
11375 aopPut (IC_RESULT (ic), one, 0, 0);
11376 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11377 aopPut (IC_RESULT (ic), zero, 0, 0);
11378 emitcode ("", "%05d$:", (tlbl->key + 100));
11379 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11383 emitcode ("setb", "c");
11384 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11385 emitcode ("clr", "c");
11386 emitcode ("", "%05d$:", (tlbl->key + 100));
11387 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11391 /*-----------------------------------------------------------------*/
11392 /* genEndCritical - generate code for end of a critical sequence */
11393 /*-----------------------------------------------------------------*/
11395 genEndCritical (iCode *ic)
11397 D(emitcode("; genEndCritical",""));
11401 aopOp (IC_RIGHT (ic), ic, FALSE);
11402 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11404 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11405 emitcode ("mov", "ea,c");
11409 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11410 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11411 emitcode ("rrc", "a");
11412 emitcode ("mov", "ea,c");
11414 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11418 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11419 emitcode ("mov", "ea,c");
11423 /*-----------------------------------------------------------------*/
11424 /* gen51Code - generate code for 8051 based controllers */
11425 /*-----------------------------------------------------------------*/
11427 gen51Code (iCode * lic)
11431 /* int cseq = 0; */
11433 _G.currentFunc = NULL;
11434 lineHead = lineCurr = NULL;
11436 /* print the allocation information */
11437 if (allocInfo && currFunc)
11438 printAllocInfo (currFunc, codeOutFile);
11439 /* if debug information required */
11440 if (options.debug && currFunc)
11442 debugFile->writeFunction (currFunc, lic);
11444 /* stack pointer name */
11445 if (options.useXstack)
11451 for (ic = lic; ic; ic = ic->next)
11453 _G.current_iCode = ic;
11455 if (ic->lineno && cln != ic->lineno)
11459 debugFile->writeCLine (ic);
11461 if (!options.noCcodeInAsm) {
11462 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11463 printCLine(ic->filename, ic->lineno));
11468 if (ic->seqPoint && ic->seqPoint != cseq)
11470 emitcode ("", "; sequence point %d", ic->seqPoint);
11471 cseq = ic->seqPoint;
11474 if (options.iCodeInAsm) {
11475 char regsInUse[80];
11479 for (i=0; i<8; i++) {
11480 sprintf (®sInUse[i],
11481 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11484 strcpy (regsInUse, "--------");
11485 for (i=0; i < 8; i++) {
11486 if (bitVectBitValue (ic->rMask, i))
11488 int offset = regs8051[i].offset;
11489 regsInUse[offset] = offset + '0'; /* show rMask */
11493 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11495 /* if the result is marked as
11496 spilt and rematerializable or code for
11497 this has already been generated then
11499 if (resultRemat (ic) || ic->generated)
11502 /* depending on the operation */
11522 /* IPOP happens only when trying to restore a
11523 spilt live range, if there is an ifx statement
11524 following this pop then the if statement might
11525 be using some of the registers being popped which
11526 would destory the contents of the register so
11527 we need to check for this condition and handle it */
11529 ic->next->op == IFX &&
11530 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11531 genIfx (ic->next, ic);
11549 genEndFunction (ic);
11569 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11586 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11590 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11597 /* note these two are xlated by algebraic equivalence
11598 during parsing SDCC.y */
11599 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11600 "got '>=' or '<=' shouldn't have come here");
11604 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11616 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11620 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11624 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11660 genRightShift (ic);
11663 case GET_VALUE_AT_ADDRESS:
11665 hasInc (IC_LEFT (ic), ic,
11666 getSize (operandType (IC_RESULT (ic)))),
11667 ifxForOp (IC_RESULT (ic), ic) );
11671 if (POINTER_SET (ic))
11672 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11698 addSet (&_G.sendSet, ic);
11701 case DUMMY_READ_VOLATILE:
11710 genEndCritical (ic);
11722 _G.current_iCode = NULL;
11724 /* now we are ready to call the
11725 peep hole optimizer */
11726 if (!options.nopeep)
11727 peepHole (&lineHead);
11729 /* now do the actual printing */
11730 printLine (lineHead, codeOutFile);