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;
2723 D(emitcode("; genCall",""));
2725 dtype = operandType (IC_LEFT (ic));
2726 etype = getSpec(dtype);
2727 /* if send set is not empty then assign */
2730 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2731 genSend(reverseSet(_G.sendSet));
2733 genSend(_G.sendSet);
2739 /* if we are calling a not _naked function that is not using
2740 the same register bank then we need to save the
2741 destination registers on the stack */
2742 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2743 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2744 !IFFUNC_ISISR (dtype))
2749 /* if caller saves & we have not saved then */
2755 emitcode ("mov", "psw,#0x%02x",
2756 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2760 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2762 if (IFFUNC_CALLEESAVES(dtype))
2764 werror (E_BANKED_WITH_CALLEESAVES);
2768 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2769 OP_SYMBOL (IC_LEFT (ic))->rname :
2770 OP_SYMBOL (IC_LEFT (ic))->name);
2772 emitcode ("mov", "r0,#%s", l);
2773 emitcode ("mov", "r1,#(%s >> 8)", l);
2774 emitcode ("mov", "r2,#(%s >> 16)", l);
2775 emitcode ("lcall", "__sdcc_banked_call");
2780 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2781 OP_SYMBOL (IC_LEFT (ic))->rname :
2782 OP_SYMBOL (IC_LEFT (ic))->name));
2787 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2790 /* if we need assign a result value */
2791 if ((IS_ITEMP (IC_RESULT (ic)) &&
2792 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2793 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2794 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2795 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2796 IS_TRUE_SYMOP (IC_RESULT (ic)))
2800 aopOp (IC_RESULT (ic), ic, FALSE);
2803 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2805 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2808 /* adjust the stack for parameters if required */
2812 if (ic->parmBytes > 3)
2816 emitcode ("push", "acc");
2819 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2820 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2822 emitcode ("mov", "F0,c");
2826 emitcode ("mov", "a,%s", spname);
2827 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2828 emitcode ("mov", "%s,a", spname);
2830 /* unsaveRegisters from xstack needs acc, but */
2831 /* unsaveRegisters from stack needs this popped */
2832 if (accPushed && !options.useXstack)
2834 emitcode ("pop", "acc");
2839 for (i = 0; i < ic->parmBytes; i++)
2840 emitcode ("dec", "%s", spname);
2843 /* if we had saved some registers then unsave them */
2844 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2846 if (accuse && !accPushed && options.useXstack)
2848 /* xstack needs acc, but doesn't touch normal stack */
2849 emitcode ("push", "acc");
2852 unsaveRegisters (ic);
2855 // /* if register bank was saved then pop them */
2857 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2859 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2862 emitcode ("mov", "c,F0");
2864 aopOp (IC_RESULT (ic), ic, FALSE);
2865 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2866 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2870 emitcode ("pop", "acc");
2873 /*-----------------------------------------------------------------*/
2874 /* -10l - generates a call by pointer statement */
2875 /*-----------------------------------------------------------------*/
2877 genPcall (iCode * ic)
2881 symbol *rlbl = newiTempLabel (NULL);
2882 // bool restoreBank=FALSE;
2883 bool swapBanks = FALSE;
2884 bool resultInF0 = FALSE;
2886 D(emitcode("; genPCall",""));
2888 dtype = operandType (IC_LEFT (ic))->next;
2889 etype = getSpec(dtype);
2890 /* if caller saves & we have not saved then */
2894 /* if we are calling a not _naked function that is not using
2895 the same register bank then we need to save the
2896 destination registers on the stack */
2897 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2898 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2899 !IFFUNC_ISISR (dtype))
2901 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2902 // restoreBank=TRUE;
2904 // need caution message to user here
2907 if (IS_LITERAL(etype))
2909 /* if send set is not empty then assign */
2912 genSend(reverseSet(_G.sendSet));
2918 emitcode ("mov", "psw,#0x%02x",
2919 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2922 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2924 if (IFFUNC_CALLEESAVES(dtype))
2926 werror (E_BANKED_WITH_CALLEESAVES);
2930 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2932 emitcode ("mov", "r0,#%s", l);
2933 emitcode ("mov", "r1,#(%s >> 8)", l);
2934 emitcode ("mov", "r2,#(%s >> 16)", l);
2935 emitcode ("lcall", "__sdcc_banked_call");
2940 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2945 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2947 if (IFFUNC_CALLEESAVES(dtype))
2949 werror (E_BANKED_WITH_CALLEESAVES);
2953 aopOp (IC_LEFT (ic), ic, FALSE);
2957 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2958 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2959 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2963 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2964 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2965 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2966 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2969 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2971 /* if send set is not empty then assign */
2974 genSend(reverseSet(_G.sendSet));
2980 emitcode ("mov", "psw,#0x%02x",
2981 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2985 emitcode ("lcall", "__sdcc_banked_call");
2990 /* push the return address on to the stack */
2991 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2992 emitcode ("push", "acc");
2993 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2994 emitcode ("push", "acc");
2996 /* now push the calling address */
2997 aopOp (IC_LEFT (ic), ic, FALSE);
2999 pushSide (IC_LEFT (ic), FPTRSIZE);
3001 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3003 /* if send set is not empty the assign */
3006 genSend(reverseSet(_G.sendSet));
3012 emitcode ("mov", "psw,#0x%02x",
3013 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
3017 emitcode ("ret", "");
3018 emitcode ("", "%05d$:", (rlbl->key + 100));
3023 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3026 /* if we need assign a result value */
3027 if ((IS_ITEMP (IC_RESULT (ic)) &&
3028 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3029 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3030 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3031 IS_TRUE_SYMOP (IC_RESULT (ic)))
3035 aopOp (IC_RESULT (ic), ic, FALSE);
3038 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3040 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3043 /* adjust the stack for parameters if required */
3047 if (ic->parmBytes > 3)
3049 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3050 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3052 emitcode ("mov", "F0,c");
3056 emitcode ("mov", "a,%s", spname);
3057 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3058 emitcode ("mov", "%s,a", spname);
3061 for (i = 0; i < ic->parmBytes; i++)
3062 emitcode ("dec", "%s", spname);
3066 // /* if register bank was saved then unsave them */
3068 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3070 /* if we had saved some registers then unsave them */
3071 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3072 unsaveRegisters (ic);
3074 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3077 emitcode ("mov", "c,F0");
3079 aopOp (IC_RESULT (ic), ic, FALSE);
3080 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3081 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3085 /*-----------------------------------------------------------------*/
3086 /* resultRemat - result is rematerializable */
3087 /*-----------------------------------------------------------------*/
3089 resultRemat (iCode * ic)
3091 if (SKIP_IC (ic) || ic->op == IFX)
3094 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3096 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3097 if (sym->remat && !POINTER_SET (ic))
3104 #if defined(__BORLANDC__) || defined(_MSC_VER)
3105 #define STRCASECMP stricmp
3107 #define STRCASECMP strcasecmp
3110 /*-----------------------------------------------------------------*/
3111 /* inExcludeList - return 1 if the string is in exclude Reg list */
3112 /*-----------------------------------------------------------------*/
3114 regsCmp(void *p1, void *p2)
3116 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3120 inExcludeList (char *s)
3122 const char *p = setFirstItem(options.excludeRegsSet);
3124 if (p == NULL || STRCASECMP(p, "none") == 0)
3128 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3131 /*-----------------------------------------------------------------*/
3132 /* genFunction - generated code for function entry */
3133 /*-----------------------------------------------------------------*/
3135 genFunction (iCode * ic)
3137 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3139 bool switchedPSW = FALSE;
3140 int calleesaves_saved_register = -1;
3141 int stackAdjust = sym->stack;
3142 int accIsFree = sym->recvSize < 4;
3143 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3144 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3147 /* create the function header */
3148 emitcode (";", "-----------------------------------------");
3149 emitcode (";", " function %s", sym->name);
3150 emitcode (";", "-----------------------------------------");
3152 emitcode ("", "%s:", sym->rname);
3153 ftype = operandType (IC_LEFT (ic));
3154 _G.currentFunc = sym;
3156 if (IFFUNC_ISNAKED(ftype))
3158 emitcode(";", "naked function: no prologue.");
3162 /* here we need to generate the equates for the
3163 register bank if required */
3164 if (FUNC_REGBANK (ftype) != rbank)
3168 rbank = FUNC_REGBANK (ftype);
3169 for (i = 0; i < mcs51_nRegs; i++)
3171 if (regs8051[i].type != REG_BIT)
3173 if (strcmp (regs8051[i].base, "0") == 0)
3174 emitcode ("", "%s = 0x%02x",
3176 8 * rbank + regs8051[i].offset);
3178 emitcode ("", "%s = %s + 0x%02x",
3181 8 * rbank + regs8051[i].offset);
3186 /* if this is an interrupt service routine then
3187 save acc, b, dpl, dph */
3188 if (IFFUNC_ISISR (sym->type))
3191 if (!inExcludeList ("acc"))
3192 emitcode ("push", "acc");
3193 if (!inExcludeList ("b"))
3194 emitcode ("push", "b");
3195 if (!inExcludeList ("dpl"))
3196 emitcode ("push", "dpl");
3197 if (!inExcludeList ("dph"))
3198 emitcode ("push", "dph");
3199 /* if this isr has no bank i.e. is going to
3200 run with bank 0 , then we need to save more
3202 if (!FUNC_REGBANK (sym->type))
3205 /* if this function does not call any other
3206 function then we can be economical and
3207 save only those registers that are used */
3208 if (!IFFUNC_HASFCALL(sym->type))
3212 /* if any registers used */
3215 bool bits_pushed = FALSE;
3216 /* save the registers used */
3217 for (i = 0; i < sym->regsUsed->size; i++)
3219 if (bitVectBitValue (sym->regsUsed, i))
3220 bits_pushed = pushReg (i, bits_pushed);
3227 /* this function has a function call. We cannot
3228 determines register usage so we will have to push the
3230 saveRBank (0, ic, FALSE);
3231 if (options.parms_in_bank1) {
3233 for (i=0; i < 8 ; i++ ) {
3234 emitcode ("push","%s",rb1regs[i]);
3241 /* This ISR uses a non-zero bank.
3243 * We assume that the bank is available for our
3246 * However, if this ISR calls a function which uses some
3247 * other bank, we must save that bank entirely.
3249 unsigned long banksToSave = 0;
3251 if (IFFUNC_HASFCALL(sym->type))
3254 #define MAX_REGISTER_BANKS 4
3259 for (i = ic; i; i = i->next)
3261 if (i->op == ENDFUNCTION)
3263 /* we got to the end OK. */
3271 dtype = operandType (IC_LEFT(i));
3273 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3275 /* Mark this bank for saving. */
3276 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3278 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3282 banksToSave |= (1 << FUNC_REGBANK(dtype));
3285 /* And note that we don't need to do it in
3293 /* This is a mess; we have no idea what
3294 * register bank the called function might
3297 * The only thing I can think of to do is
3298 * throw a warning and hope.
3300 werror(W_FUNCPTR_IN_USING_ISR);
3304 if (banksToSave && options.useXstack)
3306 /* Since we aren't passing it an ic,
3307 * saveRBank will assume r0 is available to abuse.
3309 * So switch to our (trashable) bank now, so
3310 * the caller's R0 isn't trashed.
3312 emitcode ("push", "psw");
3313 emitcode ("mov", "psw,#0x%02x",
3314 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3318 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3320 if (banksToSave & (1 << ix))
3322 saveRBank(ix, NULL, FALSE);
3326 // TODO: this needs a closer look
3327 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3330 /* Set the register bank to the desired value if nothing else */
3331 /* has done so yet. */
3334 emitcode ("push", "psw");
3335 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3340 /* This is a non-ISR function. The caller has already switched register */
3341 /* banks, if necessary, so just handle the callee-saves option. */
3343 /* if callee-save to be used for this function
3344 then save the registers being used in this function */
3345 if (IFFUNC_CALLEESAVES(sym->type))
3349 /* if any registers used */
3352 bool bits_pushed = FALSE;
3353 /* save the registers used */
3354 for (i = 0; i < sym->regsUsed->size; i++)
3356 if (bitVectBitValue (sym->regsUsed, i))
3358 /* remember one saved register for later usage */
3359 if (calleesaves_saved_register < 0)
3360 calleesaves_saved_register = i;
3361 bits_pushed = pushReg (i, bits_pushed);
3372 if (options.useXstack)
3374 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3376 emitcode ("mov", "r0,%s", spname);
3377 emitcode ("inc", "%s", spname);
3378 emitcode ("xch", "a,_bpx");
3379 emitcode ("movx", "@r0,a");
3380 emitcode ("inc", "r0");
3381 emitcode ("mov", "a,r0");
3382 emitcode ("xch", "a,_bpx");
3386 emitcode ("push", "_bp"); /* save the callers stack */
3387 emitcode ("mov", "_bp,sp");
3392 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3394 /* set up the stack */
3395 emitcode ("push", "_bp"); /* save the callers stack */
3396 emitcode ("mov", "_bp,sp");
3401 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3402 /* before setting up the stack frame completely. */
3403 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3405 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3409 if (rsym && rsym->regType == REG_CND)
3411 if (rsym && (rsym->accuse || rsym->ruonly))
3413 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3414 rsym = rsym->usl.spillLoc;
3417 /* If the RECEIVE operand immediately spills to the first entry on the */
3418 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3419 /* rather than the usual @r0/r1 machinations. */
3420 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3424 _G.current_iCode = ric;
3425 D(emitcode ("; genReceive",""));
3426 for (ofs=0; ofs < sym->recvSize; ofs++)
3428 if (!strcmp (fReturn[ofs], "a"))
3429 emitcode ("push", "acc");
3431 emitcode ("push", fReturn[ofs]);
3433 stackAdjust -= sym->recvSize;
3436 assert (stackAdjust>=0);
3439 _G.current_iCode = ic;
3443 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3444 /* to free up the accumulator. */
3445 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3449 _G.current_iCode = ric;
3450 D(emitcode ("; genReceive",""));
3451 for (ofs=0; ofs < sym->recvSize; ofs++)
3453 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3455 _G.current_iCode = ic;
3461 /* adjust the stack for the function */
3464 int i = stackAdjust;
3466 werror (W_STACK_OVERFLOW, sym->name);
3468 if (i > 3 && accIsFree)
3470 emitcode ("mov", "a,sp");
3471 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3472 emitcode ("mov", "sp,a");
3476 /* The accumulator is not free, so we will need another register */
3477 /* to clobber. No need to worry about a possible conflict with */
3478 /* the above early RECEIVE optimizations since they would have */
3479 /* freed the accumulator if they were generated. */
3481 if (IFFUNC_CALLEESAVES(sym->type))
3483 /* if it's a callee-saves function we need a saved register */
3484 if (calleesaves_saved_register >= 0)
3486 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3487 emitcode ("mov", "a,sp");
3488 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3489 emitcode ("mov", "sp,a");
3490 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3493 /* do it the hard way */
3495 emitcode ("inc", "sp");
3499 /* not callee-saves, we can clobber r0 */
3500 emitcode ("mov", "r0,a");
3501 emitcode ("mov", "a,sp");
3502 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3503 emitcode ("mov", "sp,a");
3504 emitcode ("mov", "a,r0");
3509 emitcode ("inc", "sp");
3514 char i = ((char) sym->xstack & 0xff);
3516 if (i > 3 && accIsFree)
3518 emitcode ("mov", "a,_spx");
3519 emitcode ("add", "a,#0x%02x", i);
3520 emitcode ("mov", "_spx,a");
3524 emitcode ("push", "acc");
3525 emitcode ("mov", "a,_spx");
3526 emitcode ("add", "a,#0x%02x", i);
3527 emitcode ("mov", "_spx,a");
3528 emitcode ("pop", "acc");
3533 emitcode ("inc", "_spx");
3537 /* if critical function then turn interrupts off */
3538 if (IFFUNC_ISCRITICAL (ftype))
3540 symbol *tlbl = newiTempLabel (NULL);
3541 emitcode ("setb", "c");
3542 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3543 emitcode ("clr", "c");
3544 emitcode ("", "%05d$:", (tlbl->key + 100));
3545 emitcode ("push", "psw"); /* save old ea via c in psw */
3549 /*-----------------------------------------------------------------*/
3550 /* genEndFunction - generates epilogue for functions */
3551 /*-----------------------------------------------------------------*/
3553 genEndFunction (iCode * ic)
3555 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3556 lineNode *lnp = lineCurr;
3558 bitVect *regsUsedPrologue;
3559 bitVect *regsUnneeded;
3562 _G.currentFunc = NULL;
3563 if (IFFUNC_ISNAKED(sym->type))
3565 emitcode(";", "naked function: no epilogue.");
3566 if (options.debug && currFunc)
3567 debugFile->writeEndFunction (currFunc, ic, 0);
3571 if (IFFUNC_ISCRITICAL (sym->type))
3573 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3575 emitcode ("rlc", "a"); /* save c in a */
3576 emitcode ("pop", "psw"); /* restore ea via c in psw */
3577 emitcode ("mov", "ea,c");
3578 emitcode ("rrc", "a"); /* restore c from a */
3582 emitcode ("pop", "psw"); /* restore ea via c in psw */
3583 emitcode ("mov", "ea,c");
3587 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3589 if (options.useXstack)
3593 emitcode ("mov", "sp,_bp");
3594 emitcode ("pop", "_bp");
3596 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3598 emitcode ("xch", "a,_bpx");
3599 emitcode ("mov", "r0,a");
3600 emitcode ("dec", "r0");
3601 emitcode ("movx", "a,@r0");
3602 emitcode ("xch", "a,_bpx");
3603 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3606 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3608 emitcode ("mov", "sp,_bp");
3609 emitcode ("pop", "_bp");
3613 /* restore the register bank */
3614 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3616 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3617 || !options.useXstack)
3619 /* Special case of ISR using non-zero bank with useXstack
3622 emitcode ("pop", "psw");
3626 if (IFFUNC_ISISR (sym->type))
3629 /* now we need to restore the registers */
3630 /* if this isr has no bank i.e. is going to
3631 run with bank 0 , then we need to save more
3633 if (!FUNC_REGBANK (sym->type))
3635 /* if this function does not call any other
3636 function then we can be economical and
3637 save only those registers that are used */
3638 if (!IFFUNC_HASFCALL(sym->type))
3642 /* if any registers used */
3645 bool bits_popped = FALSE;
3646 /* save the registers used */
3647 for (i = sym->regsUsed->size; i >= 0; i--)
3649 if (bitVectBitValue (sym->regsUsed, i))
3650 bits_popped = popReg (i, bits_popped);
3656 if (options.parms_in_bank1) {
3658 for (i = 7 ; i >= 0 ; i-- ) {
3659 emitcode ("pop","%s",rb1regs[i]);
3662 /* this function has a function call cannot
3663 determines register usage so we will have to pop the
3665 unsaveRBank (0, ic, FALSE);
3670 /* This ISR uses a non-zero bank.
3672 * Restore any register banks saved by genFunction
3675 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3678 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3680 if (savedBanks & (1 << ix))
3682 unsaveRBank(ix, NULL, FALSE);
3686 if (options.useXstack)
3688 /* Restore bank AFTER calling unsaveRBank,
3689 * since it can trash r0.
3691 emitcode ("pop", "psw");
3695 if (!inExcludeList ("dph"))
3696 emitcode ("pop", "dph");
3697 if (!inExcludeList ("dpl"))
3698 emitcode ("pop", "dpl");
3699 if (!inExcludeList ("b"))
3700 emitcode ("pop", "b");
3701 if (!inExcludeList ("acc"))
3702 emitcode ("pop", "acc");
3704 /* if debug then send end of function */
3705 if (options.debug && currFunc)
3707 debugFile->writeEndFunction (currFunc, ic, 1);
3710 emitcode ("reti", "");
3714 if (IFFUNC_CALLEESAVES(sym->type))
3718 /* if any registers used */
3721 /* save the registers used */
3722 for (i = sym->regsUsed->size; i >= 0; i--)
3724 if (bitVectBitValue (sym->regsUsed, i) ||
3725 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3726 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3729 else if (mcs51_ptrRegReq)
3731 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3732 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3737 /* if debug then send end of function */
3738 if (options.debug && currFunc)
3740 debugFile->writeEndFunction (currFunc, ic, 1);
3743 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3745 emitcode ("ljmp", "__sdcc_banked_ret");
3749 emitcode ("ret", "");
3753 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3756 /* If this was an interrupt handler using bank 0 that called another */
3757 /* function, then all registers must be saved; nothing to optimized. */
3758 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3759 && !FUNC_REGBANK(sym->type))
3762 /* There are no push/pops to optimize if not callee-saves or ISR */
3763 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3766 /* If there were stack parameters, we cannot optimize without also */
3767 /* fixing all of the stack offsets; this is too dificult to consider. */
3768 if (FUNC_HASSTACKPARM(sym->type))
3771 /* Compute the registers actually used */
3772 regsUsed = newBitVect (mcs51_nRegs);
3773 regsUsedPrologue = newBitVect (mcs51_nRegs);
3776 if (lnp->ic && lnp->ic->op == FUNCTION)
3777 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3779 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3781 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3782 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3789 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3790 && !bitVectBitValue (regsUsed, CND_IDX))
3792 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3793 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3794 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3795 bitVectUnSetBit (regsUsed, CND_IDX);
3798 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3800 /* If this was an interrupt handler that called another function */
3801 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3802 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3804 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3805 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3806 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3807 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3808 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3811 /* Remove the unneeded push/pops */
3812 regsUnneeded = newBitVect (mcs51_nRegs);
3815 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3817 if (!strncmp(lnp->line, "push", 4))
3819 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3820 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3822 connectLine (lnp->prev, lnp->next);
3823 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3826 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3828 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3829 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3831 connectLine (lnp->prev, lnp->next);
3832 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3839 for (idx = 0; idx < regsUnneeded->size; idx++)
3840 if (bitVectBitValue (regsUnneeded, idx))
3841 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3843 freeBitVect (regsUnneeded);
3844 freeBitVect (regsUsed);
3845 freeBitVect (regsUsedPrologue);
3848 /*-----------------------------------------------------------------*/
3849 /* genRet - generate code for return statement */
3850 /*-----------------------------------------------------------------*/
3854 int size, offset = 0, pushed = 0;
3856 D(emitcode ("; genRet",""));
3858 /* if we have no return value then
3859 just generate the "ret" */
3863 /* we have something to return then
3864 move the return value into place */
3865 aopOp (IC_LEFT (ic), ic, FALSE);
3866 size = AOP_SIZE (IC_LEFT (ic));
3869 if (IS_BIT(_G.currentFunc->etype))
3871 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3878 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3881 l = aopGet (IC_LEFT (ic), offset++,
3883 emitcode ("push", "%s", l);
3888 l = aopGet (IC_LEFT (ic), offset,
3890 if (strcmp (fReturn[offset], l))
3891 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3898 if (strcmp (fReturn[pushed], "a"))
3899 emitcode ("pop", fReturn[pushed]);
3901 emitcode ("pop", "acc");
3903 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3906 /* generate a jump to the return label
3907 if the next is not the return statement */
3908 if (!(ic->next && ic->next->op == LABEL &&
3909 IC_LABEL (ic->next) == returnLabel))
3911 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3915 /*-----------------------------------------------------------------*/
3916 /* genLabel - generates a label */
3917 /*-----------------------------------------------------------------*/
3919 genLabel (iCode * ic)
3921 /* special case never generate */
3922 if (IC_LABEL (ic) == entryLabel)
3925 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3928 /*-----------------------------------------------------------------*/
3929 /* genGoto - generates a ljmp */
3930 /*-----------------------------------------------------------------*/
3932 genGoto (iCode * ic)
3934 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3937 /*-----------------------------------------------------------------*/
3938 /* findLabelBackwards: walks back through the iCode chain looking */
3939 /* for the given label. Returns number of iCode instructions */
3940 /* between that label and given ic. */
3941 /* Returns zero if label not found. */
3942 /*-----------------------------------------------------------------*/
3944 findLabelBackwards (iCode * ic, int key)
3953 /* If we have any pushes or pops, we cannot predict the distance.
3954 I don't like this at all, this should be dealt with in the
3956 if (ic->op == IPUSH || ic->op == IPOP) {
3960 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3969 /*-----------------------------------------------------------------*/
3970 /* genPlusIncr :- does addition with increment if possible */
3971 /*-----------------------------------------------------------------*/
3973 genPlusIncr (iCode * ic)
3975 unsigned int icount;
3976 unsigned int size = getDataSize (IC_RESULT (ic));
3978 /* will try to generate an increment */
3979 /* if the right side is not a literal
3981 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3984 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3986 D(emitcode ("; genPlusIncr",""));
3988 /* if increment >=16 bits in register or direct space */
3989 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3990 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3991 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3999 /* If the next instruction is a goto and the goto target
4000 * is < 10 instructions previous to this, we can generate
4001 * jumps straight to that target.
4003 if (ic->next && ic->next->op == GOTO
4004 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4005 && labelRange <= 10)
4007 emitcode (";", "tail increment optimized");
4008 tlbl = IC_LABEL (ic->next);
4013 tlbl = newiTempLabel (NULL);
4016 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4017 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4018 IS_AOP_PREG (IC_RESULT (ic)))
4019 emitcode ("cjne", "%s,#0x00,%05d$",
4020 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4024 emitcode ("clr", "a");
4025 emitcode ("cjne", "a,%s,%05d$",
4026 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4030 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4033 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4034 IS_AOP_PREG (IC_RESULT (ic)))
4035 emitcode ("cjne", "%s,#0x00,%05d$",
4036 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4039 emitcode ("cjne", "a,%s,%05d$",
4040 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4043 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4047 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4048 IS_AOP_PREG (IC_RESULT (ic)))
4049 emitcode ("cjne", "%s,#0x00,%05d$",
4050 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4054 emitcode ("cjne", "a,%s,%05d$",
4055 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4058 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4063 emitcode ("", "%05d$:", tlbl->key + 100);
4068 /* if result is dptr */
4069 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4070 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4071 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4072 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4074 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4080 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4083 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
4084 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
4086 emitcode ("inc", "dptr");
4091 /* if the literal value of the right hand side
4092 is greater than 4 then it is not worth it */
4096 /* if the sizes are greater than 1 then we cannot */
4097 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4098 AOP_SIZE (IC_LEFT (ic)) > 1)
4101 /* we can if the aops of the left & result match or
4102 if they are in registers and the registers are the
4104 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4109 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4110 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4111 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4117 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4126 /*-----------------------------------------------------------------*/
4127 /* outBitAcc - output a bit in acc */
4128 /*-----------------------------------------------------------------*/
4130 outBitAcc (operand * result)
4132 symbol *tlbl = newiTempLabel (NULL);
4133 /* if the result is a bit */
4134 if (AOP_TYPE (result) == AOP_CRY)
4136 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4140 emitcode ("jz", "%05d$", tlbl->key + 100);
4141 emitcode ("mov", "a,%s", one);
4142 emitcode ("", "%05d$:", tlbl->key + 100);
4147 /*-----------------------------------------------------------------*/
4148 /* genPlusBits - generates code for addition of two bits */
4149 /*-----------------------------------------------------------------*/
4151 genPlusBits (iCode * ic)
4153 D(emitcode ("; genPlusBits",""));
4155 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4157 symbol *lbl = newiTempLabel (NULL);
4158 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4159 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4160 emitcode ("cpl", "c");
4161 emitcode ("", "%05d$:", (lbl->key + 100));
4162 outBitC (IC_RESULT (ic));
4166 emitcode ("clr", "a");
4167 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4168 emitcode ("rlc", "a");
4169 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4170 emitcode ("addc", "a,#0x00");
4171 outAcc (IC_RESULT (ic));
4176 /* This is the original version of this code.
4178 * This is being kept around for reference,
4179 * because I am not entirely sure I got it right...
4182 adjustArithmeticResult (iCode * ic)
4184 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4185 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4186 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4187 aopPut (IC_RESULT (ic),
4188 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4190 isOperandVolatile (IC_RESULT (ic), FALSE));
4192 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4193 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4194 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4195 aopPut (IC_RESULT (ic),
4196 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4198 isOperandVolatile (IC_RESULT (ic), FALSE));
4200 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4201 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4202 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4203 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4204 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4207 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4208 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4212 /* This is the pure and virtuous version of this code.
4213 * I'm pretty certain it's right, but not enough to toss the old
4217 adjustArithmeticResult (iCode * ic)
4219 if (opIsGptr (IC_RESULT (ic)) &&
4220 opIsGptr (IC_LEFT (ic)) &&
4221 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4223 aopPut (IC_RESULT (ic),
4224 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4226 isOperandVolatile (IC_RESULT (ic), FALSE));
4229 if (opIsGptr (IC_RESULT (ic)) &&
4230 opIsGptr (IC_RIGHT (ic)) &&
4231 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4233 aopPut (IC_RESULT (ic),
4234 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4236 isOperandVolatile (IC_RESULT (ic), FALSE));
4239 if (opIsGptr (IC_RESULT (ic)) &&
4240 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4241 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4242 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4243 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4246 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4247 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4252 /*-----------------------------------------------------------------*/
4253 /* genPlus - generates code for addition */
4254 /*-----------------------------------------------------------------*/
4256 genPlus (iCode * ic)
4258 int size, offset = 0;
4261 bool swappedLR = FALSE;
4262 operand *leftOp, *rightOp;
4265 /* special cases :- */
4267 D(emitcode ("; genPlus",""));
4269 aopOp (IC_LEFT (ic), ic, FALSE);
4270 aopOp (IC_RIGHT (ic), ic, FALSE);
4271 aopOp (IC_RESULT (ic), ic, TRUE);
4273 /* if literal, literal on the right or
4274 if left requires ACC or right is already
4276 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4277 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4278 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4280 operand *t = IC_RIGHT (ic);
4281 IC_RIGHT (ic) = IC_LEFT (ic);
4286 /* if both left & right are in bit
4288 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4289 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4295 /* if left in bit space & right literal */
4296 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4297 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4299 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4300 /* if result in bit space */
4301 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4303 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4304 emitcode ("cpl", "c");
4305 outBitC (IC_RESULT (ic));
4309 size = getDataSize (IC_RESULT (ic));
4312 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4313 emitcode ("addc", "a,#00");
4314 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4320 /* if I can do an increment instead
4321 of add then GOOD for ME */
4322 if (genPlusIncr (ic) == TRUE)
4325 size = getDataSize (IC_RESULT (ic));
4326 leftOp = IC_LEFT(ic);
4327 rightOp = IC_RIGHT(ic);
4330 /* if this is an add for an array access
4331 at a 256 byte boundary */
4333 && AOP_TYPE (op) == AOP_IMMD
4335 && IS_SPEC (OP_SYM_ETYPE (op))
4336 && SPEC_ABSA (OP_SYM_ETYPE (op))
4337 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4340 D(emitcode ("; genPlus aligned array",""));
4341 aopPut (IC_RESULT (ic),
4342 aopGet (rightOp, 0, FALSE, FALSE),
4344 isOperandVolatile (IC_RESULT (ic), FALSE));
4346 if( 1 == getDataSize (IC_RIGHT (ic)) )
4348 aopPut (IC_RESULT (ic),
4349 aopGet (leftOp, 1, FALSE, FALSE),
4351 isOperandVolatile (IC_RESULT (ic), FALSE));
4355 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4356 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4357 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4362 /* if the lower bytes of a literal are zero skip the addition */
4363 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4365 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4366 (skip_bytes+1 < size))
4371 D(emitcode ("; genPlus shortcut",""));
4376 if( offset >= skip_bytes )
4378 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4381 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4383 emitcode("xch", "a,b");
4384 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4385 emitcode (add, "a,b");
4388 else if (aopGetUsesAcc (leftOp, offset))
4390 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4391 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4395 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4396 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4398 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4399 add = "addc"; /* further adds must propagate carry */
4403 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4404 isOperandVolatile (IC_RESULT (ic), FALSE))
4407 aopPut (IC_RESULT (ic),
4408 aopGet (leftOp, offset, FALSE, FALSE),
4410 isOperandVolatile (IC_RESULT (ic), FALSE));
4416 adjustArithmeticResult (ic);
4419 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4422 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4423 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4427 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4428 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4432 /*-----------------------------------------------------------------*/
4433 /* genMinusDec :- does subtraction with decrement if possible */
4434 /*-----------------------------------------------------------------*/
4436 genMinusDec (iCode * ic)
4438 unsigned int icount;
4439 unsigned int size = getDataSize (IC_RESULT (ic));
4441 /* will try to generate an increment */
4442 /* if the right side is not a literal
4444 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4447 /* if the literal value of the right hand side
4448 is greater than 4 then it is not worth it */
4449 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4452 D(emitcode ("; genMinusDec",""));
4454 /* if decrement >=16 bits in register or direct space */
4455 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4456 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4464 /* If the next instruction is a goto and the goto target
4465 * is <= 10 instructions previous to this, we can generate
4466 * jumps straight to that target.
4468 if (ic->next && ic->next->op == GOTO
4469 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4470 && labelRange <= 10)
4472 emitcode (";", "tail decrement optimized");
4473 tlbl = IC_LABEL (ic->next);
4478 tlbl = newiTempLabel (NULL);
4482 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4483 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4484 IS_AOP_PREG (IC_RESULT (ic)))
4485 emitcode ("cjne", "%s,#0xff,%05d$"
4486 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4490 emitcode ("mov", "a,#0xff");
4491 emitcode ("cjne", "a,%s,%05d$"
4492 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4495 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4498 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4499 IS_AOP_PREG (IC_RESULT (ic)))
4500 emitcode ("cjne", "%s,#0xff,%05d$"
4501 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4505 emitcode ("cjne", "a,%s,%05d$"
4506 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4509 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4513 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4514 IS_AOP_PREG (IC_RESULT (ic)))
4515 emitcode ("cjne", "%s,#0xff,%05d$"
4516 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4520 emitcode ("cjne", "a,%s,%05d$"
4521 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4524 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4528 emitcode ("", "%05d$:", tlbl->key + 100);
4533 /* if the sizes are greater than 1 then we cannot */
4534 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4535 AOP_SIZE (IC_LEFT (ic)) > 1)
4538 /* we can if the aops of the left & result match or
4539 if they are in registers and the registers are the
4541 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4545 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4547 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4552 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4556 emitcode ("dec", "%s", l);
4558 if (AOP_NEEDSACC (IC_RESULT (ic)))
4559 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4567 /*-----------------------------------------------------------------*/
4568 /* addSign - complete with sign */
4569 /*-----------------------------------------------------------------*/
4571 addSign (operand * result, int offset, int sign)
4573 int size = (getDataSize (result) - offset);
4578 emitcode ("rlc", "a");
4579 emitcode ("subb", "a,acc");
4581 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4585 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4589 /*-----------------------------------------------------------------*/
4590 /* genMinusBits - generates code for subtraction of two bits */
4591 /*-----------------------------------------------------------------*/
4593 genMinusBits (iCode * ic)
4595 symbol *lbl = newiTempLabel (NULL);
4597 D(emitcode ("; genMinusBits",""));
4599 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4601 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4602 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4603 emitcode ("cpl", "c");
4604 emitcode ("", "%05d$:", (lbl->key + 100));
4605 outBitC (IC_RESULT (ic));
4609 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4610 emitcode ("subb", "a,acc");
4611 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4612 emitcode ("inc", "a");
4613 emitcode ("", "%05d$:", (lbl->key + 100));
4614 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4615 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4619 /*-----------------------------------------------------------------*/
4620 /* genMinus - generates code for subtraction */
4621 /*-----------------------------------------------------------------*/
4623 genMinus (iCode * ic)
4625 int size, offset = 0;
4627 D(emitcode ("; genMinus",""));
4629 aopOp (IC_LEFT (ic), ic, FALSE);
4630 aopOp (IC_RIGHT (ic), ic, FALSE);
4631 aopOp (IC_RESULT (ic), ic, TRUE);
4633 /* special cases :- */
4634 /* if both left & right are in bit space */
4635 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4636 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4642 /* if I can do an decrement instead
4643 of subtract then GOOD for ME */
4644 if (genMinusDec (ic) == TRUE)
4647 size = getDataSize (IC_RESULT (ic));
4649 /* if literal, add a,#-lit, else normal subb */
4650 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4652 unsigned long lit = 0L;
4653 bool useCarry = FALSE;
4655 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4660 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4662 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4663 if (!offset && !size && lit== (unsigned long) -1)
4665 emitcode ("dec", "a");
4669 /* first add without previous c */
4670 emitcode ("add", "a,#0x%02x",
4671 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4676 emitcode ("addc", "a,#0x%02x",
4677 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4679 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4683 /* no need to add zeroes */
4684 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4686 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4687 offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4695 operand *leftOp, *rightOp;
4697 leftOp = IC_LEFT(ic);
4698 rightOp = IC_RIGHT(ic);
4702 if (aopGetUsesAcc(rightOp, offset)) {
4703 if (aopGetUsesAcc(leftOp, offset)) {
4706 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4708 emitcode ("mov", "b,a");
4711 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4712 emitcode ("subb", "a,b");
4715 /* reverse subtraction with 2's complement */
4717 emitcode( "setb", "c");
4719 emitcode( "cpl", "c");
4720 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4721 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4722 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4723 emitcode("cpl", "a");
4724 if (size) /* skip if last byte */
4725 emitcode( "cpl", "c");
4728 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4731 emitcode ("subb", "a,%s",
4732 aopGet(rightOp, offset, FALSE, TRUE));
4735 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4740 adjustArithmeticResult (ic);
4743 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4744 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4745 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4749 /*-----------------------------------------------------------------*/
4750 /* genMultbits :- multiplication of bits */
4751 /*-----------------------------------------------------------------*/
4753 genMultbits (operand * left,
4757 D(emitcode ("; genMultbits",""));
4759 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4760 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4764 /*-----------------------------------------------------------------*/
4765 /* genMultOneByte : 8*8=8/16 bit multiplication */
4766 /*-----------------------------------------------------------------*/
4768 genMultOneByte (operand * left,
4773 int size = AOP_SIZE (result);
4774 bool runtimeSign, compiletimeSign;
4775 bool lUnsigned, rUnsigned, pushedB;
4777 D(emitcode ("; genMultOneByte",""));
4779 if (size < 1 || size > 2)
4781 /* this should never happen */
4782 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4783 AOP_SIZE(result), __FILE__, lineno);
4787 /* (if two literals: the value is computed before) */
4788 /* if one literal, literal on the right */
4789 if (AOP_TYPE (left) == AOP_LIT)
4794 /* emitcode (";", "swapped left and right"); */
4796 /* if no literal, unsigned on the right: shorter code */
4797 if ( AOP_TYPE (right) != AOP_LIT
4798 && SPEC_USIGN (getSpec (operandType (left))))
4805 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4806 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4810 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4811 no need to take care about the signedness! */
4812 || (lUnsigned && rUnsigned))
4814 /* just an unsigned 8 * 8 = 8 multiply
4816 /* emitcode (";","unsigned"); */
4817 /* TODO: check for accumulator clash between left & right aops? */
4819 if (AOP_TYPE (right) == AOP_LIT)
4821 /* moving to accumulator first helps peepholes */
4822 MOVA (aopGet (left, 0, FALSE, FALSE));
4823 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4827 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4828 MOVA (aopGet (left, 0, FALSE, FALSE));
4831 emitcode ("mul", "ab");
4832 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4834 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4840 /* we have to do a signed multiply */
4841 /* emitcode (";", "signed"); */
4843 /* now sign adjust for both left & right */
4845 /* let's see what's needed: */
4846 /* apply negative sign during runtime */
4847 runtimeSign = FALSE;
4848 /* negative sign from literals */
4849 compiletimeSign = FALSE;
4853 if (AOP_TYPE(left) == AOP_LIT)
4855 /* signed literal */
4856 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4858 compiletimeSign = TRUE;
4861 /* signed but not literal */
4867 if (AOP_TYPE(right) == AOP_LIT)
4869 /* signed literal */
4870 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4872 compiletimeSign ^= TRUE;
4875 /* signed but not literal */
4879 /* initialize F0, which stores the runtime sign */
4882 if (compiletimeSign)
4883 emitcode ("setb", "F0"); /* set sign flag */
4885 emitcode ("clr", "F0"); /* reset sign flag */
4888 /* save the signs of the operands */
4889 if (AOP_TYPE(right) == AOP_LIT)
4891 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4893 if (!rUnsigned && val < 0)
4894 emitcode ("mov", "b,#0x%02x", -val);
4896 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4898 else /* ! literal */
4900 if (rUnsigned) /* emitcode (";", "signed"); */
4902 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4905 MOVA (aopGet (right, 0, FALSE, FALSE));
4906 lbl = newiTempLabel (NULL);
4907 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4908 emitcode ("cpl", "F0"); /* complement sign flag */
4909 emitcode ("cpl", "a"); /* 2's complement */
4910 emitcode ("inc", "a");
4911 emitcode ("", "%05d$:", (lbl->key + 100));
4912 emitcode ("mov", "b,a");
4916 if (AOP_TYPE(left) == AOP_LIT)
4918 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4920 if (!lUnsigned && val < 0)
4921 emitcode ("mov", "a,#0x%02x", -val);
4923 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4925 else /* ! literal */
4927 MOVA (aopGet (left, 0, FALSE, FALSE));
4931 lbl = newiTempLabel (NULL);
4932 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4933 emitcode ("cpl", "F0"); /* complement sign flag */
4934 emitcode ("cpl", "a"); /* 2's complement */
4935 emitcode ("inc", "a");
4936 emitcode ("", "%05d$:", (lbl->key + 100));
4940 /* now the multiplication */
4941 emitcode ("mul", "ab");
4942 if (runtimeSign || compiletimeSign)
4944 lbl = newiTempLabel (NULL);
4946 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4947 emitcode ("cpl", "a"); /* lsb 2's complement */
4949 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4952 emitcode ("add", "a,#1"); /* this sets carry flag */
4953 emitcode ("xch", "a,b");
4954 emitcode ("cpl", "a"); /* msb 2's complement */
4955 emitcode ("addc", "a,#0");
4956 emitcode ("xch", "a,b");
4958 emitcode ("", "%05d$:", (lbl->key + 100));
4960 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4962 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4967 /*-----------------------------------------------------------------*/
4968 /* genMult - generates code for multiplication */
4969 /*-----------------------------------------------------------------*/
4971 genMult (iCode * ic)
4973 operand *left = IC_LEFT (ic);
4974 operand *right = IC_RIGHT (ic);
4975 operand *result = IC_RESULT (ic);
4977 D(emitcode ("; genMult",""));
4979 /* assign the asmops */
4980 aopOp (left, ic, FALSE);
4981 aopOp (right, ic, FALSE);
4982 aopOp (result, ic, TRUE);
4984 /* special cases first */
4986 if (AOP_TYPE (left) == AOP_CRY &&
4987 AOP_TYPE (right) == AOP_CRY)
4989 genMultbits (left, right, result);
4993 /* if both are of size == 1 */
4994 #if 0 // one of them can be a sloc shared with the result
4995 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4997 if (getSize(operandType(left)) == 1 &&
4998 getSize(operandType(right)) == 1)
5001 genMultOneByte (left, right, result);
5005 /* should have been converted to function call */
5006 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
5007 getSize(OP_SYMBOL(right)->type));
5011 freeAsmop (result, NULL, ic, TRUE);
5012 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5013 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5016 /*-----------------------------------------------------------------*/
5017 /* genDivbits :- division of bits */
5018 /*-----------------------------------------------------------------*/
5020 genDivbits (operand * left,
5027 D(emitcode ("; genDivbits",""));
5031 /* the result must be bit */
5032 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5033 l = aopGet (left, 0, FALSE, FALSE);
5037 emitcode ("div", "ab");
5038 emitcode ("rrc", "a");
5042 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5045 /*-----------------------------------------------------------------*/
5046 /* genDivOneByte : 8 bit division */
5047 /*-----------------------------------------------------------------*/
5049 genDivOneByte (operand * left,
5053 bool lUnsigned, rUnsigned, pushedB;
5054 bool runtimeSign, compiletimeSign;
5055 bool accuse = FALSE;
5056 bool pushedA = FALSE;
5060 D(emitcode ("; genDivOneByte",""));
5062 /* Why is it necessary that genDivOneByte() can return an int result?
5065 volatile unsigned char uc;
5066 volatile signed char sc1, sc2;
5079 In all cases a one byte result would overflow, the following cast to int
5080 would return the wrong result.
5082 Two possible solution:
5083 a) cast operands to int, if ((unsigned) / (signed)) or
5084 ((signed) / (signed))
5085 b) return an 16 bit signed int; this is what we're doing here!
5088 size = AOP_SIZE (result) - 1;
5090 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5091 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5095 /* signed or unsigned */
5096 if (lUnsigned && rUnsigned)
5098 /* unsigned is easy */
5099 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5100 MOVA (aopGet (left, 0, FALSE, FALSE));
5101 emitcode ("div", "ab");
5102 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5104 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5110 /* signed is a little bit more difficult */
5112 /* now sign adjust for both left & right */
5114 /* let's see what's needed: */
5115 /* apply negative sign during runtime */
5116 runtimeSign = FALSE;
5117 /* negative sign from literals */
5118 compiletimeSign = FALSE;
5122 if (AOP_TYPE(left) == AOP_LIT)
5124 /* signed literal */
5125 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5127 compiletimeSign = TRUE;
5130 /* signed but not literal */
5136 if (AOP_TYPE(right) == AOP_LIT)
5138 /* signed literal */
5139 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5141 compiletimeSign ^= TRUE;
5144 /* signed but not literal */
5148 /* initialize F0, which stores the runtime sign */
5151 if (compiletimeSign)
5152 emitcode ("setb", "F0"); /* set sign flag */
5154 emitcode ("clr", "F0"); /* reset sign flag */
5157 /* save the signs of the operands */
5158 if (AOP_TYPE(right) == AOP_LIT)
5160 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5162 if (!rUnsigned && val < 0)
5163 emitcode ("mov", "b,#0x%02x", -val);
5165 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5167 else /* ! literal */
5170 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5173 MOVA (aopGet (right, 0, FALSE, FALSE));
5174 lbl = newiTempLabel (NULL);
5175 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5176 emitcode ("cpl", "F0"); /* complement sign flag */
5177 emitcode ("cpl", "a"); /* 2's complement */
5178 emitcode ("inc", "a");
5179 emitcode ("", "%05d$:", (lbl->key + 100));
5180 emitcode ("mov", "b,a");
5184 if (AOP_TYPE(left) == AOP_LIT)
5186 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5188 if (!lUnsigned && val < 0)
5189 emitcode ("mov", "a,#0x%02x", -val);
5191 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5193 else /* ! literal */
5195 MOVA (aopGet (left, 0, FALSE, FALSE));
5199 lbl = newiTempLabel (NULL);
5200 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5201 emitcode ("cpl", "F0"); /* complement sign flag */
5202 emitcode ("cpl", "a"); /* 2's complement */
5203 emitcode ("inc", "a");
5204 emitcode ("", "%05d$:", (lbl->key + 100));
5208 /* now the division */
5209 emitcode ("div", "ab");
5211 if (runtimeSign || compiletimeSign)
5213 lbl = newiTempLabel (NULL);
5215 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5216 emitcode ("cpl", "a"); /* lsb 2's complement */
5217 emitcode ("inc", "a");
5218 emitcode ("", "%05d$:", (lbl->key + 100));
5220 accuse = aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5223 /* msb is 0x00 or 0xff depending on the sign */
5228 emitcode ("push", "acc");
5231 emitcode ("mov", "c,F0");
5232 emitcode ("subb", "a,acc");
5234 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5236 else /* compiletimeSign */
5238 if (aopPutUsesAcc (result, "#0xFF", offset))
5240 emitcode ("push", "acc");
5244 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5250 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5252 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5256 emitcode ("pop", "acc");
5260 /*-----------------------------------------------------------------*/
5261 /* genDiv - generates code for division */
5262 /*-----------------------------------------------------------------*/
5266 operand *left = IC_LEFT (ic);
5267 operand *right = IC_RIGHT (ic);
5268 operand *result = IC_RESULT (ic);
5270 D(emitcode ("; genDiv",""));
5272 /* assign the amsops */
5273 aopOp (left, ic, FALSE);
5274 aopOp (right, ic, FALSE);
5275 aopOp (result, ic, TRUE);
5277 /* special cases first */
5279 if (AOP_TYPE (left) == AOP_CRY &&
5280 AOP_TYPE (right) == AOP_CRY)
5282 genDivbits (left, right, result);
5286 /* if both are of size == 1 */
5287 if (AOP_SIZE (left) == 1 &&
5288 AOP_SIZE (right) == 1)
5290 genDivOneByte (left, right, result);
5294 /* should have been converted to function call */
5297 freeAsmop (result, NULL, ic, TRUE);
5298 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5299 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5302 /*-----------------------------------------------------------------*/
5303 /* genModbits :- modulus of bits */
5304 /*-----------------------------------------------------------------*/
5306 genModbits (operand * left,
5313 D(emitcode ("; genModbits",""));
5317 /* the result must be bit */
5318 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5319 l = aopGet (left, 0, FALSE, FALSE);
5323 emitcode ("div", "ab");
5324 emitcode ("mov", "a,b");
5325 emitcode ("rrc", "a");
5329 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5332 /*-----------------------------------------------------------------*/
5333 /* genModOneByte : 8 bit modulus */
5334 /*-----------------------------------------------------------------*/
5336 genModOneByte (operand * left,
5340 bool lUnsigned, rUnsigned, pushedB;
5341 bool runtimeSign, compiletimeSign;
5345 D(emitcode ("; genModOneByte",""));
5347 size = AOP_SIZE (result) - 1;
5349 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5350 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5352 /* if right is a literal, check it for 2^n */
5353 if (AOP_TYPE(right) == AOP_LIT)
5355 unsigned char val = abs((int) operandLitValue(right));
5356 symbol *lbl2 = NULL;
5360 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5369 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5370 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5371 /* because iCode should have been changed to genAnd */
5372 /* see file "SDCCopt.c", function "convertToFcall()" */
5374 MOVA (aopGet (left, 0, FALSE, FALSE));
5375 emitcode ("mov", "c,acc.7");
5376 emitcode ("anl", "a,#0x%02x", val - 1);
5377 lbl = newiTempLabel (NULL);
5378 emitcode ("jz", "%05d$", (lbl->key + 100));
5379 emitcode ("jnc", "%05d$", (lbl->key + 100));
5380 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5386 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5388 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5389 lbl2 = newiTempLabel (NULL);
5390 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5392 emitcode ("", "%05d$:", (lbl->key + 100));
5393 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5395 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5398 emitcode ("", "%05d$:", (lbl2->key + 100));
5409 /* signed or unsigned */
5410 if (lUnsigned && rUnsigned)
5412 /* unsigned is easy */
5413 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5414 MOVA (aopGet (left, 0, FALSE, FALSE));
5415 emitcode ("div", "ab");
5416 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5418 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5424 /* signed is a little bit more difficult */
5426 /* now sign adjust for both left & right */
5428 /* modulus: sign of the right operand has no influence on the result! */
5429 if (AOP_TYPE(right) == AOP_LIT)
5431 signed char val = (char) operandLitValue(right);
5433 if (!rUnsigned && val < 0)
5434 emitcode ("mov", "b,#0x%02x", -val);
5436 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5438 else /* not literal */
5441 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5444 MOVA (aopGet (right, 0, FALSE, FALSE));
5445 lbl = newiTempLabel (NULL);
5446 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5447 emitcode ("cpl", "a"); /* 2's complement */
5448 emitcode ("inc", "a");
5449 emitcode ("", "%05d$:", (lbl->key + 100));
5450 emitcode ("mov", "b,a");
5454 /* let's see what's needed: */
5455 /* apply negative sign during runtime */
5456 runtimeSign = FALSE;
5457 /* negative sign from literals */
5458 compiletimeSign = FALSE;
5460 /* sign adjust left side */
5461 if (AOP_TYPE(left) == AOP_LIT)
5463 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5465 if (!lUnsigned && val < 0)
5467 compiletimeSign = TRUE; /* set sign flag */
5468 emitcode ("mov", "a,#0x%02x", -val);
5471 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5473 else /* ! literal */
5475 MOVA (aopGet (left, 0, FALSE, FALSE));
5480 emitcode ("clr", "F0"); /* clear sign flag */
5482 lbl = newiTempLabel (NULL);
5483 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5484 emitcode ("setb", "F0"); /* set sign flag */
5485 emitcode ("cpl", "a"); /* 2's complement */
5486 emitcode ("inc", "a");
5487 emitcode ("", "%05d$:", (lbl->key + 100));
5491 /* now the modulus */
5492 emitcode ("div", "ab");
5494 if (runtimeSign || compiletimeSign)
5496 emitcode ("mov", "a,b");
5497 lbl = newiTempLabel (NULL);
5499 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5500 emitcode ("cpl", "a"); /* 2's complement */
5501 emitcode ("inc", "a");
5502 emitcode ("", "%05d$:", (lbl->key + 100));
5504 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5507 /* msb is 0x00 or 0xff depending on the sign */
5510 emitcode ("mov", "c,F0");
5511 emitcode ("subb", "a,acc");
5513 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5515 else /* compiletimeSign */
5517 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5522 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5524 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5530 /*-----------------------------------------------------------------*/
5531 /* genMod - generates code for division */
5532 /*-----------------------------------------------------------------*/
5536 operand *left = IC_LEFT (ic);
5537 operand *right = IC_RIGHT (ic);
5538 operand *result = IC_RESULT (ic);
5540 D(emitcode ("; genMod",""));
5542 /* assign the asmops */
5543 aopOp (left, ic, FALSE);
5544 aopOp (right, ic, FALSE);
5545 aopOp (result, ic, TRUE);
5547 /* special cases first */
5549 if (AOP_TYPE (left) == AOP_CRY &&
5550 AOP_TYPE (right) == AOP_CRY)
5552 genModbits (left, right, result);
5556 /* if both are of size == 1 */
5557 if (AOP_SIZE (left) == 1 &&
5558 AOP_SIZE (right) == 1)
5560 genModOneByte (left, right, result);
5564 /* should have been converted to function call */
5568 freeAsmop (result, NULL, ic, TRUE);
5569 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5570 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5573 /*-----------------------------------------------------------------*/
5574 /* genIfxJump :- will create a jump depending on the ifx */
5575 /*-----------------------------------------------------------------*/
5577 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5580 symbol *tlbl = newiTempLabel (NULL);
5583 D(emitcode ("; genIfxJump",""));
5585 /* if true label then we jump if condition
5589 jlbl = IC_TRUE (ic);
5590 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5591 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5595 /* false label is present */
5596 jlbl = IC_FALSE (ic);
5597 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5598 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5600 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5601 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5603 emitcode (inst, "%05d$", tlbl->key + 100);
5604 freeForBranchAsmop (result);
5605 freeForBranchAsmop (right);
5606 freeForBranchAsmop (left);
5607 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5608 emitcode ("", "%05d$:", tlbl->key + 100);
5610 /* mark the icode as generated */
5614 /*-----------------------------------------------------------------*/
5615 /* genCmp :- greater or less than comparison */
5616 /*-----------------------------------------------------------------*/
5618 genCmp (operand * left, operand * right,
5619 operand * result, iCode * ifx, int sign, iCode *ic)
5621 int size, offset = 0;
5622 unsigned long lit = 0L;
5625 D(emitcode ("; genCmp",""));
5627 /* if left & right are bit variables */
5628 if (AOP_TYPE (left) == AOP_CRY &&
5629 AOP_TYPE (right) == AOP_CRY)
5631 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5632 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5636 /* subtract right from left if at the
5637 end the carry flag is set then we know that
5638 left is greater than right */
5639 size = max (AOP_SIZE (left), AOP_SIZE (right));
5641 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5642 if ((size == 1) && !sign &&
5643 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5645 symbol *lbl = newiTempLabel (NULL);
5646 emitcode ("cjne", "%s,%s,%05d$",
5647 aopGet (left, offset, FALSE, FALSE),
5648 aopGet (right, offset, FALSE, FALSE),
5650 emitcode ("", "%05d$:", lbl->key + 100);
5654 if (AOP_TYPE (right) == AOP_LIT)
5656 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5657 /* optimize if(x < 0) or if(x >= 0) */
5666 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5667 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5669 genIfxJump (ifx, "acc.7", left, right, result);
5670 freeAsmop (right, NULL, ic, TRUE);
5671 freeAsmop (left, NULL, ic, TRUE);
5676 emitcode ("rlc", "a");
5684 bool pushedB = FALSE;
5685 rightInB = aopGetUsesAcc(right, offset);
5689 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5691 MOVA (aopGet (left, offset, FALSE, FALSE));
5692 if (sign && size == 0)
5694 emitcode ("xrl", "a,#0x80");
5695 if (AOP_TYPE (right) == AOP_LIT)
5697 unsigned long lit = (unsigned long)
5698 floatFromVal (AOP (right)->aopu.aop_lit);
5699 emitcode ("subb", "a,#0x%02x",
5700 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5708 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5710 emitcode ("xrl", "b,#0x80");
5711 emitcode ("subb", "a,b");
5717 emitcode ("subb", "a,b");
5719 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5729 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5730 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5731 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5737 /* if the result is used in the next
5738 ifx conditional branch then generate
5739 code a little differently */
5741 genIfxJump (ifx, "c", NULL, NULL, result);
5744 /* leave the result in acc */
5748 /*-----------------------------------------------------------------*/
5749 /* genCmpGt :- greater than comparison */
5750 /*-----------------------------------------------------------------*/
5752 genCmpGt (iCode * ic, iCode * ifx)
5754 operand *left, *right, *result;
5755 sym_link *letype, *retype;
5758 D(emitcode ("; genCmpGt",""));
5760 left = IC_LEFT (ic);
5761 right = IC_RIGHT (ic);
5762 result = IC_RESULT (ic);
5764 letype = getSpec (operandType (left));
5765 retype = getSpec (operandType (right));
5766 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5767 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5768 /* assign the amsops */
5769 aopOp (result, ic, TRUE);
5770 aopOp (left, ic, FALSE);
5771 aopOp (right, ic, FALSE);
5773 genCmp (right, left, result, ifx, sign, ic);
5775 freeAsmop (result, NULL, ic, TRUE);
5778 /*-----------------------------------------------------------------*/
5779 /* genCmpLt - less than comparisons */
5780 /*-----------------------------------------------------------------*/
5782 genCmpLt (iCode * ic, iCode * ifx)
5784 operand *left, *right, *result;
5785 sym_link *letype, *retype;
5788 D(emitcode ("; genCmpLt",""));
5790 left = IC_LEFT (ic);
5791 right = IC_RIGHT (ic);
5792 result = IC_RESULT (ic);
5794 letype = getSpec (operandType (left));
5795 retype = getSpec (operandType (right));
5796 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5797 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5798 /* assign the amsops */
5799 aopOp (result, ic, TRUE);
5800 aopOp (left, ic, FALSE);
5801 aopOp (right, ic, FALSE);
5803 genCmp (left, right, result, ifx, sign, ic);
5805 freeAsmop (result, NULL, ic, TRUE);
5808 /*-----------------------------------------------------------------*/
5809 /* gencjneshort - compare and jump if not equal */
5810 /*-----------------------------------------------------------------*/
5812 gencjneshort (operand * left, operand * right, symbol * lbl)
5814 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5816 unsigned long lit = 0L;
5818 /* if the left side is a literal or
5819 if the right is in a pointer register and left
5821 if ((AOP_TYPE (left) == AOP_LIT) ||
5822 (AOP_TYPE (left) == AOP_IMMD) ||
5823 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5830 if (AOP_TYPE (right) == AOP_LIT)
5831 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5833 /* if the right side is a literal then anything goes */
5834 if (AOP_TYPE (right) == AOP_LIT &&
5835 AOP_TYPE (left) != AOP_DIR &&
5836 AOP_TYPE (left) != AOP_IMMD)
5840 emitcode ("cjne", "%s,%s,%05d$",
5841 aopGet (left, offset, FALSE, FALSE),
5842 aopGet (right, offset, FALSE, FALSE),
5848 /* if the right side is in a register or in direct space or
5849 if the left is a pointer register & right is not */
5850 else if (AOP_TYPE (right) == AOP_REG ||
5851 AOP_TYPE (right) == AOP_DIR ||
5852 AOP_TYPE (right) == AOP_LIT ||
5853 AOP_TYPE (right) == AOP_IMMD ||
5854 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5855 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5859 MOVA (aopGet (left, offset, FALSE, FALSE));
5860 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5861 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5862 emitcode ("jnz", "%05d$", lbl->key + 100);
5864 emitcode ("cjne", "a,%s,%05d$",
5865 aopGet (right, offset, FALSE, TRUE),
5872 /* right is a pointer reg need both a & b */
5876 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5877 wassertl(!BINUSE, "B was in use");
5878 l = aopGet (left, offset, FALSE, FALSE);
5879 if (strcmp (l, "b"))
5880 emitcode ("mov", "b,%s", l);
5881 MOVA (aopGet (right, offset, FALSE, FALSE));
5882 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5888 /*-----------------------------------------------------------------*/
5889 /* gencjne - compare and jump if not equal */
5890 /*-----------------------------------------------------------------*/
5892 gencjne (operand * left, operand * right, symbol * lbl)
5894 symbol *tlbl = newiTempLabel (NULL);
5896 gencjneshort (left, right, lbl);
5898 emitcode ("mov", "a,%s", one);
5899 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5900 emitcode ("", "%05d$:", lbl->key + 100);
5901 emitcode ("clr", "a");
5902 emitcode ("", "%05d$:", tlbl->key + 100);
5905 /*-----------------------------------------------------------------*/
5906 /* genCmpEq - generates code for equal to */
5907 /*-----------------------------------------------------------------*/
5909 genCmpEq (iCode * ic, iCode * ifx)
5911 bool swappedLR = FALSE;
5912 operand *left, *right, *result;
5914 D(emitcode ("; genCmpEq",""));
5916 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5917 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5918 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5920 /* if literal, literal on the right or
5921 if the right is in a pointer register and left
5923 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5924 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5926 operand *t = IC_RIGHT (ic);
5927 IC_RIGHT (ic) = IC_LEFT (ic);
5932 if (ifx && !AOP_SIZE (result))
5935 /* if they are both bit variables */
5936 if (AOP_TYPE (left) == AOP_CRY &&
5937 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5939 if (AOP_TYPE (right) == AOP_LIT)
5941 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5944 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5945 emitcode ("cpl", "c");
5949 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5953 emitcode ("clr", "c");
5955 /* AOP_TYPE(right) == AOP_CRY */
5959 symbol *lbl = newiTempLabel (NULL);
5960 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5961 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5962 emitcode ("cpl", "c");
5963 emitcode ("", "%05d$:", (lbl->key + 100));
5965 /* if true label then we jump if condition
5967 tlbl = newiTempLabel (NULL);
5970 emitcode ("jnc", "%05d$", tlbl->key + 100);
5971 freeForBranchAsmop (result);
5972 freeForBranchAsmop (right);
5973 freeForBranchAsmop (left);
5974 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5978 emitcode ("jc", "%05d$", tlbl->key + 100);
5979 freeForBranchAsmop (result);
5980 freeForBranchAsmop (right);
5981 freeForBranchAsmop (left);
5982 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5984 emitcode ("", "%05d$:", tlbl->key + 100);
5988 tlbl = newiTempLabel (NULL);
5989 gencjneshort (left, right, tlbl);
5992 freeForBranchAsmop (result);
5993 freeForBranchAsmop (right);
5994 freeForBranchAsmop (left);
5995 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5996 emitcode ("", "%05d$:", tlbl->key + 100);
6000 symbol *lbl = newiTempLabel (NULL);
6001 emitcode ("sjmp", "%05d$", lbl->key + 100);
6002 emitcode ("", "%05d$:", tlbl->key + 100);
6003 freeForBranchAsmop (result);
6004 freeForBranchAsmop (right);
6005 freeForBranchAsmop (left);
6006 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
6007 emitcode ("", "%05d$:", lbl->key + 100);
6010 /* mark the icode as generated */
6015 /* if they are both bit variables */
6016 if (AOP_TYPE (left) == AOP_CRY &&
6017 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
6019 if (AOP_TYPE (right) == AOP_LIT)
6021 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6024 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6025 emitcode ("cpl", "c");
6029 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6033 emitcode ("clr", "c");
6035 /* AOP_TYPE(right) == AOP_CRY */
6039 symbol *lbl = newiTempLabel (NULL);
6040 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6041 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6042 emitcode ("cpl", "c");
6043 emitcode ("", "%05d$:", (lbl->key + 100));
6046 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6053 genIfxJump (ifx, "c", left, right, result);
6056 /* if the result is used in an arithmetic operation
6057 then put the result in place */
6062 gencjne (left, right, newiTempLabel (NULL));
6063 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6065 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6070 genIfxJump (ifx, "a", left, right, result);
6073 /* if the result is used in an arithmetic operation
6074 then put the result in place */
6075 if (AOP_TYPE (result) != AOP_CRY)
6077 /* leave the result in acc */
6081 freeAsmop (result, NULL, ic, TRUE);
6084 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6085 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6089 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6090 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6094 /*-----------------------------------------------------------------*/
6095 /* ifxForOp - returns the icode containing the ifx for operand */
6096 /*-----------------------------------------------------------------*/
6098 ifxForOp (operand * op, iCode * ic)
6100 /* if true symbol then needs to be assigned */
6101 if (IS_TRUE_SYMOP (op))
6104 /* if this has register type condition and
6105 the next instruction is ifx with the same operand
6106 and live to of the operand is upto the ifx only then */
6108 ic->next->op == IFX &&
6109 IC_COND (ic->next)->key == op->key &&
6110 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6116 /*-----------------------------------------------------------------*/
6117 /* hasInc - operand is incremented before any other use */
6118 /*-----------------------------------------------------------------*/
6120 hasInc (operand *op, iCode *ic,int osize)
6122 sym_link *type = operandType(op);
6123 sym_link *retype = getSpec (type);
6124 iCode *lic = ic->next;
6127 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6128 if (!IS_SYMOP(op)) return NULL;
6130 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6131 if (IS_AGGREGATE(type->next)) return NULL;
6132 if (osize != (isize = getSize(type->next))) return NULL;
6135 /* if operand of the form op = op + <sizeof *op> */
6136 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6137 isOperandEqual(IC_RESULT(lic),op) &&
6138 isOperandLiteral(IC_RIGHT(lic)) &&
6139 operandLitValue(IC_RIGHT(lic)) == isize) {
6142 /* if the operand used or deffed */
6143 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6146 /* if GOTO or IFX */
6147 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6153 /*-----------------------------------------------------------------*/
6154 /* genAndOp - for && operation */
6155 /*-----------------------------------------------------------------*/
6157 genAndOp (iCode * ic)
6159 operand *left, *right, *result;
6162 D(emitcode ("; genAndOp",""));
6164 /* note here that && operations that are in an
6165 if statement are taken away by backPatchLabels
6166 only those used in arthmetic operations remain */
6167 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6168 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6169 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6171 /* if both are bit variables */
6172 if (AOP_TYPE (left) == AOP_CRY &&
6173 AOP_TYPE (right) == AOP_CRY)
6175 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6176 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6181 tlbl = newiTempLabel (NULL);
6183 emitcode ("jz", "%05d$", tlbl->key + 100);
6185 emitcode ("", "%05d$:", tlbl->key + 100);
6189 freeAsmop (result, NULL, ic, TRUE);
6190 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6191 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6195 /*-----------------------------------------------------------------*/
6196 /* genOrOp - for || operation */
6197 /*-----------------------------------------------------------------*/
6199 genOrOp (iCode * ic)
6201 operand *left, *right, *result;
6204 D(emitcode ("; genOrOp",""));
6206 /* note here that || operations that are in an
6207 if statement are taken away by backPatchLabels
6208 only those used in arthmetic operations remain */
6209 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6210 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6211 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6213 /* if both are bit variables */
6214 if (AOP_TYPE (left) == AOP_CRY &&
6215 AOP_TYPE (right) == AOP_CRY)
6217 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6218 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6223 tlbl = newiTempLabel (NULL);
6225 emitcode ("jnz", "%05d$", tlbl->key + 100);
6227 emitcode ("", "%05d$:", tlbl->key + 100);
6231 freeAsmop (result, NULL, ic, TRUE);
6232 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6233 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6236 /*-----------------------------------------------------------------*/
6237 /* isLiteralBit - test if lit == 2^n */
6238 /*-----------------------------------------------------------------*/
6240 isLiteralBit (unsigned long lit)
6242 unsigned long pw[32] =
6243 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6244 0x100L, 0x200L, 0x400L, 0x800L,
6245 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6246 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6247 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6248 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6249 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6252 for (idx = 0; idx < 32; idx++)
6258 /*-----------------------------------------------------------------*/
6259 /* continueIfTrue - */
6260 /*-----------------------------------------------------------------*/
6262 continueIfTrue (iCode * ic)
6265 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6269 /*-----------------------------------------------------------------*/
6271 /*-----------------------------------------------------------------*/
6273 jumpIfTrue (iCode * ic)
6276 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6280 /*-----------------------------------------------------------------*/
6281 /* jmpTrueOrFalse - */
6282 /*-----------------------------------------------------------------*/
6284 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6286 // ugly but optimized by peephole
6289 symbol *nlbl = newiTempLabel (NULL);
6290 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6291 emitcode ("", "%05d$:", tlbl->key + 100);
6292 freeForBranchAsmop (result);
6293 freeForBranchAsmop (right);
6294 freeForBranchAsmop (left);
6295 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6296 emitcode ("", "%05d$:", nlbl->key + 100);
6300 freeForBranchAsmop (result);
6301 freeForBranchAsmop (right);
6302 freeForBranchAsmop (left);
6303 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6304 emitcode ("", "%05d$:", tlbl->key + 100);
6309 /*-----------------------------------------------------------------*/
6310 /* genAnd - code for and */
6311 /*-----------------------------------------------------------------*/
6313 genAnd (iCode * ic, iCode * ifx)
6315 operand *left, *right, *result;
6316 int size, offset = 0;
6317 unsigned long lit = 0L;
6321 D(emitcode ("; genAnd",""));
6323 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6324 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6325 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6328 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6330 AOP_TYPE (left), AOP_TYPE (right));
6331 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6333 AOP_SIZE (left), AOP_SIZE (right));
6336 /* if left is a literal & right is not then exchange them */
6337 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6338 AOP_NEEDSACC (left))
6340 operand *tmp = right;
6345 /* if result = right then exchange left and right */
6346 if (sameRegs (AOP (result), AOP (right)))
6348 operand *tmp = right;
6353 /* if right is bit then exchange them */
6354 if (AOP_TYPE (right) == AOP_CRY &&
6355 AOP_TYPE (left) != AOP_CRY)
6357 operand *tmp = right;
6361 if (AOP_TYPE (right) == AOP_LIT)
6362 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6364 size = AOP_SIZE (result);
6367 // result = bit & yy;
6368 if (AOP_TYPE (left) == AOP_CRY)
6370 // c = bit & literal;
6371 if (AOP_TYPE (right) == AOP_LIT)
6375 if (size && sameRegs (AOP (result), AOP (left)))
6378 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6383 if (size && (AOP_TYPE (result) == AOP_CRY))
6385 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6388 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6393 emitcode ("clr", "c");
6398 if (AOP_TYPE (right) == AOP_CRY)
6401 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6402 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6407 MOVA (aopGet (right, 0, FALSE, FALSE));
6409 emitcode ("rrc", "a");
6410 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6418 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6419 genIfxJump (ifx, "c", left, right, result);
6423 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6424 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6425 if ((AOP_TYPE (right) == AOP_LIT) &&
6426 (AOP_TYPE (result) == AOP_CRY) &&
6427 (AOP_TYPE (left) != AOP_CRY))
6429 int posbit = isLiteralBit (lit);
6434 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6438 switch (posbit & 0x07)
6440 case 0: emitcode ("rrc", "a");
6442 case 7: emitcode ("rlc", "a");
6444 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6453 SNPRINTF (buffer, sizeof(buffer),
6454 "acc.%d", posbit & 0x07);
6455 genIfxJump (ifx, buffer, left, right, result);
6458 {// what is this case? just found it in ds390/gen.c
6459 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6466 symbol *tlbl = newiTempLabel (NULL);
6467 int sizel = AOP_SIZE (left);
6469 emitcode ("setb", "c");
6472 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6474 MOVA (aopGet (left, offset, FALSE, FALSE));
6476 if ((posbit = isLiteralBit (bytelit)) != 0)
6477 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6480 if (bytelit != 0x0FFL)
6481 emitcode ("anl", "a,%s",
6482 aopGet (right, offset, FALSE, TRUE));
6483 emitcode ("jnz", "%05d$", tlbl->key + 100);
6488 // bit = left & literal
6491 emitcode ("clr", "c");
6492 emitcode ("", "%05d$:", tlbl->key + 100);
6494 // if(left & literal)
6498 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6500 emitcode ("", "%05d$:", tlbl->key + 100);
6508 /* if left is same as result */
6509 if (sameRegs (AOP (result), AOP (left)))
6511 for (; size--; offset++)
6513 if (AOP_TYPE (right) == AOP_LIT)
6515 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6516 if (bytelit == 0x0FF)
6518 /* dummy read of volatile operand */
6519 if (isOperandVolatile (left, FALSE))
6520 MOVA (aopGet (left, offset, FALSE, FALSE));
6524 else if (bytelit == 0)
6526 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6528 else if (IS_AOP_PREG (result))
6530 MOVA (aopGet (left, offset, FALSE, TRUE));
6531 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6532 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6535 emitcode ("anl", "%s,%s",
6536 aopGet (left, offset, FALSE, TRUE),
6537 aopGet (right, offset, FALSE, FALSE));
6541 if (AOP_TYPE (left) == AOP_ACC)
6544 emitcode("mov", "a,b");
6545 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6547 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6549 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6550 MOVA (aopGet (right, offset, FALSE, FALSE));
6551 emitcode ("anl", "a,b");
6552 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6554 else if (aopGetUsesAcc (left, offset))
6556 MOVA (aopGet (left, offset, FALSE, FALSE));
6557 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6558 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6562 MOVA (aopGet (right, offset, FALSE, FALSE));
6563 if (IS_AOP_PREG (result))
6565 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6566 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6569 emitcode ("anl", "%s,a",
6570 aopGet (left, offset, FALSE, TRUE));
6577 // left & result in different registers
6578 if (AOP_TYPE (result) == AOP_CRY)
6581 // if(size), result in bit
6582 // if(!size && ifx), conditional oper: if(left & right)
6583 symbol *tlbl = newiTempLabel (NULL);
6584 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6586 emitcode ("setb", "c");
6589 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6590 && AOP_TYPE(left)==AOP_ACC)
6593 emitcode("mov", "a,b");
6594 emitcode ("anl", "a,%s",
6595 aopGet (right, offset, FALSE, FALSE));
6597 if (AOP_TYPE(left)==AOP_ACC)
6601 bool pushedB = pushB ();
6602 emitcode("mov", "b,a");
6603 MOVA (aopGet (right, offset, FALSE, FALSE));
6604 emitcode("anl", "a,b");
6609 MOVA (aopGet (right, offset, FALSE, FALSE));
6610 emitcode("anl", "a,b");
6613 MOVA (aopGet (right, offset, FALSE, FALSE));
6614 emitcode ("anl", "a,%s",
6615 aopGet (left, offset, FALSE, FALSE));
6618 emitcode ("jnz", "%05d$", tlbl->key + 100);
6624 emitcode ("", "%05d$:", tlbl->key + 100);
6628 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6630 emitcode ("", "%05d$:", tlbl->key + 100);
6634 for (; (size--); offset++)
6637 // result = left & right
6638 if (AOP_TYPE (right) == AOP_LIT)
6640 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6641 if (bytelit == 0x0FF)
6644 aopGet (left, offset, FALSE, FALSE),
6646 isOperandVolatile (result, FALSE));
6649 else if (bytelit == 0)
6651 /* dummy read of volatile operand */
6652 if (isOperandVolatile (left, FALSE))
6653 MOVA (aopGet (left, offset, FALSE, FALSE));
6654 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6657 else if (AOP_TYPE (left) == AOP_ACC)
6661 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6662 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6667 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6668 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6673 // faster than result <- left, anl result,right
6674 // and better if result is SFR
6675 if (AOP_TYPE (left) == AOP_ACC)
6678 emitcode("mov", "a,b");
6679 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6681 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6683 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6684 MOVA (aopGet (right, offset, FALSE, FALSE));
6685 emitcode ("anl", "a,b");
6687 else if (aopGetUsesAcc (left, offset))
6689 MOVA (aopGet (left, offset, FALSE, FALSE));
6690 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6694 MOVA (aopGet (right, offset, FALSE, FALSE));
6695 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6697 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6703 freeAsmop (result, NULL, ic, TRUE);
6704 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6705 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6708 /*-----------------------------------------------------------------*/
6709 /* genOr - code for or */
6710 /*-----------------------------------------------------------------*/
6712 genOr (iCode * ic, iCode * ifx)
6714 operand *left, *right, *result;
6715 int size, offset = 0;
6716 unsigned long lit = 0L;
6719 D(emitcode ("; genOr",""));
6721 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6722 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6723 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6726 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6728 AOP_TYPE (left), AOP_TYPE (right));
6729 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6731 AOP_SIZE (left), AOP_SIZE (right));
6734 /* if left is a literal & right is not then exchange them */
6735 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6736 AOP_NEEDSACC (left))
6738 operand *tmp = right;
6743 /* if result = right then exchange them */
6744 if (sameRegs (AOP (result), AOP (right)))
6746 operand *tmp = right;
6751 /* if right is bit then exchange them */
6752 if (AOP_TYPE (right) == AOP_CRY &&
6753 AOP_TYPE (left) != AOP_CRY)
6755 operand *tmp = right;
6759 if (AOP_TYPE (right) == AOP_LIT)
6760 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6762 size = AOP_SIZE (result);
6766 if (AOP_TYPE (left) == AOP_CRY)
6768 if (AOP_TYPE (right) == AOP_LIT)
6770 // c = bit | literal;
6773 // lit != 0 => result = 1
6774 if (AOP_TYPE (result) == AOP_CRY)
6777 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6779 continueIfTrue (ifx);
6782 emitcode ("setb", "c");
6786 // lit == 0 => result = left
6787 if (size && sameRegs (AOP (result), AOP (left)))
6789 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6794 if (AOP_TYPE (right) == AOP_CRY)
6797 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6798 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6803 symbol *tlbl = newiTempLabel (NULL);
6804 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6805 emitcode ("setb", "c");
6806 emitcode ("jb", "%s,%05d$",
6807 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6809 emitcode ("jnz", "%05d$", tlbl->key + 100);
6810 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6812 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6818 emitcode ("", "%05d$:", tlbl->key + 100);
6827 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6828 genIfxJump (ifx, "c", left, right, result);
6832 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6833 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6834 if ((AOP_TYPE (right) == AOP_LIT) &&
6835 (AOP_TYPE (result) == AOP_CRY) &&
6836 (AOP_TYPE (left) != AOP_CRY))
6842 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6844 continueIfTrue (ifx);
6849 // lit = 0, result = boolean(left)
6851 emitcode ("setb", "c");
6855 symbol *tlbl = newiTempLabel (NULL);
6856 emitcode ("jnz", "%05d$", tlbl->key + 100);
6858 emitcode ("", "%05d$:", tlbl->key + 100);
6862 genIfxJump (ifx, "a", left, right, result);
6870 /* if left is same as result */
6871 if (sameRegs (AOP (result), AOP (left)))
6873 for (; size--; offset++)
6875 if (AOP_TYPE (right) == AOP_LIT)
6877 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6880 /* dummy read of volatile operand */
6881 if (isOperandVolatile (left, FALSE))
6882 MOVA (aopGet (left, offset, FALSE, FALSE));
6886 else if (bytelit == 0x0FF)
6888 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6890 else if (IS_AOP_PREG (left))
6892 MOVA (aopGet (left, offset, FALSE, TRUE));
6893 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6894 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6898 emitcode ("orl", "%s,%s",
6899 aopGet (left, offset, FALSE, TRUE),
6900 aopGet (right, offset, FALSE, FALSE));
6905 if (AOP_TYPE (left) == AOP_ACC)
6908 emitcode("mov", "a,b");
6909 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6911 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6913 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6914 MOVA (aopGet (right, offset, FALSE, FALSE));
6915 emitcode ("orl", "a,b");
6916 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6918 else if (aopGetUsesAcc (left, offset))
6920 MOVA (aopGet (left, offset, FALSE, FALSE));
6921 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6922 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6926 MOVA (aopGet (right, offset, FALSE, FALSE));
6927 if (IS_AOP_PREG (left))
6929 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6930 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6934 emitcode ("orl", "%s,a",
6935 aopGet (left, offset, FALSE, TRUE));
6943 // left & result in different registers
6944 if (AOP_TYPE (result) == AOP_CRY)
6947 // if(size), result in bit
6948 // if(!size && ifx), conditional oper: if(left | right)
6949 symbol *tlbl = newiTempLabel (NULL);
6950 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6952 emitcode ("setb", "c");
6955 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6957 emitcode("mov", "a,b");
6958 emitcode ("orl", "a,%s",
6959 aopGet (right, offset, FALSE, FALSE));
6961 MOVA (aopGet (right, offset, FALSE, FALSE));
6962 emitcode ("orl", "a,%s",
6963 aopGet (left, offset, FALSE, FALSE));
6965 emitcode ("jnz", "%05d$", tlbl->key + 100);
6971 emitcode ("", "%05d$:", tlbl->key + 100);
6975 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6977 emitcode ("", "%05d$:", tlbl->key + 100);
6981 for (; (size--); offset++)
6984 // result = left | right
6985 if (AOP_TYPE (right) == AOP_LIT)
6987 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6991 aopGet (left, offset, FALSE, FALSE),
6993 isOperandVolatile (result, FALSE));
6996 else if (bytelit == 0x0FF)
6998 /* dummy read of volatile operand */
6999 if (isOperandVolatile (left, FALSE))
7000 MOVA (aopGet (left, offset, FALSE, FALSE));
7001 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
7005 // faster than result <- left, anl result,right
7006 // and better if result is SFR
7007 if (AOP_TYPE (left) == AOP_ACC)
7010 emitcode("mov", "a,b");
7011 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7013 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7015 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7016 MOVA (aopGet (right, offset, FALSE, FALSE));
7017 emitcode ("orl", "a,b");
7019 else if (aopGetUsesAcc (left, offset))
7021 MOVA (aopGet (left, offset, FALSE, FALSE));
7022 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7026 MOVA (aopGet (right, offset, FALSE, FALSE));
7027 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7029 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7035 freeAsmop (result, NULL, ic, TRUE);
7036 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7037 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7040 /*-----------------------------------------------------------------*/
7041 /* genXor - code for xclusive or */
7042 /*-----------------------------------------------------------------*/
7044 genXor (iCode * ic, iCode * ifx)
7046 operand *left, *right, *result;
7047 int size, offset = 0;
7048 unsigned long lit = 0L;
7051 D(emitcode ("; genXor",""));
7053 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7054 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7055 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7058 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7060 AOP_TYPE (left), AOP_TYPE (right));
7061 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7063 AOP_SIZE (left), AOP_SIZE (right));
7066 /* if left is a literal & right is not ||
7067 if left needs acc & right does not */
7068 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7069 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7071 operand *tmp = right;
7076 /* if result = right then exchange them */
7077 if (sameRegs (AOP (result), AOP (right)))
7079 operand *tmp = right;
7084 /* if right is bit then exchange them */
7085 if (AOP_TYPE (right) == AOP_CRY &&
7086 AOP_TYPE (left) != AOP_CRY)
7088 operand *tmp = right;
7092 if (AOP_TYPE (right) == AOP_LIT)
7093 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7095 size = AOP_SIZE (result);
7099 if (AOP_TYPE (left) == AOP_CRY)
7101 if (AOP_TYPE (right) == AOP_LIT)
7103 // c = bit & literal;
7106 // lit>>1 != 0 => result = 1
7107 if (AOP_TYPE (result) == AOP_CRY)
7110 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7112 continueIfTrue (ifx);
7115 emitcode ("setb", "c");
7122 // lit == 0, result = left
7123 if (size && sameRegs (AOP (result), AOP (left)))
7125 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7129 // lit == 1, result = not(left)
7130 if (size && sameRegs (AOP (result), AOP (left)))
7132 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7137 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7138 emitcode ("cpl", "c");
7147 symbol *tlbl = newiTempLabel (NULL);
7148 if (AOP_TYPE (right) == AOP_CRY)
7151 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7155 int sizer = AOP_SIZE (right);
7157 // if val>>1 != 0, result = 1
7158 emitcode ("setb", "c");
7161 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7163 // test the msb of the lsb
7164 emitcode ("anl", "a,#0xfe");
7165 emitcode ("jnz", "%05d$", tlbl->key + 100);
7169 emitcode ("rrc", "a");
7171 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7172 emitcode ("cpl", "c");
7173 emitcode ("", "%05d$:", (tlbl->key + 100));
7180 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7181 genIfxJump (ifx, "c", left, right, result);
7185 /* if left is same as result */
7186 if (sameRegs (AOP (result), AOP (left)))
7188 for (; size--; offset++)
7190 if (AOP_TYPE (right) == AOP_LIT)
7192 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7195 /* dummy read of volatile operand */
7196 if (isOperandVolatile (left, FALSE))
7197 MOVA (aopGet (left, offset, FALSE, FALSE));
7201 else if (IS_AOP_PREG (left))
7203 MOVA (aopGet (left, offset, FALSE, TRUE));
7204 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7205 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7209 emitcode ("xrl", "%s,%s",
7210 aopGet (left, offset, FALSE, TRUE),
7211 aopGet (right, offset, FALSE, FALSE));
7216 if (AOP_TYPE (left) == AOP_ACC)
7219 emitcode("mov", "a,b");
7220 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7222 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7224 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7225 MOVA (aopGet (right, offset, FALSE, FALSE));
7226 emitcode ("xrl", "a,b");
7227 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7229 else if (aopGetUsesAcc (left, offset))
7231 MOVA (aopGet (left, offset, FALSE, FALSE));
7232 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7233 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7237 MOVA (aopGet (right, offset, FALSE, FALSE));
7238 if (IS_AOP_PREG (left))
7240 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7241 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7244 emitcode ("xrl", "%s,a",
7245 aopGet (left, offset, FALSE, TRUE));
7252 // left & result in different registers
7253 if (AOP_TYPE (result) == AOP_CRY)
7256 // if(size), result in bit
7257 // if(!size && ifx), conditional oper: if(left ^ right)
7258 symbol *tlbl = newiTempLabel (NULL);
7259 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7261 emitcode ("setb", "c");
7264 if ((AOP_TYPE (right) == AOP_LIT) &&
7265 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7267 MOVA (aopGet (left, offset, FALSE, FALSE));
7271 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7273 emitcode("mov", "a,b");
7274 emitcode ("xrl", "a,%s",
7275 aopGet (right, offset, FALSE, FALSE));
7277 MOVA (aopGet (right, offset, FALSE, FALSE));
7278 emitcode ("xrl", "a,%s",
7279 aopGet (left, offset, FALSE, FALSE));
7282 emitcode ("jnz", "%05d$", tlbl->key + 100);
7288 emitcode ("", "%05d$:", tlbl->key + 100);
7292 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7296 for (; (size--); offset++)
7299 // result = left & right
7300 if (AOP_TYPE (right) == AOP_LIT)
7302 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7306 aopGet (left, offset, FALSE, FALSE),
7308 isOperandVolatile (result, FALSE));
7312 // faster than result <- left, anl result,right
7313 // and better if result is SFR
7314 if (AOP_TYPE (left) == AOP_ACC)
7317 emitcode("mov", "a,b");
7318 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7320 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7322 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7323 MOVA (aopGet (right, offset, FALSE, FALSE));
7324 emitcode ("xrl", "a,b");
7326 else if (aopGetUsesAcc (left, offset))
7328 MOVA (aopGet (left, offset, FALSE, FALSE));
7329 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7333 MOVA (aopGet (right, offset, FALSE, FALSE));
7334 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7336 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7342 freeAsmop (result, NULL, ic, TRUE);
7343 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7344 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7347 /*-----------------------------------------------------------------*/
7348 /* genInline - write the inline code out */
7349 /*-----------------------------------------------------------------*/
7351 genInline (iCode * ic)
7353 char *buffer, *bp, *bp1;
7355 D(emitcode ("; genInline",""));
7357 _G.inLine += (!options.asmpeep);
7359 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7360 strcpy (buffer, IC_INLINE (ic));
7362 /* emit each line as a code */
7373 /* Add \n for labels, not dirs such as c:\mydir */
7374 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7388 /* emitcode("",buffer); */
7389 _G.inLine -= (!options.asmpeep);
7392 /*-----------------------------------------------------------------*/
7393 /* genRRC - rotate right with carry */
7394 /*-----------------------------------------------------------------*/
7398 operand *left, *result;
7399 int size, offset = 0;
7402 D(emitcode ("; genRRC",""));
7404 /* rotate right with carry */
7405 left = IC_LEFT (ic);
7406 result = IC_RESULT (ic);
7407 aopOp (left, ic, FALSE);
7408 aopOp (result, ic, FALSE);
7410 /* move it to the result */
7411 size = AOP_SIZE (result);
7413 if (size == 1) { /* special case for 1 byte */
7414 l = aopGet (left, offset, FALSE, FALSE);
7416 emitcode ("rr", "a");
7419 /* no need to clear carry, bit7 will be written later */
7422 l = aopGet (left, offset, FALSE, FALSE);
7424 emitcode ("rrc", "a");
7425 if (AOP_SIZE (result) > 1)
7426 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7428 /* now we need to put the carry into the
7429 highest order byte of the result */
7430 if (AOP_SIZE (result) > 1)
7432 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7435 emitcode ("mov", "acc.7,c");
7437 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7438 freeAsmop (result, NULL, ic, TRUE);
7439 freeAsmop (left, NULL, ic, TRUE);
7442 /*-----------------------------------------------------------------*/
7443 /* genRLC - generate code for rotate left with carry */
7444 /*-----------------------------------------------------------------*/
7448 operand *left, *result;
7449 int size, offset = 0;
7452 D(emitcode ("; genRLC",""));
7454 /* rotate right with carry */
7455 left = IC_LEFT (ic);
7456 result = IC_RESULT (ic);
7457 aopOp (left, ic, FALSE);
7458 aopOp (result, ic, FALSE);
7460 /* move it to the result */
7461 size = AOP_SIZE (result);
7465 l = aopGet (left, offset, FALSE, FALSE);
7467 if (size == 0) { /* special case for 1 byte */
7471 emitcode("rlc","a"); /* bit0 will be written later */
7472 if (AOP_SIZE (result) > 1)
7473 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7476 l = aopGet (left, offset, FALSE, FALSE);
7478 emitcode ("rlc", "a");
7479 if (AOP_SIZE (result) > 1)
7480 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7483 /* now we need to put the carry into the
7484 highest order byte of the result */
7485 if (AOP_SIZE (result) > 1)
7487 l = aopGet (result, 0, FALSE, FALSE);
7490 emitcode ("mov", "acc.0,c");
7492 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7493 freeAsmop (result, NULL, ic, TRUE);
7494 freeAsmop (left, NULL, ic, TRUE);
7497 /*-----------------------------------------------------------------*/
7498 /* genGetHbit - generates code get highest order bit */
7499 /*-----------------------------------------------------------------*/
7501 genGetHbit (iCode * ic)
7503 operand *left, *result;
7505 D(emitcode ("; genGetHbit",""));
7507 left = IC_LEFT (ic);
7508 result = IC_RESULT (ic);
7509 aopOp (left, ic, FALSE);
7510 aopOp (result, ic, FALSE);
7512 /* get the highest order byte into a */
7513 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7514 if (AOP_TYPE (result) == AOP_CRY)
7516 emitcode ("rlc", "a");
7521 emitcode ("rl", "a");
7522 emitcode ("anl", "a,#0x01");
7526 freeAsmop (result, NULL, ic, TRUE);
7527 freeAsmop (left, NULL, ic, TRUE);
7530 /*-----------------------------------------------------------------*/
7531 /* genGetAbit - generates code get a single bit */
7532 /*-----------------------------------------------------------------*/
7534 genGetAbit (iCode * ic)
7536 operand *left, *right, *result;
7539 D(emitcode ("; genGetAbit",""));
7541 left = IC_LEFT (ic);
7542 right = IC_RIGHT (ic);
7543 result = IC_RESULT (ic);
7544 aopOp (left, ic, FALSE);
7545 aopOp (right, ic, FALSE);
7546 aopOp (result, ic, FALSE);
7548 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7550 /* get the needed byte into a */
7551 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7553 if (AOP_TYPE (result) == AOP_CRY)
7556 emitcode ("rlc", "a");
7557 else if ((shCount) == 0)
7558 emitcode ("rrc", "a");
7560 emitcode ("mov", "c,acc[%d]", shCount);
7568 emitcode ("rr", "a");
7571 emitcode ("rr", "a");
7574 emitcode ("anl", "a,#0x01");
7578 emitcode ("mov", "c,acc[%d]", shCount);
7579 emitcode ("clr", "a");
7580 emitcode ("rlc", "a");
7583 emitcode ("swap", "a");
7584 emitcode ("anl", "a,#0x01");
7587 emitcode ("rl", "a");
7590 emitcode ("rl", "a");
7591 emitcode ("anl", "a,#0x01");
7597 freeAsmop (result, NULL, ic, TRUE);
7598 freeAsmop (right, NULL, ic, TRUE);
7599 freeAsmop (left, NULL, ic, TRUE);
7602 /*-----------------------------------------------------------------*/
7603 /* genGetByte - generates code get a single byte */
7604 /*-----------------------------------------------------------------*/
7606 genGetByte (iCode * ic)
7608 operand *left, *right, *result;
7611 D(emitcode ("; genGetByte",""));
7613 left = IC_LEFT (ic);
7614 right = IC_RIGHT (ic);
7615 result = IC_RESULT (ic);
7616 aopOp (left, ic, FALSE);
7617 aopOp (right, ic, FALSE);
7618 aopOp (result, ic, FALSE);
7620 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7622 aopGet (left, offset, FALSE, FALSE),
7624 isOperandVolatile (result, FALSE));
7626 freeAsmop (result, NULL, ic, TRUE);
7627 freeAsmop (right, NULL, ic, TRUE);
7628 freeAsmop (left, NULL, ic, TRUE);
7631 /*-----------------------------------------------------------------*/
7632 /* genGetWord - generates code get two bytes */
7633 /*-----------------------------------------------------------------*/
7635 genGetWord (iCode * ic)
7637 operand *left, *right, *result;
7640 D(emitcode ("; genGetWord",""));
7642 left = IC_LEFT (ic);
7643 right = IC_RIGHT (ic);
7644 result = IC_RESULT (ic);
7645 aopOp (left, ic, FALSE);
7646 aopOp (right, ic, FALSE);
7647 aopOp (result, ic, FALSE);
7649 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7651 aopGet (left, offset, FALSE, FALSE),
7653 isOperandVolatile (result, FALSE));
7655 aopGet (left, offset+1, FALSE, FALSE),
7657 isOperandVolatile (result, FALSE));
7659 freeAsmop (result, NULL, ic, TRUE);
7660 freeAsmop (right, NULL, ic, TRUE);
7661 freeAsmop (left, NULL, ic, TRUE);
7664 /*-----------------------------------------------------------------*/
7665 /* genSwap - generates code to swap nibbles or bytes */
7666 /*-----------------------------------------------------------------*/
7668 genSwap (iCode * ic)
7670 operand *left, *result;
7672 D(emitcode ("; genSwap",""));
7674 left = IC_LEFT (ic);
7675 result = IC_RESULT (ic);
7676 aopOp (left, ic, FALSE);
7677 aopOp (result, ic, FALSE);
7679 switch (AOP_SIZE (left))
7681 case 1: /* swap nibbles in byte */
7682 MOVA (aopGet (left, 0, FALSE, FALSE));
7683 emitcode ("swap", "a");
7684 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7686 case 2: /* swap bytes in word */
7687 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7689 MOVA (aopGet (left, 0, FALSE, FALSE));
7690 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7691 0, isOperandVolatile (result, FALSE));
7692 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7694 else if (operandsEqu (left, result))
7697 bool pushedB = FALSE, leftInB = FALSE;
7699 MOVA (aopGet (left, 0, FALSE, FALSE));
7700 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7703 emitcode ("mov", "b,a");
7707 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7708 0, isOperandVolatile (result, FALSE));
7709 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7716 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7717 0, isOperandVolatile (result, FALSE));
7718 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7719 1, isOperandVolatile (result, FALSE));
7723 wassertl(FALSE, "unsupported SWAP operand size");
7726 freeAsmop (result, NULL, ic, TRUE);
7727 freeAsmop (left, NULL, ic, TRUE);
7731 /*-----------------------------------------------------------------*/
7732 /* AccRol - rotate left accumulator by known count */
7733 /*-----------------------------------------------------------------*/
7735 AccRol (int shCount)
7737 shCount &= 0x0007; // shCount : 0..7
7744 emitcode ("rl", "a");
7747 emitcode ("rl", "a");
7748 emitcode ("rl", "a");
7751 emitcode ("swap", "a");
7752 emitcode ("rr", "a");
7755 emitcode ("swap", "a");
7758 emitcode ("swap", "a");
7759 emitcode ("rl", "a");
7762 emitcode ("rr", "a");
7763 emitcode ("rr", "a");
7766 emitcode ("rr", "a");
7771 /*-----------------------------------------------------------------*/
7772 /* AccLsh - left shift accumulator by known count */
7773 /*-----------------------------------------------------------------*/
7775 AccLsh (int shCount)
7780 emitcode ("add", "a,acc");
7781 else if (shCount == 2)
7783 emitcode ("add", "a,acc");
7784 emitcode ("add", "a,acc");
7788 /* rotate left accumulator */
7790 /* and kill the lower order bits */
7791 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7796 /*-----------------------------------------------------------------*/
7797 /* AccRsh - right shift accumulator by known count */
7798 /*-----------------------------------------------------------------*/
7800 AccRsh (int shCount)
7807 emitcode ("rrc", "a");
7811 /* rotate right accumulator */
7812 AccRol (8 - shCount);
7813 /* and kill the higher order bits */
7814 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7819 /*-----------------------------------------------------------------*/
7820 /* AccSRsh - signed right shift accumulator by known count */
7821 /*-----------------------------------------------------------------*/
7823 AccSRsh (int shCount)
7830 emitcode ("mov", "c,acc.7");
7831 emitcode ("rrc", "a");
7833 else if (shCount == 2)
7835 emitcode ("mov", "c,acc.7");
7836 emitcode ("rrc", "a");
7837 emitcode ("mov", "c,acc.7");
7838 emitcode ("rrc", "a");
7842 tlbl = newiTempLabel (NULL);
7843 /* rotate right accumulator */
7844 AccRol (8 - shCount);
7845 /* and kill the higher order bits */
7846 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7847 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7848 emitcode ("orl", "a,#0x%02x",
7849 (unsigned char) ~SRMask[shCount]);
7850 emitcode ("", "%05d$:", tlbl->key + 100);
7855 /*-----------------------------------------------------------------*/
7856 /* shiftR1Left2Result - shift right one byte from left to result */
7857 /*-----------------------------------------------------------------*/
7859 shiftR1Left2Result (operand * left, int offl,
7860 operand * result, int offr,
7861 int shCount, int sign)
7863 MOVA (aopGet (left, offl, FALSE, FALSE));
7864 /* shift right accumulator */
7869 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7872 /*-----------------------------------------------------------------*/
7873 /* shiftL1Left2Result - shift left one byte from left to result */
7874 /*-----------------------------------------------------------------*/
7876 shiftL1Left2Result (operand * left, int offl,
7877 operand * result, int offr, int shCount)
7880 l = aopGet (left, offl, FALSE, FALSE);
7882 /* shift left accumulator */
7884 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7887 /*-----------------------------------------------------------------*/
7888 /* movLeft2Result - move byte from left to result */
7889 /*-----------------------------------------------------------------*/
7891 movLeft2Result (operand * left, int offl,
7892 operand * result, int offr, int sign)
7895 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7897 l = aopGet (left, offl, FALSE, FALSE);
7899 if (*l == '@' && (IS_AOP_PREG (result)))
7901 emitcode ("mov", "a,%s", l);
7902 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7907 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7910 /* MSB sign in acc.7 ! */
7911 if (getDataSize (left) == offl + 1)
7914 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7921 /*-----------------------------------------------------------------*/
7922 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7923 /*-----------------------------------------------------------------*/
7927 emitcode ("rrc", "a");
7928 emitcode ("xch", "a,%s", x);
7929 emitcode ("rrc", "a");
7930 emitcode ("xch", "a,%s", x);
7933 /*-----------------------------------------------------------------*/
7934 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7935 /*-----------------------------------------------------------------*/
7939 emitcode ("xch", "a,%s", x);
7940 emitcode ("rlc", "a");
7941 emitcode ("xch", "a,%s", x);
7942 emitcode ("rlc", "a");
7945 /*-----------------------------------------------------------------*/
7946 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7947 /*-----------------------------------------------------------------*/
7951 emitcode ("xch", "a,%s", x);
7952 emitcode ("add", "a,acc");
7953 emitcode ("xch", "a,%s", x);
7954 emitcode ("rlc", "a");
7957 /*-----------------------------------------------------------------*/
7958 /* AccAXLsh - left shift a:x by known count (0..7) */
7959 /*-----------------------------------------------------------------*/
7961 AccAXLsh (char *x, int shCount)
7976 case 5: // AAAAABBB:CCCCCDDD
7978 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7980 emitcode ("anl", "a,#0x%02x",
7981 SLMask[shCount]); // BBB00000:CCCCCDDD
7983 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7985 AccRol (shCount); // DDDCCCCC:BBB00000
7987 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7989 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7991 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7993 emitcode ("anl", "a,#0x%02x",
7994 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7996 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7998 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
8001 case 6: // AAAAAABB:CCCCCCDD
8002 emitcode ("anl", "a,#0x%02x",
8003 SRMask[shCount]); // 000000BB:CCCCCCDD
8004 emitcode ("mov", "c,acc.0"); // c = B
8005 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
8007 AccAXRrl1 (x); // BCCCCCCD:D000000B
8008 AccAXRrl1 (x); // BBCCCCCC:DD000000
8010 emitcode("rrc","a");
8011 emitcode("xch","a,%s", x);
8012 emitcode("rrc","a");
8013 emitcode("mov","c,acc.0"); //<< get correct bit
8014 emitcode("xch","a,%s", x);
8016 emitcode("rrc","a");
8017 emitcode("xch","a,%s", x);
8018 emitcode("rrc","a");
8019 emitcode("xch","a,%s", x);
8022 case 7: // a:x <<= 7
8024 emitcode ("anl", "a,#0x%02x",
8025 SRMask[shCount]); // 0000000B:CCCCCCCD
8027 emitcode ("mov", "c,acc.0"); // c = B
8029 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8031 AccAXRrl1 (x); // BCCCCCCC:D0000000
8039 /*-----------------------------------------------------------------*/
8040 /* AccAXRsh - right shift a:x known count (0..7) */
8041 /*-----------------------------------------------------------------*/
8043 AccAXRsh (char *x, int shCount)
8051 AccAXRrl1 (x); // 0->a:x
8056 AccAXRrl1 (x); // 0->a:x
8059 AccAXRrl1 (x); // 0->a:x
8064 case 5: // AAAAABBB:CCCCCDDD = a:x
8066 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8068 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8070 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8072 emitcode ("anl", "a,#0x%02x",
8073 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8075 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8077 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8079 emitcode ("anl", "a,#0x%02x",
8080 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8082 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8084 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8086 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8089 case 6: // AABBBBBB:CCDDDDDD
8091 emitcode ("mov", "c,acc.7");
8092 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8094 emitcode ("mov", "c,acc.7");
8095 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8097 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8099 emitcode ("anl", "a,#0x%02x",
8100 SRMask[shCount]); // 000000AA:BBBBBBCC
8103 case 7: // ABBBBBBB:CDDDDDDD
8105 emitcode ("mov", "c,acc.7"); // c = A
8107 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8109 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8111 emitcode ("anl", "a,#0x%02x",
8112 SRMask[shCount]); // 0000000A:BBBBBBBC
8120 /*-----------------------------------------------------------------*/
8121 /* AccAXRshS - right shift signed a:x known count (0..7) */
8122 /*-----------------------------------------------------------------*/
8124 AccAXRshS (char *x, int shCount)
8132 emitcode ("mov", "c,acc.7");
8133 AccAXRrl1 (x); // s->a:x
8137 emitcode ("mov", "c,acc.7");
8138 AccAXRrl1 (x); // s->a:x
8140 emitcode ("mov", "c,acc.7");
8141 AccAXRrl1 (x); // s->a:x
8146 case 5: // AAAAABBB:CCCCCDDD = a:x
8148 tlbl = newiTempLabel (NULL);
8149 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8151 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8153 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8155 emitcode ("anl", "a,#0x%02x",
8156 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8158 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8160 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8162 emitcode ("anl", "a,#0x%02x",
8163 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8165 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8167 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8169 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8171 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8172 emitcode ("orl", "a,#0x%02x",
8173 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8175 emitcode ("", "%05d$:", tlbl->key + 100);
8176 break; // SSSSAAAA:BBBCCCCC
8178 case 6: // AABBBBBB:CCDDDDDD
8180 tlbl = newiTempLabel (NULL);
8181 emitcode ("mov", "c,acc.7");
8182 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8184 emitcode ("mov", "c,acc.7");
8185 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8187 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8189 emitcode ("anl", "a,#0x%02x",
8190 SRMask[shCount]); // 000000AA:BBBBBBCC
8192 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8193 emitcode ("orl", "a,#0x%02x",
8194 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8196 emitcode ("", "%05d$:", tlbl->key + 100);
8198 case 7: // ABBBBBBB:CDDDDDDD
8200 tlbl = newiTempLabel (NULL);
8201 emitcode ("mov", "c,acc.7"); // c = A
8203 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8205 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8207 emitcode ("anl", "a,#0x%02x",
8208 SRMask[shCount]); // 0000000A:BBBBBBBC
8210 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8211 emitcode ("orl", "a,#0x%02x",
8212 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8214 emitcode ("", "%05d$:", tlbl->key + 100);
8221 /*-----------------------------------------------------------------*/
8222 /* shiftL2Left2Result - shift left two bytes from left to result */
8223 /*-----------------------------------------------------------------*/
8225 shiftL2Left2Result (operand * left, int offl,
8226 operand * result, int offr, int shCount)
8229 bool pushedB = FALSE;
8232 if (sameRegs (AOP (result), AOP (left)) &&
8233 ((offl + MSB16) == offr))
8235 /* don't crash result[offr] */
8236 MOVA (aopGet (left, offl, FALSE, FALSE));
8237 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8238 x = aopGet (result, offr, FALSE, FALSE);
8240 else if (aopGetUsesAcc (result, offr))
8242 movLeft2Result (left, offl, result, offr, 0);
8245 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8246 MOVA (aopGet (result, offr, FALSE, FALSE));
8247 emitcode ("xch", "a,b");
8252 movLeft2Result (left, offl, result, offr, 0);
8253 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8254 x = aopGet (result, offr, FALSE, FALSE);
8256 /* ax << shCount (x = lsb(result)) */
8257 AccAXLsh (x, shCount);
8260 emitcode ("xch", "a,b");
8261 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8262 aopPut (result, "b", offr + MSB16, isOperandVolatile (result, FALSE));
8267 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8272 /*-----------------------------------------------------------------*/
8273 /* shiftR2Left2Result - shift right two bytes from left to result */
8274 /*-----------------------------------------------------------------*/
8276 shiftR2Left2Result (operand * left, int offl,
8277 operand * result, int offr,
8278 int shCount, int sign)
8281 bool pushedB = FALSE;
8284 if (sameRegs (AOP (result), AOP (left)) &&
8285 ((offl + MSB16) == offr))
8287 /* don't crash result[offr] */
8288 MOVA (aopGet (left, offl, FALSE, FALSE));
8289 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8290 x = aopGet (result, offr, FALSE, FALSE);
8292 else if (aopGetUsesAcc (result, offr))
8294 movLeft2Result (left, offl, result, offr, 0);
8297 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8298 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8303 movLeft2Result (left, offl, result, offr, 0);
8304 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8305 x = aopGet (result, offr, FALSE, FALSE);
8307 /* a:x >> shCount (x = lsb(result)) */
8309 AccAXRshS (x, shCount);
8311 AccAXRsh (x, shCount);
8314 emitcode ("xch", "a,b");
8315 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8316 emitcode ("xch", "a,b");
8319 if (getDataSize (result) > 1)
8320 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8323 /*-----------------------------------------------------------------*/
8324 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8325 /*-----------------------------------------------------------------*/
8327 shiftLLeftOrResult (operand * left, int offl,
8328 operand * result, int offr, int shCount)
8330 MOVA (aopGet (left, offl, FALSE, FALSE));
8331 /* shift left accumulator */
8333 /* or with result */
8334 if (aopGetUsesAcc (result, offr))
8336 emitcode ("xch", "a,b");
8337 MOVA (aopGet (result, offr, FALSE, FALSE));
8338 emitcode ("orl", "a,b");
8342 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8344 /* back to result */
8345 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8348 /*-----------------------------------------------------------------*/
8349 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8350 /*-----------------------------------------------------------------*/
8352 shiftRLeftOrResult (operand * left, int offl,
8353 operand * result, int offr, int shCount)
8355 MOVA (aopGet (left, offl, FALSE, FALSE));
8356 /* shift right accumulator */
8358 /* or with result */
8359 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8360 /* back to result */
8361 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8364 /*-----------------------------------------------------------------*/
8365 /* genlshOne - left shift a one byte quantity by known count */
8366 /*-----------------------------------------------------------------*/
8368 genlshOne (operand * result, operand * left, int shCount)
8370 D(emitcode ("; genlshOne",""));
8372 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8375 /*-----------------------------------------------------------------*/
8376 /* genlshTwo - left shift two bytes by known amount != 0 */
8377 /*-----------------------------------------------------------------*/
8379 genlshTwo (operand * result, operand * left, int shCount)
8383 D(emitcode ("; genlshTwo",""));
8385 size = getDataSize (result);
8387 /* if shCount >= 8 */
8395 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8397 movLeft2Result (left, LSB, result, MSB16, 0);
8399 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8402 /* 1 <= shCount <= 7 */
8406 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8408 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8412 /*-----------------------------------------------------------------*/
8413 /* shiftLLong - shift left one long from left to result */
8414 /* offl = LSB or MSB16 */
8415 /*-----------------------------------------------------------------*/
8417 shiftLLong (operand * left, operand * result, int offr)
8420 int size = AOP_SIZE (result);
8422 if (size >= LSB + offr)
8424 l = aopGet (left, LSB, FALSE, FALSE);
8426 emitcode ("add", "a,acc");
8427 if (sameRegs (AOP (left), AOP (result)) &&
8428 size >= MSB16 + offr && offr != LSB)
8429 emitcode ("xch", "a,%s",
8430 aopGet (left, LSB + offr, FALSE, FALSE));
8432 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8435 if (size >= MSB16 + offr)
8437 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8439 l = aopGet (left, MSB16, FALSE, FALSE);
8442 emitcode ("rlc", "a");
8443 if (sameRegs (AOP (left), AOP (result)) &&
8444 size >= MSB24 + offr && offr != LSB)
8445 emitcode ("xch", "a,%s",
8446 aopGet (left, MSB16 + offr, FALSE, FALSE));
8448 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8451 if (size >= MSB24 + offr)
8453 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8455 l = aopGet (left, MSB24, FALSE, FALSE);
8458 emitcode ("rlc", "a");
8459 if (sameRegs (AOP (left), AOP (result)) &&
8460 size >= MSB32 + offr && offr != LSB)
8461 emitcode ("xch", "a,%s",
8462 aopGet (left, MSB24 + offr, FALSE, FALSE));
8464 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8467 if (size > MSB32 + offr)
8469 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8471 l = aopGet (left, MSB32, FALSE, FALSE);
8474 emitcode ("rlc", "a");
8475 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8478 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8481 /*-----------------------------------------------------------------*/
8482 /* genlshFour - shift four byte by a known amount != 0 */
8483 /*-----------------------------------------------------------------*/
8485 genlshFour (operand * result, operand * left, int shCount)
8489 D(emitcode ("; genlshFour",""));
8491 size = AOP_SIZE (result);
8493 /* if shifting more that 3 bytes */
8498 /* lowest order of left goes to the highest
8499 order of the destination */
8500 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8502 movLeft2Result (left, LSB, result, MSB32, 0);
8503 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8504 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8505 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8509 /* more than two bytes */
8510 else if (shCount >= 16)
8512 /* lower order two bytes goes to higher order two bytes */
8514 /* if some more remaining */
8516 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8519 movLeft2Result (left, MSB16, result, MSB32, 0);
8520 movLeft2Result (left, LSB, result, MSB24, 0);
8522 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8523 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8527 /* if more than 1 byte */
8528 else if (shCount >= 8)
8530 /* lower order three bytes goes to higher order three bytes */
8535 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8537 movLeft2Result (left, LSB, result, MSB16, 0);
8543 movLeft2Result (left, MSB24, result, MSB32, 0);
8544 movLeft2Result (left, MSB16, result, MSB24, 0);
8545 movLeft2Result (left, LSB, result, MSB16, 0);
8546 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8548 else if (shCount == 1)
8549 shiftLLong (left, result, MSB16);
8552 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8553 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8554 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8555 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8560 /* 1 <= shCount <= 7 */
8561 else if (shCount <= 2)
8563 shiftLLong (left, result, LSB);
8565 shiftLLong (result, result, LSB);
8567 /* 3 <= shCount <= 7, optimize */
8570 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8571 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8572 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8576 /*-----------------------------------------------------------------*/
8577 /* genLeftShiftLiteral - left shifting by known count */
8578 /*-----------------------------------------------------------------*/
8580 genLeftShiftLiteral (operand * left,
8585 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8588 D(emitcode ("; genLeftShiftLiteral",""));
8590 freeAsmop (right, NULL, ic, TRUE);
8592 aopOp (left, ic, FALSE);
8593 aopOp (result, ic, FALSE);
8595 size = getSize (operandType (result));
8598 emitcode ("; shift left ", "result %d, left %d", size,
8602 /* I suppose that the left size >= result size */
8607 movLeft2Result (left, size, result, size, 0);
8611 else if (shCount >= (size * 8))
8613 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8619 genlshOne (result, left, shCount);
8623 genlshTwo (result, left, shCount);
8627 genlshFour (result, left, shCount);
8630 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8631 "*** ack! mystery literal shift!\n");
8635 freeAsmop (result, NULL, ic, TRUE);
8636 freeAsmop (left, NULL, ic, TRUE);
8639 /*-----------------------------------------------------------------*/
8640 /* genLeftShift - generates code for left shifting */
8641 /*-----------------------------------------------------------------*/
8643 genLeftShift (iCode * ic)
8645 operand *left, *right, *result;
8648 symbol *tlbl, *tlbl1;
8651 D(emitcode ("; genLeftShift",""));
8653 right = IC_RIGHT (ic);
8654 left = IC_LEFT (ic);
8655 result = IC_RESULT (ic);
8657 aopOp (right, ic, FALSE);
8659 /* if the shift count is known then do it
8660 as efficiently as possible */
8661 if (AOP_TYPE (right) == AOP_LIT)
8663 genLeftShiftLiteral (left, right, result, ic);
8667 /* shift count is unknown then we have to form
8668 a loop get the loop count in B : Note: we take
8669 only the lower order byte since shifting
8670 more that 32 bits make no sense anyway, ( the
8671 largest size of an object can be only 32 bits ) */
8674 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8675 emitcode ("inc", "b");
8676 freeAsmop (right, NULL, ic, TRUE);
8677 aopOp (left, ic, FALSE);
8678 aopOp (result, ic, FALSE);
8680 /* now move the left to the result if they are not the same */
8681 if (!sameRegs (AOP (left), AOP (result)) &&
8682 AOP_SIZE (result) > 1)
8685 size = AOP_SIZE (result);
8689 l = aopGet (left, offset, FALSE, TRUE);
8690 if (*l == '@' && (IS_AOP_PREG (result)))
8693 emitcode ("mov", "a,%s", l);
8694 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8697 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8702 tlbl = newiTempLabel (NULL);
8703 size = AOP_SIZE (result);
8705 tlbl1 = newiTempLabel (NULL);
8707 /* if it is only one byte then */
8710 symbol *tlbl1 = newiTempLabel (NULL);
8712 l = aopGet (left, 0, FALSE, FALSE);
8714 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8715 emitcode ("", "%05d$:", tlbl->key + 100);
8716 emitcode ("add", "a,acc");
8717 emitcode ("", "%05d$:", tlbl1->key + 100);
8718 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8720 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8724 reAdjustPreg (AOP (result));
8726 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8727 emitcode ("", "%05d$:", tlbl->key + 100);
8728 l = aopGet (result, offset, FALSE, FALSE);
8730 emitcode ("add", "a,acc");
8731 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8734 l = aopGet (result, offset, FALSE, FALSE);
8736 emitcode ("rlc", "a");
8737 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8739 reAdjustPreg (AOP (result));
8741 emitcode ("", "%05d$:", tlbl1->key + 100);
8742 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8745 freeAsmop (result, NULL, ic, TRUE);
8746 freeAsmop (left, NULL, ic, TRUE);
8749 /*-----------------------------------------------------------------*/
8750 /* genrshOne - right shift a one byte quantity by known count */
8751 /*-----------------------------------------------------------------*/
8753 genrshOne (operand * result, operand * left,
8754 int shCount, int sign)
8756 D(emitcode ("; genrshOne",""));
8758 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8761 /*-----------------------------------------------------------------*/
8762 /* genrshTwo - right shift two bytes by known amount != 0 */
8763 /*-----------------------------------------------------------------*/
8765 genrshTwo (operand * result, operand * left,
8766 int shCount, int sign)
8768 D(emitcode ("; genrshTwo",""));
8770 /* if shCount >= 8 */
8775 shiftR1Left2Result (left, MSB16, result, LSB,
8778 movLeft2Result (left, MSB16, result, LSB, sign);
8779 addSign (result, MSB16, sign);
8782 /* 1 <= shCount <= 7 */
8784 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8787 /*-----------------------------------------------------------------*/
8788 /* shiftRLong - shift right one long from left to result */
8789 /* offl = LSB or MSB16 */
8790 /*-----------------------------------------------------------------*/
8792 shiftRLong (operand * left, int offl,
8793 operand * result, int sign)
8795 bool useSameRegs = regsInCommon (left, result);
8797 if (useSameRegs && offl>1)
8799 // we are in big trouble, but this shouldn't happen
8800 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8803 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8810 emitcode ("rlc", "a");
8811 emitcode ("subb", "a,acc");
8812 if (useSameRegs && sameReg (AOP (left), MSB32, AOP (result), MSB32))
8814 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8818 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8819 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8824 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8830 emitcode ("clr", "c");
8834 emitcode ("mov", "c,acc.7");
8837 emitcode ("rrc", "a");
8839 if (useSameRegs && offl==MSB16 &&
8840 sameReg (AOP (left), MSB24, AOP (result), MSB32-offl))
8842 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8846 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8847 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8850 emitcode ("rrc", "a");
8851 if (useSameRegs && offl==1 &&
8852 sameReg (AOP (left), MSB16, AOP (result), MSB24-offl))
8854 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8858 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8859 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8861 emitcode ("rrc", "a");
8864 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8869 sameReg (AOP (left), LSB, AOP (result), MSB16-offl))
8871 emitcode ("xch", "a,%s",aopGet (left, LSB, FALSE, FALSE));
8875 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8876 MOVA (aopGet (left, LSB, FALSE, FALSE));
8878 emitcode ("rrc", "a");
8879 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8883 /*-----------------------------------------------------------------*/
8884 /* genrshFour - shift four byte by a known amount != 0 */
8885 /*-----------------------------------------------------------------*/
8887 genrshFour (operand * result, operand * left,
8888 int shCount, int sign)
8890 D(emitcode ("; genrshFour",""));
8892 /* if shifting more that 3 bytes */
8897 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8899 movLeft2Result (left, MSB32, result, LSB, sign);
8900 addSign (result, MSB16, sign);
8902 else if (shCount >= 16)
8906 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8909 movLeft2Result (left, MSB24, result, LSB, 0);
8910 movLeft2Result (left, MSB32, result, MSB16, sign);
8912 addSign (result, MSB24, sign);
8914 else if (shCount >= 8)
8918 shiftRLong (left, MSB16, result, sign);
8919 else if (shCount == 0)
8921 movLeft2Result (left, MSB16, result, LSB, 0);
8922 movLeft2Result (left, MSB24, result, MSB16, 0);
8923 movLeft2Result (left, MSB32, result, MSB24, sign);
8924 addSign (result, MSB32, sign);
8928 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8929 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8930 /* the last shift is signed */
8931 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8932 addSign (result, MSB32, sign);
8936 { /* 1 <= shCount <= 7 */
8939 shiftRLong (left, LSB, result, sign);
8941 shiftRLong (result, LSB, result, sign);
8945 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8946 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8947 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8952 /*-----------------------------------------------------------------*/
8953 /* genRightShiftLiteral - right shifting by known count */
8954 /*-----------------------------------------------------------------*/
8956 genRightShiftLiteral (operand * left,
8962 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8965 D(emitcode ("; genRightShiftLiteral",""));
8967 freeAsmop (right, NULL, ic, TRUE);
8969 aopOp (left, ic, FALSE);
8970 aopOp (result, ic, FALSE);
8973 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8977 size = getDataSize (left);
8978 /* test the LEFT size !!! */
8980 /* I suppose that the left size >= result size */
8983 size = getDataSize (result);
8985 movLeft2Result (left, size, result, size, 0);
8988 else if (shCount >= (size * 8))
8991 /* get sign in acc.7 */
8992 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8994 addSign (result, LSB, sign);
9001 genrshOne (result, left, shCount, sign);
9005 genrshTwo (result, left, shCount, sign);
9009 genrshFour (result, left, shCount, sign);
9015 freeAsmop (result, NULL, ic, TRUE);
9016 freeAsmop (left, NULL, ic, TRUE);
9019 /*-----------------------------------------------------------------*/
9020 /* genSignedRightShift - right shift of signed number */
9021 /*-----------------------------------------------------------------*/
9023 genSignedRightShift (iCode * ic)
9025 operand *right, *left, *result;
9028 symbol *tlbl, *tlbl1;
9031 D(emitcode ("; genSignedRightShift",""));
9033 /* we do it the hard way put the shift count in b
9034 and loop thru preserving the sign */
9036 right = IC_RIGHT (ic);
9037 left = IC_LEFT (ic);
9038 result = IC_RESULT (ic);
9040 aopOp (right, ic, FALSE);
9043 if (AOP_TYPE (right) == AOP_LIT)
9045 genRightShiftLiteral (left, right, result, ic, 1);
9048 /* shift count is unknown then we have to form
9049 a loop get the loop count in B : Note: we take
9050 only the lower order byte since shifting
9051 more that 32 bits make no sense anyway, ( the
9052 largest size of an object can be only 32 bits ) */
9055 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9056 emitcode ("inc", "b");
9057 freeAsmop (right, NULL, ic, TRUE);
9058 aopOp (left, ic, FALSE);
9059 aopOp (result, ic, FALSE);
9061 /* now move the left to the result if they are not the
9063 if (!sameRegs (AOP (left), AOP (result)) &&
9064 AOP_SIZE (result) > 1)
9067 size = AOP_SIZE (result);
9071 l = aopGet (left, offset, FALSE, TRUE);
9072 if (*l == '@' && IS_AOP_PREG (result))
9075 emitcode ("mov", "a,%s", l);
9076 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9079 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9084 /* mov the highest order bit to OVR */
9085 tlbl = newiTempLabel (NULL);
9086 tlbl1 = newiTempLabel (NULL);
9088 size = AOP_SIZE (result);
9090 MOVA (aopGet (left, offset, FALSE, FALSE));
9091 emitcode ("rlc", "a");
9092 emitcode ("mov", "ov,c");
9093 /* if it is only one byte then */
9096 l = aopGet (left, 0, FALSE, FALSE);
9098 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9099 emitcode ("", "%05d$:", tlbl->key + 100);
9100 emitcode ("mov", "c,ov");
9101 emitcode ("rrc", "a");
9102 emitcode ("", "%05d$:", tlbl1->key + 100);
9103 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9105 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9109 reAdjustPreg (AOP (result));
9110 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9111 emitcode ("", "%05d$:", tlbl->key + 100);
9112 emitcode ("mov", "c,ov");
9115 l = aopGet (result, offset, FALSE, FALSE);
9117 emitcode ("rrc", "a");
9118 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9120 reAdjustPreg (AOP (result));
9121 emitcode ("", "%05d$:", tlbl1->key + 100);
9122 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9126 freeAsmop (result, NULL, ic, TRUE);
9127 freeAsmop (left, NULL, ic, TRUE);
9130 /*-----------------------------------------------------------------*/
9131 /* genRightShift - generate code for right shifting */
9132 /*-----------------------------------------------------------------*/
9134 genRightShift (iCode * ic)
9136 operand *right, *left, *result;
9140 symbol *tlbl, *tlbl1;
9143 D(emitcode ("; genRightShift",""));
9145 /* if signed then we do it the hard way preserve the
9146 sign bit moving it inwards */
9147 letype = getSpec (operandType (IC_LEFT (ic)));
9149 if (!SPEC_USIGN (letype))
9151 genSignedRightShift (ic);
9155 /* signed & unsigned types are treated the same : i.e. the
9156 signed is NOT propagated inwards : quoting from the
9157 ANSI - standard : "for E1 >> E2, is equivalent to division
9158 by 2**E2 if unsigned or if it has a non-negative value,
9159 otherwise the result is implementation defined ", MY definition
9160 is that the sign does not get propagated */
9162 right = IC_RIGHT (ic);
9163 left = IC_LEFT (ic);
9164 result = IC_RESULT (ic);
9166 aopOp (right, ic, FALSE);
9168 /* if the shift count is known then do it
9169 as efficiently as possible */
9170 if (AOP_TYPE (right) == AOP_LIT)
9172 genRightShiftLiteral (left, right, result, ic, 0);
9176 /* shift count is unknown then we have to form
9177 a loop get the loop count in B : Note: we take
9178 only the lower order byte since shifting
9179 more that 32 bits make no sense anyway, ( the
9180 largest size of an object can be only 32 bits ) */
9183 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9184 emitcode ("inc", "b");
9185 freeAsmop (right, NULL, ic, TRUE);
9186 aopOp (left, ic, FALSE);
9187 aopOp (result, ic, FALSE);
9189 /* now move the left to the result if they are not the
9191 if (!sameRegs (AOP (left), AOP (result)) &&
9192 AOP_SIZE (result) > 1)
9195 size = AOP_SIZE (result);
9199 l = aopGet (left, offset, FALSE, TRUE);
9200 if (*l == '@' && IS_AOP_PREG (result))
9203 emitcode ("mov", "a,%s", l);
9204 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9207 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9212 tlbl = newiTempLabel (NULL);
9213 tlbl1 = newiTempLabel (NULL);
9214 size = AOP_SIZE (result);
9217 /* if it is only one byte then */
9220 l = aopGet (left, 0, FALSE, FALSE);
9222 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9223 emitcode ("", "%05d$:", tlbl->key + 100);
9225 emitcode ("rrc", "a");
9226 emitcode ("", "%05d$:", tlbl1->key + 100);
9227 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9229 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9233 reAdjustPreg (AOP (result));
9234 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9235 emitcode ("", "%05d$:", tlbl->key + 100);
9239 l = aopGet (result, offset, FALSE, FALSE);
9241 emitcode ("rrc", "a");
9242 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9244 reAdjustPreg (AOP (result));
9246 emitcode ("", "%05d$:", tlbl1->key + 100);
9247 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9251 freeAsmop (result, NULL, ic, TRUE);
9252 freeAsmop (left, NULL, ic, TRUE);
9255 /*-----------------------------------------------------------------*/
9256 /* emitPtrByteGet - emits code to get a byte into A through a */
9257 /* pointer register (R0, R1, or DPTR). The */
9258 /* original value of A can be preserved in B. */
9259 /*-----------------------------------------------------------------*/
9261 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9268 emitcode ("mov", "b,a");
9269 emitcode ("mov", "a,@%s", rname);
9274 emitcode ("mov", "b,a");
9275 emitcode ("movx", "a,@%s", rname);
9280 emitcode ("mov", "b,a");
9281 emitcode ("movx", "a,@dptr");
9286 emitcode ("mov", "b,a");
9287 emitcode ("clr", "a");
9288 emitcode ("movc", "a,@a+dptr");
9294 emitcode ("push", "b");
9295 emitcode ("push", "acc");
9297 emitcode ("lcall", "__gptrget");
9299 emitcode ("pop", "b");
9304 /*-----------------------------------------------------------------*/
9305 /* emitPtrByteSet - emits code to set a byte from src through a */
9306 /* pointer register (R0, R1, or DPTR). */
9307 /*-----------------------------------------------------------------*/
9309 emitPtrByteSet (char *rname, int p_type, char *src)
9318 emitcode ("mov", "@%s,a", rname);
9321 emitcode ("mov", "@%s,%s", rname, src);
9326 emitcode ("movx", "@%s,a", rname);
9331 emitcode ("movx", "@dptr,a");
9336 emitcode ("lcall", "__gptrput");
9341 /*-----------------------------------------------------------------*/
9342 /* genUnpackBits - generates code for unpacking bits */
9343 /*-----------------------------------------------------------------*/
9345 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9347 int offset = 0; /* result byte offset */
9348 int rsize; /* result size */
9349 int rlen = 0; /* remaining bitfield length */
9350 sym_link *etype; /* bitfield type information */
9351 int blen; /* bitfield length */
9352 int bstr; /* bitfield starting bit within byte */
9355 D(emitcode ("; genUnpackBits",""));
9357 etype = getSpec (operandType (result));
9358 rsize = getSize (operandType (result));
9359 blen = SPEC_BLEN (etype);
9360 bstr = SPEC_BSTR (etype);
9362 if (ifx && blen <= 8)
9364 emitPtrByteGet (rname, ptype, FALSE);
9367 SNPRINTF (buffer, sizeof(buffer),
9369 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9374 emitcode ("anl", "a,#0x%02x",
9375 (((unsigned char) -1) >> (8 - blen)) << bstr);
9376 genIfxJump (ifx, "a", NULL, NULL, NULL);
9382 /* If the bitfield length is less than a byte */
9385 emitPtrByteGet (rname, ptype, FALSE);
9387 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9388 if (!SPEC_USIGN (etype))
9390 /* signed bitfield */
9391 symbol *tlbl = newiTempLabel (NULL);
9393 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9394 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9395 emitcode ("", "%05d$:", tlbl->key + 100);
9397 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9401 /* Bit field did not fit in a byte. Copy all
9402 but the partial byte at the end. */
9403 for (rlen=blen;rlen>=8;rlen-=8)
9405 emitPtrByteGet (rname, ptype, FALSE);
9406 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9408 emitcode ("inc", "%s", rname);
9411 /* Handle the partial byte at the end */
9414 emitPtrByteGet (rname, ptype, FALSE);
9415 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9416 if (!SPEC_USIGN (etype))
9418 /* signed bitfield */
9419 symbol *tlbl = newiTempLabel (NULL);
9421 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9422 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9423 emitcode ("", "%05d$:", tlbl->key + 100);
9425 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9433 if (SPEC_USIGN (etype))
9437 /* signed bitfield: sign extension with 0x00 or 0xff */
9438 emitcode ("rlc", "a");
9439 emitcode ("subb", "a,acc");
9445 aopPut (result, source, offset++, isOperandVolatile (result, FALSE));
9450 /*-----------------------------------------------------------------*/
9451 /* genDataPointerGet - generates code when ptr offset is known */
9452 /*-----------------------------------------------------------------*/
9454 genDataPointerGet (operand * left,
9460 int size, offset = 0;
9462 D(emitcode ("; genDataPointerGet",""));
9464 aopOp (result, ic, TRUE);
9466 /* get the string representation of the name */
9467 l = aopGet (left, 0, FALSE, TRUE);
9468 size = AOP_SIZE (result);
9472 sprintf (buffer, "(%s + %d)", l + 1, offset);
9474 sprintf (buffer, "%s", l + 1);
9475 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9478 freeAsmop (result, NULL, ic, TRUE);
9479 freeAsmop (left, NULL, ic, TRUE);
9482 /*-----------------------------------------------------------------*/
9483 /* genNearPointerGet - emitcode for near pointer fetch */
9484 /*-----------------------------------------------------------------*/
9486 genNearPointerGet (operand * left,
9495 sym_link *rtype, *retype;
9496 sym_link *ltype = operandType (left);
9499 D(emitcode ("; genNearPointerGet",""));
9501 rtype = operandType (result);
9502 retype = getSpec (rtype);
9504 aopOp (left, ic, FALSE);
9506 /* if left is rematerialisable and
9507 result is not bitfield variable type and
9508 the left is pointer to data space i.e
9509 lower 128 bytes of space */
9510 if (AOP_TYPE (left) == AOP_IMMD &&
9511 !IS_BITFIELD (retype) &&
9512 DCL_TYPE (ltype) == POINTER)
9514 genDataPointerGet (left, result, ic);
9518 /* if the value is already in a pointer register
9519 then don't need anything more */
9520 if (!AOP_INPREG (AOP (left)))
9522 if (IS_AOP_PREG (left))
9524 // Aha, it is a pointer, just in disguise.
9525 rname = aopGet (left, 0, FALSE, FALSE);
9528 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9529 __FILE__, __LINE__);
9534 emitcode ("mov", "a%s,%s", rname + 1, rname);
9535 rname++; // skip the '@'.
9540 /* otherwise get a free pointer register */
9542 preg = getFreePtr (ic, &aop, FALSE);
9543 emitcode ("mov", "%s,%s",
9545 aopGet (left, 0, FALSE, TRUE));
9550 rname = aopGet (left, 0, FALSE, FALSE);
9552 //aopOp (result, ic, FALSE);
9553 aopOp (result, ic, result?TRUE:FALSE);
9555 /* if bitfield then unpack the bits */
9556 if (IS_BITFIELD (retype))
9557 genUnpackBits (result, rname, POINTER, ifx);
9560 /* we have can just get the values */
9561 int size = AOP_SIZE (result);
9566 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9569 emitcode ("mov", "a,@%s", rname);
9571 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9575 sprintf (buffer, "@%s", rname);
9576 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9580 emitcode ("inc", "%s", rname);
9584 /* now some housekeeping stuff */
9585 if (aop) /* we had to allocate for this iCode */
9587 if (pi) { /* post increment present */
9588 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9590 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9594 /* we did not allocate which means left
9595 already in a pointer register, then
9596 if size > 0 && this could be used again
9597 we have to point it back to where it
9599 if ((AOP_SIZE (result) > 1 &&
9600 !OP_SYMBOL (left)->remat &&
9601 (OP_SYMBOL (left)->liveTo > ic->seq ||
9605 int size = AOP_SIZE (result) - 1;
9607 emitcode ("dec", "%s", rname);
9611 if (ifx && !ifx->generated)
9613 genIfxJump (ifx, "a", left, NULL, result);
9617 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9618 freeAsmop (left, NULL, ic, TRUE);
9619 if (pi) pi->generated = 1;
9622 /*-----------------------------------------------------------------*/
9623 /* genPagedPointerGet - emitcode for paged pointer fetch */
9624 /*-----------------------------------------------------------------*/
9626 genPagedPointerGet (operand * left,
9635 sym_link *rtype, *retype;
9637 D(emitcode ("; genPagedPointerGet",""));
9639 rtype = operandType (result);
9640 retype = getSpec (rtype);
9642 aopOp (left, ic, FALSE);
9644 /* if the value is already in a pointer register
9645 then don't need anything more */
9646 if (!AOP_INPREG (AOP (left)))
9648 /* otherwise get a free pointer register */
9650 preg = getFreePtr (ic, &aop, FALSE);
9651 emitcode ("mov", "%s,%s",
9653 aopGet (left, 0, FALSE, TRUE));
9657 rname = aopGet (left, 0, FALSE, FALSE);
9659 aopOp (result, ic, FALSE);
9661 /* if bitfield then unpack the bits */
9662 if (IS_BITFIELD (retype))
9663 genUnpackBits (result, rname, PPOINTER, ifx);
9666 /* we have can just get the values */
9667 int size = AOP_SIZE (result);
9673 emitcode ("movx", "a,@%s", rname);
9675 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9680 emitcode ("inc", "%s", rname);
9684 /* now some housekeeping stuff */
9685 if (aop) /* we had to allocate for this iCode */
9687 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9688 freeAsmop (NULL, aop, ic, TRUE);
9692 /* we did not allocate which means left
9693 already in a pointer register, then
9694 if size > 0 && this could be used again
9695 we have to point it back to where it
9697 if ((AOP_SIZE (result) > 1 &&
9698 !OP_SYMBOL (left)->remat &&
9699 (OP_SYMBOL (left)->liveTo > ic->seq ||
9703 int size = AOP_SIZE (result) - 1;
9705 emitcode ("dec", "%s", rname);
9709 if (ifx && !ifx->generated)
9711 genIfxJump (ifx, "a", left, NULL, result);
9715 freeAsmop (result, NULL, ic, TRUE);
9716 freeAsmop (left, NULL, ic, TRUE);
9717 if (pi) pi->generated = 1;
9720 /*--------------------------------------------------------------------*/
9721 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9722 /*--------------------------------------------------------------------*/
9724 loadDptrFromOperand (operand *op, bool loadBToo)
9726 if (AOP_TYPE (op) != AOP_STR)
9728 /* if this is rematerializable */
9729 if (AOP_TYPE (op) == AOP_IMMD)
9731 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9734 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9735 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9738 wassertl(FALSE, "need pointerCode");
9739 emitcode ("", "; mov b,???");
9740 /* genPointerGet and genPointerSet originally did different
9741 ** things for this case. Both seem wrong.
9742 ** from genPointerGet:
9743 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9744 ** from genPointerSet:
9745 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9750 else if (AOP_TYPE (op) == AOP_DPTR)
9754 MOVA (aopGet (op, 0, FALSE, FALSE));
9755 emitcode ("push", "acc");
9756 MOVA (aopGet (op, 1, FALSE, FALSE));
9757 emitcode ("push", "acc");
9758 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9759 emitcode ("pop", "dph");
9760 emitcode ("pop", "dpl");
9764 MOVA (aopGet (op, 0, FALSE, FALSE));
9765 emitcode ("push", "acc");
9766 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9767 emitcode ("pop", "dpl");
9771 { /* we need to get it byte by byte */
9772 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9773 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9775 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9780 /*-----------------------------------------------------------------*/
9781 /* genFarPointerGet - gget value from far space */
9782 /*-----------------------------------------------------------------*/
9784 genFarPointerGet (operand * left,
9785 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9788 sym_link *retype = getSpec (operandType (result));
9790 D(emitcode ("; genFarPointerGet",""));
9792 aopOp (left, ic, FALSE);
9793 loadDptrFromOperand (left, FALSE);
9795 /* so dptr now contains the address */
9796 aopOp (result, ic, FALSE);
9798 /* if bit then unpack */
9799 if (IS_BITFIELD (retype))
9800 genUnpackBits (result, "dptr", FPOINTER, ifx);
9803 size = AOP_SIZE (result);
9808 emitcode ("movx", "a,@dptr");
9810 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9812 emitcode ("inc", "dptr");
9816 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9818 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9819 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9823 if (ifx && !ifx->generated)
9825 genIfxJump (ifx, "a", left, NULL, result);
9828 freeAsmop (result, NULL, ic, TRUE);
9829 freeAsmop (left, NULL, ic, TRUE);
9832 /*-----------------------------------------------------------------*/
9833 /* genCodePointerGet - gget value from code space */
9834 /*-----------------------------------------------------------------*/
9836 genCodePointerGet (operand * left,
9837 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9840 sym_link *retype = getSpec (operandType (result));
9842 D(emitcode ("; genCodePointerGet",""));
9844 aopOp (left, ic, FALSE);
9845 loadDptrFromOperand (left, FALSE);
9847 /* so dptr now contains the address */
9848 aopOp (result, ic, FALSE);
9850 /* if bit then unpack */
9851 if (IS_BITFIELD (retype))
9852 genUnpackBits (result, "dptr", CPOINTER, ifx);
9855 size = AOP_SIZE (result);
9862 emitcode ("clr", "a");
9863 emitcode ("movc", "a,@a+dptr");
9865 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9866 emitcode ("inc", "dptr");
9870 emitcode ("mov", "a,#0x%02x", offset);
9871 emitcode ("movc", "a,@a+dptr");
9873 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9878 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9880 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9881 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9885 if (ifx && !ifx->generated)
9887 genIfxJump (ifx, "a", left, NULL, result);
9890 freeAsmop (result, NULL, ic, TRUE);
9891 freeAsmop (left, NULL, ic, TRUE);
9894 /*-----------------------------------------------------------------*/
9895 /* genGenPointerGet - gget value from generic pointer space */
9896 /*-----------------------------------------------------------------*/
9898 genGenPointerGet (operand * left,
9899 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9902 sym_link *retype = getSpec (operandType (result));
9904 D(emitcode ("; genGenPointerGet",""));
9906 aopOp (left, ic, FALSE);
9907 loadDptrFromOperand (left, TRUE);
9909 /* so dptr know contains the address */
9910 aopOp (result, ic, FALSE);
9912 /* if bit then unpack */
9913 if (IS_BITFIELD (retype))
9914 genUnpackBits (result, "dptr", GPOINTER, ifx);
9917 size = AOP_SIZE (result);
9922 emitcode ("lcall", "__gptrget");
9924 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9926 emitcode ("inc", "dptr");
9930 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9932 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9933 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9937 if (ifx && !ifx->generated)
9939 genIfxJump (ifx, "a", left, NULL, result);
9942 freeAsmop (result, NULL, ic, TRUE);
9943 freeAsmop (left, NULL, ic, TRUE);
9946 /*-----------------------------------------------------------------*/
9947 /* genPointerGet - generate code for pointer get */
9948 /*-----------------------------------------------------------------*/
9950 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9952 operand *left, *result;
9953 sym_link *type, *etype;
9956 D(emitcode ("; genPointerGet",""));
9958 left = IC_LEFT (ic);
9959 result = IC_RESULT (ic);
9961 if (getSize (operandType (result))>1)
9964 /* depending on the type of pointer we need to
9965 move it to the correct pointer register */
9966 type = operandType (left);
9967 etype = getSpec (type);
9968 /* if left is of type of pointer then it is simple */
9969 if (IS_PTR (type) && !IS_FUNC (type->next))
9970 p_type = DCL_TYPE (type);
9973 /* we have to go by the storage class */
9974 p_type = PTR_TYPE (SPEC_OCLS (etype));
9977 /* special case when cast remat */
9978 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9979 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9980 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9981 type = operandType (left);
9982 p_type = DCL_TYPE (type);
9984 /* now that we have the pointer type we assign
9985 the pointer values */
9991 genNearPointerGet (left, result, ic, pi, ifx);
9995 genPagedPointerGet (left, result, ic, pi, ifx);
9999 genFarPointerGet (left, result, ic, pi, ifx);
10003 genCodePointerGet (left, result, ic, pi, ifx);
10007 genGenPointerGet (left, result, ic, pi, ifx);
10015 /*-----------------------------------------------------------------*/
10016 /* genPackBits - generates code for packed bit storage */
10017 /*-----------------------------------------------------------------*/
10019 genPackBits (sym_link * etype,
10021 char *rname, int p_type)
10023 int offset = 0; /* source byte offset */
10024 int rlen = 0; /* remaining bitfield length */
10025 int blen; /* bitfield length */
10026 int bstr; /* bitfield starting bit within byte */
10027 int litval; /* source literal value (if AOP_LIT) */
10028 unsigned char mask; /* bitmask within current byte */
10030 D(emitcode ("; genPackBits",""));
10032 blen = SPEC_BLEN (etype);
10033 bstr = SPEC_BSTR (etype);
10035 /* If the bitfield length is less than a byte */
10038 mask = ((unsigned char) (0xFF << (blen + bstr)) |
10039 (unsigned char) (0xFF >> (8 - bstr)));
10041 if (AOP_TYPE (right) == AOP_LIT)
10043 /* Case with a bitfield length <8 and literal source
10045 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10047 litval &= (~mask) & 0xff;
10048 emitPtrByteGet (rname, p_type, FALSE);
10049 if ((mask|litval)!=0xff)
10050 emitcode ("anl","a,#0x%02x", mask);
10052 emitcode ("orl","a,#0x%02x", litval);
10056 if ((blen==1) && (p_type!=GPOINTER))
10058 /* Case with a bitfield length == 1 and no generic pointer
10060 if (AOP_TYPE (right) == AOP_CRY)
10061 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10064 MOVA (aopGet (right, 0, FALSE, FALSE));
10065 emitcode ("rrc","a");
10067 emitPtrByteGet (rname, p_type, FALSE);
10068 emitcode ("mov","acc.%d,c",bstr);
10073 /* Case with a bitfield length < 8 and arbitrary source
10075 MOVA (aopGet (right, 0, FALSE, FALSE));
10076 /* shift and mask source value */
10078 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10080 pushedB = pushB ();
10081 /* transfer A to B and get next byte */
10082 emitPtrByteGet (rname, p_type, TRUE);
10084 emitcode ("anl", "a,#0x%02x", mask);
10085 emitcode ("orl", "a,b");
10086 if (p_type == GPOINTER)
10087 emitcode ("pop", "b");
10093 emitPtrByteSet (rname, p_type, "a");
10097 /* Bit length is greater than 7 bits. In this case, copy */
10098 /* all except the partial byte at the end */
10099 for (rlen=blen;rlen>=8;rlen-=8)
10101 emitPtrByteSet (rname, p_type,
10102 aopGet (right, offset++, FALSE, TRUE) );
10104 emitcode ("inc", "%s", rname);
10107 /* If there was a partial byte at the end */
10110 mask = (((unsigned char) -1 << rlen) & 0xff);
10112 if (AOP_TYPE (right) == AOP_LIT)
10114 /* Case with partial byte and literal source
10116 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10117 litval >>= (blen-rlen);
10118 litval &= (~mask) & 0xff;
10119 emitPtrByteGet (rname, p_type, FALSE);
10120 if ((mask|litval)!=0xff)
10121 emitcode ("anl","a,#0x%02x", mask);
10123 emitcode ("orl","a,#0x%02x", litval);
10128 /* Case with partial byte and arbitrary source
10130 MOVA (aopGet (right, offset++, FALSE, FALSE));
10131 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10133 pushedB = pushB ();
10134 /* transfer A to B and get next byte */
10135 emitPtrByteGet (rname, p_type, TRUE);
10137 emitcode ("anl", "a,#0x%02x", mask);
10138 emitcode ("orl", "a,b");
10139 if (p_type == GPOINTER)
10140 emitcode ("pop", "b");
10144 emitPtrByteSet (rname, p_type, "a");
10150 /*-----------------------------------------------------------------*/
10151 /* genDataPointerSet - remat pointer to data space */
10152 /*-----------------------------------------------------------------*/
10154 genDataPointerSet (operand * right,
10158 int size, offset = 0;
10159 char *l, buffer[256];
10161 D(emitcode ("; genDataPointerSet",""));
10163 aopOp (right, ic, FALSE);
10165 l = aopGet (result, 0, FALSE, TRUE);
10166 size = AOP_SIZE (right);
10170 sprintf (buffer, "(%s + %d)", l + 1, offset);
10172 sprintf (buffer, "%s", l + 1);
10173 emitcode ("mov", "%s,%s", buffer,
10174 aopGet (right, offset++, FALSE, FALSE));
10177 freeAsmop (result, NULL, ic, TRUE);
10178 freeAsmop (right, NULL, ic, TRUE);
10181 /*-----------------------------------------------------------------*/
10182 /* genNearPointerSet - emitcode for near pointer put */
10183 /*-----------------------------------------------------------------*/
10185 genNearPointerSet (operand * right,
10193 sym_link *retype, *letype;
10194 sym_link *ptype = operandType (result);
10196 D(emitcode ("; genNearPointerSet",""));
10198 retype = getSpec (operandType (right));
10199 letype = getSpec (ptype);
10200 aopOp (result, ic, FALSE);
10202 /* if the result is rematerializable &
10203 in data space & not a bit variable */
10204 if (AOP_TYPE (result) == AOP_IMMD &&
10205 DCL_TYPE (ptype) == POINTER &&
10206 !IS_BITVAR (retype) &&
10207 !IS_BITVAR (letype))
10209 genDataPointerSet (right, result, ic);
10213 /* if the value is already in a pointer register
10214 then don't need anything more */
10215 if (!AOP_INPREG (AOP (result)))
10218 //AOP_TYPE (result) == AOP_STK
10219 IS_AOP_PREG(result)
10222 // Aha, it is a pointer, just in disguise.
10223 rname = aopGet (result, 0, FALSE, FALSE);
10226 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10227 __FILE__, __LINE__);
10232 emitcode ("mov", "a%s,%s", rname + 1, rname);
10233 rname++; // skip the '@'.
10238 /* otherwise get a free pointer register */
10239 aop = newAsmop (0);
10240 preg = getFreePtr (ic, &aop, FALSE);
10241 emitcode ("mov", "%s,%s",
10243 aopGet (result, 0, FALSE, TRUE));
10244 rname = preg->name;
10249 rname = aopGet (result, 0, FALSE, FALSE);
10252 aopOp (right, ic, FALSE);
10254 /* if bitfield then unpack the bits */
10255 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10256 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10259 /* we have can just get the values */
10260 int size = AOP_SIZE (right);
10265 l = aopGet (right, offset, FALSE, TRUE);
10269 emitcode ("mov", "@%s,a", rname);
10272 emitcode ("mov", "@%s,%s", rname, l);
10274 emitcode ("inc", "%s", rname);
10279 /* now some housekeeping stuff */
10280 if (aop) /* we had to allocate for this iCode */
10283 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10284 freeAsmop (NULL, aop, ic, TRUE);
10288 /* we did not allocate which means left
10289 already in a pointer register, then
10290 if size > 0 && this could be used again
10291 we have to point it back to where it
10293 if ((AOP_SIZE (right) > 1 &&
10294 !OP_SYMBOL (result)->remat &&
10295 (OP_SYMBOL (result)->liveTo > ic->seq ||
10299 int size = AOP_SIZE (right) - 1;
10301 emitcode ("dec", "%s", rname);
10306 if (pi) pi->generated = 1;
10307 freeAsmop (result, NULL, ic, TRUE);
10308 freeAsmop (right, NULL, ic, TRUE);
10311 /*-----------------------------------------------------------------*/
10312 /* genPagedPointerSet - emitcode for Paged pointer put */
10313 /*-----------------------------------------------------------------*/
10315 genPagedPointerSet (operand * right,
10323 sym_link *retype, *letype;
10325 D(emitcode ("; genPagedPointerSet",""));
10327 retype = getSpec (operandType (right));
10328 letype = getSpec (operandType (result));
10330 aopOp (result, ic, FALSE);
10332 /* if the value is already in a pointer register
10333 then don't need anything more */
10334 if (!AOP_INPREG (AOP (result)))
10336 /* otherwise get a free pointer register */
10337 aop = newAsmop (0);
10338 preg = getFreePtr (ic, &aop, FALSE);
10339 emitcode ("mov", "%s,%s",
10341 aopGet (result, 0, FALSE, TRUE));
10342 rname = preg->name;
10345 rname = aopGet (result, 0, FALSE, FALSE);
10347 aopOp (right, ic, FALSE);
10349 /* if bitfield then unpack the bits */
10350 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10351 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10354 /* we have can just get the values */
10355 int size = AOP_SIZE (right);
10360 l = aopGet (right, offset, FALSE, TRUE);
10363 emitcode ("movx", "@%s,a", rname);
10366 emitcode ("inc", "%s", rname);
10372 /* now some housekeeping stuff */
10373 if (aop) /* we had to allocate for this iCode */
10376 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10377 freeAsmop (NULL, aop, ic, TRUE);
10381 /* we did not allocate which means left
10382 already in a pointer register, then
10383 if size > 0 && this could be used again
10384 we have to point it back to where it
10386 if (AOP_SIZE (right) > 1 &&
10387 !OP_SYMBOL (result)->remat &&
10388 (OP_SYMBOL (result)->liveTo > ic->seq ||
10391 int size = AOP_SIZE (right) - 1;
10393 emitcode ("dec", "%s", rname);
10398 if (pi) pi->generated = 1;
10399 freeAsmop (result, NULL, ic, TRUE);
10400 freeAsmop (right, NULL, ic, TRUE);
10403 /*-----------------------------------------------------------------*/
10404 /* genFarPointerSet - set value from far space */
10405 /*-----------------------------------------------------------------*/
10407 genFarPointerSet (operand * right,
10408 operand * result, iCode * ic, iCode * pi)
10411 sym_link *retype = getSpec (operandType (right));
10412 sym_link *letype = getSpec (operandType (result));
10414 D(emitcode ("; genFarPointerSet",""));
10416 aopOp (result, ic, FALSE);
10417 loadDptrFromOperand (result, FALSE);
10419 /* so dptr know contains the address */
10420 aopOp (right, ic, FALSE);
10422 /* if bit then unpack */
10423 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10424 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10427 size = AOP_SIZE (right);
10432 char *l = aopGet (right, offset++, FALSE, FALSE);
10434 emitcode ("movx", "@dptr,a");
10436 emitcode ("inc", "dptr");
10439 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10440 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10441 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10444 freeAsmop (result, NULL, ic, TRUE);
10445 freeAsmop (right, NULL, ic, TRUE);
10448 /*-----------------------------------------------------------------*/
10449 /* genGenPointerSet - set value from generic pointer space */
10450 /*-----------------------------------------------------------------*/
10452 genGenPointerSet (operand * right,
10453 operand * result, iCode * ic, iCode * pi)
10456 sym_link *retype = getSpec (operandType (right));
10457 sym_link *letype = getSpec (operandType (result));
10459 D(emitcode ("; genGenPointerSet",""));
10461 aopOp (result, ic, FALSE);
10462 loadDptrFromOperand (result, TRUE);
10464 /* so dptr know contains the address */
10465 aopOp (right, ic, FALSE);
10467 /* if bit then unpack */
10468 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10469 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10472 size = AOP_SIZE (right);
10477 char *l = aopGet (right, offset++, FALSE, FALSE);
10479 emitcode ("lcall", "__gptrput");
10481 emitcode ("inc", "dptr");
10485 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10486 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10487 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10490 freeAsmop (result, NULL, ic, TRUE);
10491 freeAsmop (right, NULL, ic, TRUE);
10494 /*-----------------------------------------------------------------*/
10495 /* genPointerSet - stores the value into a pointer location */
10496 /*-----------------------------------------------------------------*/
10498 genPointerSet (iCode * ic, iCode *pi)
10500 operand *right, *result;
10501 sym_link *type, *etype;
10504 D(emitcode ("; genPointerSet",""));
10506 right = IC_RIGHT (ic);
10507 result = IC_RESULT (ic);
10509 /* depending on the type of pointer we need to
10510 move it to the correct pointer register */
10511 type = operandType (result);
10512 etype = getSpec (type);
10513 /* if left is of type of pointer then it is simple */
10514 if (IS_PTR (type) && !IS_FUNC (type->next))
10516 p_type = DCL_TYPE (type);
10520 /* we have to go by the storage class */
10521 p_type = PTR_TYPE (SPEC_OCLS (etype));
10524 /* special case when cast remat */
10525 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10526 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10527 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10528 type = operandType (result);
10529 p_type = DCL_TYPE (type);
10531 /* now that we have the pointer type we assign
10532 the pointer values */
10538 genNearPointerSet (right, result, ic, pi);
10542 genPagedPointerSet (right, result, ic, pi);
10546 genFarPointerSet (right, result, ic, pi);
10550 genGenPointerSet (right, result, ic, pi);
10554 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10555 "genPointerSet: illegal pointer type");
10560 /*-----------------------------------------------------------------*/
10561 /* genIfx - generate code for Ifx statement */
10562 /*-----------------------------------------------------------------*/
10564 genIfx (iCode * ic, iCode * popIc)
10566 operand *cond = IC_COND (ic);
10570 D(emitcode ("; genIfx",""));
10572 aopOp (cond, ic, FALSE);
10574 /* get the value into acc */
10575 if (AOP_TYPE (cond) != AOP_CRY)
10580 if (AOP(cond)->aopu.aop_dir)
10581 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10583 /* the result is now in the accumulator or a directly addressable bit */
10584 freeAsmop (cond, NULL, ic, TRUE);
10586 /* if there was something to be popped then do it */
10590 /* if the condition is a bit variable */
10592 genIfxJump(ic, dup, NULL, NULL, NULL);
10593 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10594 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10595 else if (isbit && !IS_ITEMP (cond))
10596 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10598 genIfxJump (ic, "a", NULL, NULL, NULL);
10603 /*-----------------------------------------------------------------*/
10604 /* genAddrOf - generates code for address of */
10605 /*-----------------------------------------------------------------*/
10607 genAddrOf (iCode * ic)
10609 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10612 D(emitcode ("; genAddrOf",""));
10614 aopOp (IC_RESULT (ic), ic, FALSE);
10616 /* if the operand is on the stack then we
10617 need to get the stack offset of this
10621 /* if it has an offset then we need to compute
10625 emitcode ("mov", "a,%s", SYM_BP (sym));
10626 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10627 ((char) (sym->stack - _G.nRegsSaved)) :
10628 ((char) sym->stack)) & 0xff);
10629 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10633 /* we can just move _bp */
10634 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10636 /* fill the result with zero */
10637 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10642 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10648 /* object not on stack then we need the name */
10649 size = AOP_SIZE (IC_RESULT (ic));
10654 char s[SDCC_NAME_MAX];
10656 sprintf (s, "#(%s >> %d)",
10660 sprintf (s, "#%s", sym->rname);
10661 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10665 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10669 /*-----------------------------------------------------------------*/
10670 /* genFarFarAssign - assignment when both are in far space */
10671 /*-----------------------------------------------------------------*/
10673 genFarFarAssign (operand * result, operand * right, iCode * ic)
10675 int size = AOP_SIZE (right);
10679 D(emitcode ("; genFarFarAssign",""));
10681 /* first push the right side on to the stack */
10684 l = aopGet (right, offset++, FALSE, FALSE);
10686 emitcode ("push", "acc");
10689 freeAsmop (right, NULL, ic, FALSE);
10690 /* now assign DPTR to result */
10691 aopOp (result, ic, FALSE);
10692 size = AOP_SIZE (result);
10695 emitcode ("pop", "acc");
10696 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10698 freeAsmop (result, NULL, ic, FALSE);
10701 /*-----------------------------------------------------------------*/
10702 /* genAssign - generate code for assignment */
10703 /*-----------------------------------------------------------------*/
10705 genAssign (iCode * ic)
10707 operand *result, *right;
10709 unsigned long lit = 0L;
10711 D(emitcode("; genAssign",""));
10713 result = IC_RESULT (ic);
10714 right = IC_RIGHT (ic);
10716 /* if they are the same */
10717 if (operandsEqu (result, right) &&
10718 !isOperandVolatile (result, FALSE) &&
10719 !isOperandVolatile (right, FALSE))
10722 aopOp (right, ic, FALSE);
10724 /* special case both in far space */
10725 if (AOP_TYPE (right) == AOP_DPTR &&
10726 IS_TRUE_SYMOP (result) &&
10727 isOperandInFarSpace (result))
10730 genFarFarAssign (result, right, ic);
10734 aopOp (result, ic, TRUE);
10736 /* if they are the same registers */
10737 if (sameRegs (AOP (right), AOP (result)) &&
10738 !isOperandVolatile (result, FALSE) &&
10739 !isOperandVolatile (right, FALSE))
10742 /* if the result is a bit */
10743 if (AOP_TYPE (result) == AOP_CRY)
10746 /* if the right size is a literal then
10747 we know what the value is */
10748 if (AOP_TYPE (right) == AOP_LIT)
10750 if (((int) operandLitValue (right)))
10751 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10753 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10757 /* the right is also a bit variable */
10758 if (AOP_TYPE (right) == AOP_CRY)
10760 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10761 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10765 /* we need to or */
10767 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10771 /* bit variables done */
10773 size = AOP_SIZE (result);
10775 if (AOP_TYPE (right) == AOP_LIT)
10776 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10778 (AOP_TYPE (result) != AOP_REG) &&
10779 (AOP_TYPE (right) == AOP_LIT) &&
10780 !IS_FLOAT (operandType (right)) &&
10783 while ((size) && (lit))
10786 aopGet (right, offset, FALSE, FALSE),
10788 isOperandVolatile (result, FALSE));
10793 emitcode ("clr", "a");
10796 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10805 aopGet (right, offset, FALSE, FALSE),
10807 isOperandVolatile (result, FALSE));
10813 freeAsmop (result, NULL, ic, TRUE);
10814 freeAsmop (right, NULL, ic, TRUE);
10817 /*-----------------------------------------------------------------*/
10818 /* genJumpTab - generates code for jump table */
10819 /*-----------------------------------------------------------------*/
10821 genJumpTab (iCode * ic)
10823 symbol *jtab,*jtablo,*jtabhi;
10825 unsigned int count;
10827 D(emitcode ("; genJumpTab",""));
10829 count = elementsInSet( IC_JTLABELS (ic) );
10833 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10834 if the switch argument is in a register.
10835 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10836 /* (MB) What if peephole converts ljmp to sjmp or ret ???
10837 How will multiply by three be updated ???*/
10838 aopOp (IC_JTCOND (ic), ic, FALSE);
10839 /* get the condition into accumulator */
10840 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10842 /* multiply by three */
10843 emitcode ("add", "a,acc");
10844 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10845 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10847 jtab = newiTempLabel (NULL);
10848 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10849 emitcode ("jmp", "@a+dptr");
10850 emitcode ("", "%05d$:", jtab->key + 100);
10851 /* now generate the jump labels */
10852 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10853 jtab = setNextItem (IC_JTLABELS (ic)))
10854 emitcode ("ljmp", "%05d$", jtab->key + 100);
10858 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10859 if the switch argument is in a register.
10860 For n>6 this algorithm may be more compact */
10861 jtablo = newiTempLabel (NULL);
10862 jtabhi = newiTempLabel (NULL);
10864 /* get the condition into accumulator.
10865 Using b as temporary storage, if register push/pop is needed */
10866 aopOp (IC_JTCOND (ic), ic, FALSE);
10867 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10868 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10869 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10871 // (MB) what if B is in use???
10872 wassertl(!BINUSE, "B was in use");
10873 emitcode ("mov", "b,%s", l);
10876 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10880 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10881 emitcode ("movc", "a,@a+pc");
10882 emitcode ("push", "acc");
10885 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10886 emitcode ("movc", "a,@a+pc");
10887 emitcode ("push", "acc");
10891 /* this scales up to n<=255, but needs two more bytes
10892 and changes dptr */
10893 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10894 emitcode ("movc", "a,@a+dptr");
10895 emitcode ("push", "acc");
10898 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10899 emitcode ("movc", "a,@a+dptr");
10900 emitcode ("push", "acc");
10903 emitcode ("ret", "");
10905 /* now generate jump table, LSB */
10906 emitcode ("", "%05d$:", jtablo->key + 100);
10907 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10908 jtab = setNextItem (IC_JTLABELS (ic)))
10909 emitcode (".db", "%05d$", jtab->key + 100);
10911 /* now generate jump table, MSB */
10912 emitcode ("", "%05d$:", jtabhi->key + 100);
10913 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10914 jtab = setNextItem (IC_JTLABELS (ic)))
10915 emitcode (".db", "%05d$>>8", jtab->key + 100);
10919 /*-----------------------------------------------------------------*/
10920 /* genCast - gen code for casting */
10921 /*-----------------------------------------------------------------*/
10923 genCast (iCode * ic)
10925 operand *result = IC_RESULT (ic);
10926 sym_link *ctype = operandType (IC_LEFT (ic));
10927 sym_link *rtype = operandType (IC_RIGHT (ic));
10928 operand *right = IC_RIGHT (ic);
10931 D(emitcode("; genCast",""));
10933 /* if they are equivalent then do nothing */
10934 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10937 aopOp (right, ic, FALSE);
10938 aopOp (result, ic, FALSE);
10940 /* if the result is a bit (and not a bitfield) */
10941 // if (AOP_TYPE (result) == AOP_CRY)
10942 if (IS_BIT (OP_SYMBOL (result)->type))
10943 /* not for bitfields */
10945 /* if the right size is a literal then
10946 we know what the value is */
10947 if (AOP_TYPE (right) == AOP_LIT)
10949 if (((int) operandLitValue (right)))
10950 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10952 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10957 /* the right is also a bit variable */
10958 if (AOP_TYPE (right) == AOP_CRY)
10960 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10961 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10965 /* we need to or */
10967 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10972 /* if they are the same size : or less */
10973 if (AOP_SIZE (result) <= AOP_SIZE (right))
10976 /* if they are in the same place */
10977 if (sameRegs (AOP (right), AOP (result)))
10980 /* if they in different places then copy */
10981 size = AOP_SIZE (result);
10986 aopGet (right, offset, FALSE, FALSE),
10988 isOperandVolatile (result, FALSE));
10995 /* if the result is of type pointer */
10996 if (IS_PTR (ctype))
11000 sym_link *type = operandType (right);
11001 sym_link *etype = getSpec (type);
11003 /* pointer to generic pointer */
11004 if (IS_GENPTR (ctype))
11007 p_type = DCL_TYPE (type);
11010 if (SPEC_SCLS(etype)==S_REGISTER) {
11011 // let's assume it is a generic pointer
11014 /* we have to go by the storage class */
11015 p_type = PTR_TYPE (SPEC_OCLS (etype));
11019 /* the first two bytes are known */
11020 size = GPTRSIZE - 1;
11025 aopGet (right, offset, FALSE, FALSE),
11027 isOperandVolatile (result, FALSE));
11030 /* the last byte depending on type */
11032 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11037 // pointerTypeToGPByte will have bitched.
11041 sprintf(gpValStr, "#0x%x", gpVal);
11042 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
11047 /* just copy the pointers */
11048 size = AOP_SIZE (result);
11053 aopGet (right, offset, FALSE, FALSE),
11055 isOperandVolatile (result, FALSE));
11061 /* so we now know that the size of destination is greater
11062 than the size of the source */
11063 /* we move to result for the size of source */
11064 size = AOP_SIZE (right);
11069 aopGet (right, offset, FALSE, FALSE),
11071 isOperandVolatile (result, FALSE));
11075 /* now depending on the sign of the source && destination */
11076 size = AOP_SIZE (result) - AOP_SIZE (right);
11077 /* if unsigned or not an integral type */
11078 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11081 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
11085 /* we need to extend the sign :{ */
11086 char *l = aopGet (right, AOP_SIZE (right) - 1,
11089 emitcode ("rlc", "a");
11090 emitcode ("subb", "a,acc");
11092 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
11095 /* we are done hurray !!!! */
11098 freeAsmop (result, NULL, ic, TRUE);
11099 freeAsmop (right, NULL, ic, TRUE);
11102 /*-----------------------------------------------------------------*/
11103 /* genDjnz - generate decrement & jump if not zero instrucion */
11104 /*-----------------------------------------------------------------*/
11106 genDjnz (iCode * ic, iCode * ifx)
11108 symbol *lbl, *lbl1;
11112 D(emitcode ("; genDjnz",""));
11114 /* if the if condition has a false label
11115 then we cannot save */
11116 if (IC_FALSE (ifx))
11119 /* if the minus is not of the form
11121 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11122 !IS_OP_LITERAL (IC_RIGHT (ic)))
11125 if (operandLitValue (IC_RIGHT (ic)) != 1)
11128 /* if the size of this greater than one then no
11130 if (getSize (operandType (IC_RESULT (ic))) > 1)
11133 /* otherwise we can save BIG */
11134 lbl = newiTempLabel (NULL);
11135 lbl1 = newiTempLabel (NULL);
11137 aopOp (IC_RESULT (ic), ic, FALSE);
11139 if (AOP_NEEDSACC(IC_RESULT(ic)))
11141 /* If the result is accessed indirectly via
11142 * the accumulator, we must explicitly write
11143 * it back after the decrement.
11145 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11147 if (strcmp(rByte, "a"))
11149 /* Something is hopelessly wrong */
11150 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11151 __FILE__, __LINE__);
11152 /* We can just give up; the generated code will be inefficient,
11153 * but what the hey.
11155 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11158 emitcode ("dec", "%s", rByte);
11159 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
11160 emitcode ("jnz", "%05d$", lbl->key + 100);
11162 else if (IS_AOP_PREG (IC_RESULT (ic)))
11164 emitcode ("dec", "%s",
11165 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11166 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11167 emitcode ("jnz", "%05d$", lbl->key + 100);
11171 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11174 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11175 emitcode ("", "%05d$:", lbl->key + 100);
11176 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11177 emitcode ("", "%05d$:", lbl1->key + 100);
11179 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11180 ifx->generated = 1;
11184 /*-----------------------------------------------------------------*/
11185 /* genReceive - generate code for a receive iCode */
11186 /*-----------------------------------------------------------------*/
11188 genReceive (iCode * ic)
11190 int size = getSize (operandType (IC_RESULT (ic)));
11193 D(emitcode ("; genReceive",""));
11195 if (ic->argreg == 1)
11196 { /* first parameter */
11197 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11198 isOperandInPagedSpace (IC_RESULT (ic))) &&
11199 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11200 IS_TRUE_SYMOP (IC_RESULT (ic))))
11203 int receivingA = 0;
11206 for (offset = 0; offset<size; offset++)
11207 if (!strcmp (fReturn[offset], "a"))
11212 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11214 for (offset = size-1; offset>0; offset--)
11215 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11216 emitcode("mov","a,%s", fReturn[0]);
11218 aopOp (IC_RESULT (ic), ic, FALSE);
11220 aopPut (IC_RESULT (ic), "a", offset,
11221 isOperandVolatile (IC_RESULT (ic), FALSE));
11222 for (offset = 1; offset<size; offset++)
11223 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
11224 isOperandVolatile (IC_RESULT (ic), FALSE));
11230 if (getTempRegs(tempRegs, size, ic))
11232 for (offset = 0; offset<size; offset++)
11233 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11234 aopOp (IC_RESULT (ic), ic, FALSE);
11235 for (offset = 0; offset<size; offset++)
11236 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
11237 isOperandVolatile (IC_RESULT (ic), FALSE));
11242 offset = fReturnSizeMCS51 - size;
11245 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11246 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11249 aopOp (IC_RESULT (ic), ic, FALSE);
11250 size = AOP_SIZE (IC_RESULT (ic));
11254 emitcode ("pop", "acc");
11255 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11261 aopOp (IC_RESULT (ic), ic, FALSE);
11263 assignResultValue (IC_RESULT (ic), NULL);
11266 else if (ic->argreg > 12)
11267 { /* bit parameters */
11268 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11270 aopOp (IC_RESULT (ic), ic, FALSE);
11271 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11272 outBitC(IC_RESULT (ic));
11276 { /* other parameters */
11278 aopOp (IC_RESULT (ic), ic, FALSE);
11279 rb1off = ic->argreg;
11282 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11287 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11290 /*-----------------------------------------------------------------*/
11291 /* genDummyRead - generate code for dummy read of volatiles */
11292 /*-----------------------------------------------------------------*/
11294 genDummyRead (iCode * ic)
11299 D(emitcode("; genDummyRead",""));
11301 op = IC_RIGHT (ic);
11302 if (op && IS_SYMOP (op))
11304 aopOp (op, ic, FALSE);
11306 /* if the result is a bit */
11307 if (AOP_TYPE (op) == AOP_CRY)
11308 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11311 /* bit variables done */
11313 size = AOP_SIZE (op);
11317 MOVA (aopGet (op, offset, FALSE, FALSE));
11322 freeAsmop (op, NULL, ic, TRUE);
11326 if (op && IS_SYMOP (op))
11328 aopOp (op, ic, FALSE);
11330 /* if the result is a bit */
11331 if (AOP_TYPE (op) == AOP_CRY)
11332 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11335 /* bit variables done */
11337 size = AOP_SIZE (op);
11341 MOVA (aopGet (op, offset, FALSE, FALSE));
11346 freeAsmop (op, NULL, ic, TRUE);
11350 /*-----------------------------------------------------------------*/
11351 /* genCritical - generate code for start of a critical sequence */
11352 /*-----------------------------------------------------------------*/
11354 genCritical (iCode *ic)
11356 symbol *tlbl = newiTempLabel (NULL);
11358 D(emitcode("; genCritical",""));
11360 if (IC_RESULT (ic))
11362 aopOp (IC_RESULT (ic), ic, TRUE);
11363 aopPut (IC_RESULT (ic), one, 0, 0);
11364 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11365 aopPut (IC_RESULT (ic), zero, 0, 0);
11366 emitcode ("", "%05d$:", (tlbl->key + 100));
11367 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11371 emitcode ("setb", "c");
11372 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11373 emitcode ("clr", "c");
11374 emitcode ("", "%05d$:", (tlbl->key + 100));
11375 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11379 /*-----------------------------------------------------------------*/
11380 /* genEndCritical - generate code for end of a critical sequence */
11381 /*-----------------------------------------------------------------*/
11383 genEndCritical (iCode *ic)
11385 D(emitcode("; genEndCritical",""));
11389 aopOp (IC_RIGHT (ic), ic, FALSE);
11390 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11392 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11393 emitcode ("mov", "ea,c");
11397 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11398 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11399 emitcode ("rrc", "a");
11400 emitcode ("mov", "ea,c");
11402 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11406 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11407 emitcode ("mov", "ea,c");
11411 /*-----------------------------------------------------------------*/
11412 /* gen51Code - generate code for 8051 based controllers */
11413 /*-----------------------------------------------------------------*/
11415 gen51Code (iCode * lic)
11419 /* int cseq = 0; */
11421 _G.currentFunc = NULL;
11422 lineHead = lineCurr = NULL;
11424 /* print the allocation information */
11425 if (allocInfo && currFunc)
11426 printAllocInfo (currFunc, codeOutFile);
11427 /* if debug information required */
11428 if (options.debug && currFunc)
11430 debugFile->writeFunction (currFunc, lic);
11432 /* stack pointer name */
11433 if (options.useXstack)
11439 for (ic = lic; ic; ic = ic->next)
11441 _G.current_iCode = ic;
11443 if (ic->lineno && cln != ic->lineno)
11447 debugFile->writeCLine (ic);
11449 if (!options.noCcodeInAsm) {
11450 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11451 printCLine(ic->filename, ic->lineno));
11456 if (ic->seqPoint && ic->seqPoint != cseq)
11458 emitcode ("", "; sequence point %d", ic->seqPoint);
11459 cseq = ic->seqPoint;
11462 if (options.iCodeInAsm) {
11463 char regsInUse[80];
11467 for (i=0; i<8; i++) {
11468 sprintf (®sInUse[i],
11469 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11472 strcpy (regsInUse, "--------");
11473 for (i=0; i < 8; i++) {
11474 if (bitVectBitValue (ic->rMask, i))
11476 int offset = regs8051[i].offset;
11477 regsInUse[offset] = offset + '0'; /* show rMask */
11481 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11483 /* if the result is marked as
11484 spilt and rematerializable or code for
11485 this has already been generated then
11487 if (resultRemat (ic) || ic->generated)
11490 /* depending on the operation */
11510 /* IPOP happens only when trying to restore a
11511 spilt live range, if there is an ifx statement
11512 following this pop then the if statement might
11513 be using some of the registers being popped which
11514 would destory the contents of the register so
11515 we need to check for this condition and handle it */
11517 ic->next->op == IFX &&
11518 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11519 genIfx (ic->next, ic);
11537 genEndFunction (ic);
11557 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11574 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11578 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11585 /* note these two are xlated by algebraic equivalence
11586 during parsing SDCC.y */
11587 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11588 "got '>=' or '<=' shouldn't have come here");
11592 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11604 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11608 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11612 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11648 genRightShift (ic);
11651 case GET_VALUE_AT_ADDRESS:
11653 hasInc (IC_LEFT (ic), ic,
11654 getSize (operandType (IC_RESULT (ic)))),
11655 ifxForOp (IC_RESULT (ic), ic) );
11659 if (POINTER_SET (ic))
11660 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11686 addSet (&_G.sendSet, ic);
11689 case DUMMY_READ_VOLATILE:
11698 genEndCritical (ic);
11710 _G.current_iCode = NULL;
11712 /* now we are ready to call the
11713 peep hole optimizer */
11714 if (!options.nopeep)
11715 peepHole (&lineHead);
11717 /* now do the actual printing */
11718 printLine (lineHead, codeOutFile);