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 /* sameRegs - two asmops have the same registers */
814 /*-----------------------------------------------------------------*/
816 sameRegs (asmop * aop1, asmop * aop2)
823 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
826 if (aop1->type != aop2->type)
829 if (aop1->size != aop2->size)
832 for (i = 0; i < aop1->size; i++)
833 if (aop1->aopu.aop_reg[i] !=
834 aop2->aopu.aop_reg[i])
840 /*-----------------------------------------------------------------*/
841 /* aopOp - allocates an asmop for an operand : */
842 /*-----------------------------------------------------------------*/
844 aopOp (operand * op, iCode * ic, bool result)
853 /* if this a literal */
854 if (IS_OP_LITERAL (op))
856 op->aop = aop = newAsmop (AOP_LIT);
857 aop->aopu.aop_lit = op->operand.valOperand;
858 aop->size = getSize (operandType (op));
862 /* if already has a asmop then continue */
865 op->aop->allocated++;
869 /* if the underlying symbol has a aop */
870 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
872 op->aop = OP_SYMBOL (op)->aop;
873 op->aop->allocated++;
877 /* if this is a true symbol */
878 if (IS_TRUE_SYMOP (op))
880 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
884 /* this is a temporary : this has
890 e) can be a return use only */
892 sym = OP_SYMBOL (op);
894 /* if the type is a conditional */
895 if (sym->regType == REG_CND)
897 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
902 /* if it is spilt then two situations
904 b) has a spill location */
905 if (sym->isspilt || sym->nRegs == 0)
908 /* rematerialize it NOW */
911 sym->aop = op->aop = aop =
913 aop->size = getSize (sym->type);
920 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
921 aop->size = getSize (sym->type);
922 for (i = 0; i < 2; i++)
923 aop->aopu.aop_str[i] = accUse[i];
931 aop = op->aop = sym->aop = newAsmop (AOP_STR);
932 aop->size = getSize (sym->type);
933 for (i = 0; i < fReturnSizeMCS51; i++)
934 aop->aopu.aop_str[i] = fReturn[i];
938 if (sym->usl.spillLoc)
940 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
942 /* force a new aop if sizes differ */
943 sym->usl.spillLoc->aop = NULL;
945 sym->aop = op->aop = aop =
946 aopForSym (ic, sym->usl.spillLoc, result);
947 aop->size = getSize (sym->type);
951 /* else must be a dummy iTemp */
952 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
953 aop->size = getSize (sym->type);
957 /* if the type is a bit register */
958 if (sym->regType == REG_BIT)
960 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
961 aop->size = sym->nRegs;//1???
962 aop->aopu.aop_reg[0] = sym->regs[0];
963 aop->aopu.aop_dir = sym->regs[0]->name;
967 /* must be in a register */
968 sym->aop = op->aop = aop = newAsmop (AOP_REG);
969 aop->size = sym->nRegs;
970 for (i = 0; i < sym->nRegs; i++)
971 aop->aopu.aop_reg[i] = sym->regs[i];
974 /*-----------------------------------------------------------------*/
975 /* freeAsmop - free up the asmop given to an operand */
976 /*----------------------------------------------------------------*/
978 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
995 /* depending on the asmop type only three cases need work
996 AOP_R0, AOP_R1 & AOP_STK */
1002 emitcode ("mov", "r0,b");
1005 else if (_G.r0Pushed)
1009 emitcode ("pop", "ar0");
1013 bitVectUnSetBit (ic->rUsed, R0_IDX);
1019 emitcode ("mov", "r1,b");
1026 emitcode ("pop", "ar1");
1030 bitVectUnSetBit (ic->rUsed, R1_IDX);
1036 int stk = aop->aopu.aop_stk + aop->size - 1;
1037 bitVectUnSetBit (ic->rUsed, R0_IDX);
1038 bitVectUnSetBit (ic->rUsed, R1_IDX);
1040 getFreePtr (ic, &aop, FALSE);
1044 emitcode ("mov", "a,_bp");
1045 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1046 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1050 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1055 emitcode ("pop", "acc");
1056 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1059 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1062 freeAsmop (op, NULL, ic, TRUE);
1065 emitcode ("pop", "ar1");
1071 emitcode ("pop", "ar0");
1078 /* all other cases just dealloc */
1084 OP_SYMBOL (op)->aop = NULL;
1085 /* if the symbol has a spill */
1087 SPIL_LOC (op)->aop = NULL;
1092 /*------------------------------------------------------------------*/
1093 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1094 /* pop r0 or r1 off stack if pushed */
1095 /*------------------------------------------------------------------*/
1097 freeForBranchAsmop (operand * op)
1109 if (!aop->allocated)
1117 emitcode ("mov", "r0,b");
1119 else if (_G.r0Pushed)
1121 emitcode ("pop", "ar0");
1128 emitcode ("mov", "r1,b");
1130 else if (_G.r1Pushed)
1132 emitcode ("pop", "ar1");
1139 int stk = aop->aopu.aop_stk + aop->size - 1;
1141 emitcode ("mov", "b,r0");
1144 emitcode ("mov", "a,_bp");
1145 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1146 emitcode ("mov", "r0,a");
1150 emitcode ("mov", "r0,_bp");
1155 emitcode ("pop", "acc");
1156 emitcode ("mov", "@r0,a");
1159 emitcode ("dec", "r0");
1161 emitcode ("mov", "r0,b");
1167 /*-----------------------------------------------------------------*/
1168 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1169 /* clobber the accumulator */
1170 /*-----------------------------------------------------------------*/
1172 aopGetUsesAcc (operand * oper, int offset)
1174 asmop * aop = AOP (oper);
1176 if (offset > (aop->size - 1))
1194 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1205 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1211 /* Error case --- will have been caught already */
1217 /*-----------------------------------------------------------------*/
1218 /* aopGet - for fetching value of the aop */
1219 /*-----------------------------------------------------------------*/
1221 aopGet (operand * oper, int offset, bool bit16, bool dname)
1225 asmop * aop = AOP (oper);
1227 /* offset is greater than
1229 if (offset > (aop->size - 1) &&
1230 aop->type != AOP_LIT)
1233 /* depending on type */
1241 /* if we need to increment it */
1242 while (offset > aop->coff)
1244 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1248 while (offset < aop->coff)
1250 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1257 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1258 return (dname ? "acc" : "a");
1260 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1261 rs = Safe_calloc (1, strlen (s) + 1);
1266 if (aop->code && aop->coff==0 && offset>=1) {
1267 emitcode ("mov", "a,#0x%02x", offset);
1268 emitcode ("movc", "a,@a+dptr");
1269 return (dname ? "acc" : "a");
1272 while (offset > aop->coff)
1274 emitcode ("inc", "dptr");
1278 while (offset < aop->coff)
1280 emitcode ("lcall", "__decdptr");
1287 emitcode ("clr", "a");
1288 emitcode ("movc", "a,@a+dptr");
1292 emitcode ("movx", "a,@dptr");
1294 return (dname ? "acc" : "a");
1298 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1299 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1301 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1303 sprintf (s, "#(%s >> %d)",
1304 aop->aopu.aop_immd.aop_immd1,
1308 aop->aopu.aop_immd.aop_immd1);
1309 rs = Safe_calloc (1, strlen (s) + 1);
1314 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1315 sprintf (s, "(%s >> %d)",
1316 aop->aopu.aop_dir, offset * 8);
1318 sprintf (s, "(%s + %d)",
1322 sprintf (s, "%s", aop->aopu.aop_dir);
1323 rs = Safe_calloc (1, strlen (s) + 1);
1329 return aop->aopu.aop_reg[offset]->dname;
1331 return aop->aopu.aop_reg[offset]->name;
1334 emitcode ("clr", "a");
1335 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1336 emitcode ("rlc", "a");
1337 return (dname ? "acc" : "a");
1340 if (!offset && dname)
1342 return aop->aopu.aop_str[offset];
1345 return aopLiteral (aop->aopu.aop_lit, offset);
1349 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1353 return aop->aopu.aop_str[offset];
1357 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1358 "aopget got unsupported aop->type");
1362 /*-----------------------------------------------------------------*/
1363 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1364 /* clobber the accumulator */
1365 /*-----------------------------------------------------------------*/
1367 aopPutUsesAcc (operand * oper, const char *s, int offset)
1369 asmop * aop = AOP (oper);
1371 if (offset > (aop->size - 1))
1381 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1387 return ((aop->paged) || (*s == '@'));
1391 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1399 /* Error case --- will have been caught already */
1405 /*-----------------------------------------------------------------*/
1406 /* aopPut - puts a string for a aop and indicates if acc is in use */
1407 /*-----------------------------------------------------------------*/
1409 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1412 bool accuse = FALSE;
1413 asmop * aop = AOP (result);
1415 if (aop->size && offset > (aop->size - 1))
1417 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1418 "aopPut got offset > aop->size");
1422 /* will assign value to value */
1423 /* depending on where it is ofcourse */
1427 MOVA (s); /* read s in case it was volatile */
1432 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1433 sprintf (d, "(%s >> %d)", aop->aopu.aop_dir, offset * 8);
1435 sprintf (d, "(%s + %d)", aop->aopu.aop_dir, offset);
1437 sprintf (d, "%s", aop->aopu.aop_dir);
1439 if (strcmp (d, s) || bvolatile)
1440 emitcode ("mov", "%s,%s", d, s);
1441 if (!strcmp (d, "acc"))
1447 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1448 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1451 strcmp (s, "r0") == 0 ||
1452 strcmp (s, "r1") == 0 ||
1453 strcmp (s, "r2") == 0 ||
1454 strcmp (s, "r3") == 0 ||
1455 strcmp (s, "r4") == 0 ||
1456 strcmp (s, "r5") == 0 ||
1457 strcmp (s, "r6") == 0 ||
1458 strcmp (s, "r7") == 0)
1459 emitcode ("mov", "%s,%s",
1460 aop->aopu.aop_reg[offset]->dname, s);
1462 emitcode ("mov", "%s,%s",
1463 aop->aopu.aop_reg[offset]->name, s);
1470 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1471 "aopPut writing to code space");
1475 while (offset > aop->coff)
1478 emitcode ("inc", "dptr");
1481 while (offset < aop->coff)
1484 emitcode ("lcall", "__decdptr");
1489 /* if not in accumulator */
1492 emitcode ("movx", "@dptr,a");
1497 while (offset > aop->coff)
1500 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1502 while (offset < aop->coff)
1505 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1512 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1517 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1519 else if (strcmp (s, "r0") == 0 ||
1520 strcmp (s, "r1") == 0 ||
1521 strcmp (s, "r2") == 0 ||
1522 strcmp (s, "r3") == 0 ||
1523 strcmp (s, "r4") == 0 ||
1524 strcmp (s, "r5") == 0 ||
1525 strcmp (s, "r6") == 0 ||
1526 strcmp (s, "r7") == 0)
1529 sprintf (buffer, "a%s", s);
1530 emitcode ("mov", "@%s,%s",
1531 aop->aopu.aop_ptr->name, buffer);
1534 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1539 if (strcmp (s, "a") == 0)
1540 emitcode ("push", "acc");
1544 emitcode ("push", "acc");
1546 emitcode ("push", s);
1552 /* if not bit variable */
1553 if (!aop->aopu.aop_dir)
1555 /* inefficient: move carry into A and use jz/jnz */
1556 emitcode ("clr", "a");
1557 emitcode ("rlc", "a");
1563 emitcode ("clr", "%s", aop->aopu.aop_dir);
1565 emitcode ("setb", "%s", aop->aopu.aop_dir);
1566 else if (!strcmp (s, "c"))
1567 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1568 else if (strcmp (s, aop->aopu.aop_dir))
1571 /* set C, if a >= 1 */
1572 emitcode ("add", "a,#0xff");
1573 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1580 if (strcmp (aop->aopu.aop_str[offset], s) ||
1582 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1588 if (!offset && (strcmp (s, "acc") == 0) &&
1592 if (strcmp (aop->aopu.aop_str[offset], s) &&
1594 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1598 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1599 "aopPut got unsupported aop->type");
1608 /*-----------------------------------------------------------------*/
1609 /* pointToEnd :- points to the last byte of the operand */
1610 /*-----------------------------------------------------------------*/
1612 pointToEnd (asmop * aop)
1618 aop->coff = count = (aop->size - 1);
1624 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1628 emitcode ("inc", "dptr");
1635 /*-----------------------------------------------------------------*/
1636 /* reAdjustPreg - points a register back to where it should */
1637 /*-----------------------------------------------------------------*/
1639 reAdjustPreg (asmop * aop)
1641 if ((aop->coff==0) || aop->size <= 1)
1649 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1654 emitcode ("lcall", "__decdptr");
1661 /*-----------------------------------------------------------------*/
1662 /* opIsGptr: returns non-zero if the passed operand is */
1663 /* a generic pointer type. */
1664 /*-----------------------------------------------------------------*/
1666 opIsGptr (operand * op)
1668 sym_link *type = operandType (op);
1670 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1677 /*-----------------------------------------------------------------*/
1678 /* getDataSize - get the operand data size */
1679 /*-----------------------------------------------------------------*/
1681 getDataSize (operand * op)
1684 size = AOP_SIZE (op);
1685 if (size == GPTRSIZE)
1687 sym_link *type = operandType (op);
1688 if (IS_GENPTR (type))
1690 /* generic pointer; arithmetic operations
1691 * should ignore the high byte (pointer type).
1699 /*-----------------------------------------------------------------*/
1700 /* outAcc - output Acc */
1701 /*-----------------------------------------------------------------*/
1703 outAcc (operand * result)
1706 size = getDataSize (result);
1709 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1712 /* unsigned or positive */
1715 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1720 /*-----------------------------------------------------------------*/
1721 /* outBitC - output a bit C */
1722 /*-----------------------------------------------------------------*/
1724 outBitC (operand * result)
1726 /* if the result is bit */
1727 if (AOP_TYPE (result) == AOP_CRY)
1728 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1731 emitcode ("clr", "a");
1732 emitcode ("rlc", "a");
1737 /*-----------------------------------------------------------------*/
1738 /* toBoolean - emit code for orl a,operator(sizeop) */
1739 /*-----------------------------------------------------------------*/
1741 toBoolean (operand * oper)
1743 int size = AOP_SIZE (oper) - 1;
1745 bool AccUsed = FALSE;
1748 while (!AccUsed && size--)
1750 AccUsed |= aopGetUsesAcc(oper, offset++);
1753 size = AOP_SIZE (oper) - 1;
1755 MOVA (aopGet (oper, 0, FALSE, FALSE));
1756 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1759 emitcode("mov", "b,a");
1762 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1763 emitcode ("orl", "b,a");
1765 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1766 emitcode ("orl", "a,b");
1773 emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1779 /*-----------------------------------------------------------------*/
1780 /* genNot - generate code for ! operation */
1781 /*-----------------------------------------------------------------*/
1787 D(emitcode ("; genNot",""));
1789 /* assign asmOps to operand & result */
1790 aopOp (IC_LEFT (ic), ic, FALSE);
1791 aopOp (IC_RESULT (ic), ic, TRUE);
1793 /* if in bit space then a special case */
1794 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1796 /* if left==result then cpl bit */
1797 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1799 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1803 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1804 emitcode ("cpl", "c");
1805 outBitC (IC_RESULT (ic));
1810 toBoolean (IC_LEFT (ic));
1812 /* set C, if a == 0 */
1813 tlbl = newiTempLabel (NULL);
1814 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1815 emitcode ("", "%05d$:", tlbl->key + 100);
1816 outBitC (IC_RESULT (ic));
1819 /* release the aops */
1820 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1821 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1825 /*-----------------------------------------------------------------*/
1826 /* genCpl - generate code for complement */
1827 /*-----------------------------------------------------------------*/
1834 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1836 D(emitcode (";", "genCpl"));
1838 /* assign asmOps to operand & result */
1839 aopOp (IC_LEFT (ic), ic, FALSE);
1840 aopOp (IC_RESULT (ic), ic, TRUE);
1842 /* special case if in bit space */
1843 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1847 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1848 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1850 /* promotion rules are responsible for this strange result:
1851 bit -> int -> ~int -> bit
1852 uchar -> int -> ~int -> bit
1854 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1858 tlbl=newiTempLabel(NULL);
1859 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1860 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1861 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1862 IS_AOP_PREG (IC_LEFT (ic)))
1864 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1869 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1871 emitcode ("", "%05d$:", tlbl->key + 100);
1872 outBitC (IC_RESULT(ic));
1876 size = AOP_SIZE (IC_RESULT (ic));
1879 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1881 emitcode ("cpl", "a");
1882 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1887 /* release the aops */
1888 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1889 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1892 /*-----------------------------------------------------------------*/
1893 /* genUminusFloat - unary minus for floating points */
1894 /*-----------------------------------------------------------------*/
1896 genUminusFloat (operand * op, operand * result)
1898 int size, offset = 0;
1901 D(emitcode ("; genUminusFloat",""));
1903 /* for this we just copy and then flip the bit */
1905 size = AOP_SIZE (op) - 1;
1910 aopGet (op, offset, FALSE, FALSE),
1912 isOperandVolatile (result, FALSE));
1916 l = aopGet (op, offset, FALSE, FALSE);
1920 emitcode ("cpl", "acc.7");
1921 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1924 /*-----------------------------------------------------------------*/
1925 /* genUminus - unary minus code generation */
1926 /*-----------------------------------------------------------------*/
1928 genUminus (iCode * ic)
1931 sym_link *optype, *rtype;
1934 D(emitcode ("; genUminus",""));
1937 aopOp (IC_LEFT (ic), ic, FALSE);
1938 aopOp (IC_RESULT (ic), ic, TRUE);
1940 /* if both in bit space then special
1942 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1943 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1946 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1947 emitcode ("cpl", "c");
1948 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1952 optype = operandType (IC_LEFT (ic));
1953 rtype = operandType (IC_RESULT (ic));
1955 /* if float then do float stuff */
1956 if (IS_FLOAT (optype))
1958 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1962 /* otherwise subtract from zero */
1963 size = AOP_SIZE (IC_LEFT (ic));
1968 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1969 if (!strcmp (l, "a"))
1973 emitcode ("cpl", "a");
1974 emitcode ("addc", "a,#0");
1980 emitcode ("clr", "a");
1981 emitcode ("subb", "a,%s", l);
1983 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1986 /* if any remaining bytes in the result */
1987 /* we just need to propagate the sign */
1988 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1990 emitcode ("rlc", "a");
1991 emitcode ("subb", "a,acc");
1993 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1997 /* release the aops */
1998 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1999 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2002 /*-----------------------------------------------------------------*/
2003 /* saveRegisters - will look for a call and save the registers */
2004 /*-----------------------------------------------------------------*/
2006 saveRegisters (iCode * lic)
2013 for (ic = lic; ic; ic = ic->next)
2014 if (ic->op == CALL || ic->op == PCALL)
2019 fprintf (stderr, "found parameter push with no function call\n");
2023 /* if the registers have been saved already or don't need to be then
2027 if (IS_SYMOP(IC_LEFT(ic)) &&
2028 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2029 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2032 /* save the registers in use at this time but skip the
2033 ones for the result */
2034 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2035 mcs51_rUmaskForOp (IC_RESULT(ic)));
2038 if (options.useXstack)
2040 int count = bitVectnBitsOn (rsave);
2044 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2045 if (reg->type == REG_BIT)
2047 emitcode ("mov", "a,%s", reg->base);
2051 emitcode ("mov", "a,%s", reg->name);
2053 emitcode ("mov", "r0,%s", spname);
2054 emitcode ("inc", "%s", spname);// allocate before use
2055 emitcode ("movx", "@r0,a");
2056 if (bitVectBitValue (rsave, R0_IDX))
2057 emitcode ("mov", "r0,a");
2059 else if (count != 0)
2061 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2062 int nBits = bitVectnBitsOn (rsavebits);
2066 count = count - nBits + 1;
2067 /* remove all but the first bits as they are pushed all at once */
2068 rsave = bitVectCplAnd (rsave, rsavebits);
2069 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2072 if (bitVectBitValue (rsave, R0_IDX))
2074 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2076 emitcode ("mov", "r0,%s", spname);
2078 emitcode ("add", "a,#%d", count);
2079 emitcode ("mov", "%s,a", spname);
2080 for (i = 0; i < mcs51_nRegs; i++)
2082 if (bitVectBitValue (rsave, i))
2084 regs * reg = mcs51_regWithIdx (i);
2087 emitcode ("pop", "acc");
2088 emitcode ("push", "acc");
2090 else if (reg->type == REG_BIT)
2092 emitcode ("mov", "a,%s", reg->base);
2096 emitcode ("mov", "a,%s", reg->name);
2098 emitcode ("movx", "@r0,a");
2101 emitcode ("inc", "r0");
2105 if (bitVectBitValue (rsave, R0_IDX))
2107 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2113 bool bits_pushed = FALSE;
2114 for (i = 0; i < mcs51_nRegs; i++)
2116 if (bitVectBitValue (rsave, i))
2118 bits_pushed = pushReg (i, bits_pushed);
2124 /*-----------------------------------------------------------------*/
2125 /* unsaveRegisters - pop the pushed registers */
2126 /*-----------------------------------------------------------------*/
2128 unsaveRegisters (iCode * ic)
2133 /* restore the registers in use at this time but skip the
2134 ones for the result */
2135 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2136 mcs51_rUmaskForOp (IC_RESULT(ic)));
2138 if (options.useXstack)
2140 int count = bitVectnBitsOn (rsave);
2144 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2145 emitcode ("mov", "r0,%s", spname);
2146 emitcode ("dec", "r0");
2147 emitcode ("movx", "a,@r0");
2148 if (reg->type == REG_BIT)
2150 emitcode ("mov", "%s,a", reg->base);
2154 emitcode ("mov", "%s,a", reg->name);
2156 emitcode ("dec", "%s", spname);
2158 else if (count != 0)
2160 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2161 int nBits = bitVectnBitsOn (rsavebits);
2165 count = count - nBits + 1;
2166 /* remove all but the first bits as they are popped all at once */
2167 rsave = bitVectCplAnd (rsave, rsavebits);
2168 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2171 emitcode ("mov", "r0,%s", spname);
2172 for (i = mcs51_nRegs; i >= 0; i--)
2174 if (bitVectBitValue (rsave, i))
2176 regs * reg = mcs51_regWithIdx (i);
2177 emitcode ("dec", "r0");
2178 emitcode ("movx", "a,@r0");
2181 emitcode ("push", "acc");
2183 else if (reg->type == REG_BIT)
2185 emitcode ("mov", "%s,a", reg->base);
2189 emitcode ("mov", "%s,a", reg->name);
2193 emitcode ("mov", "%s,r0", spname);
2194 if (bitVectBitValue (rsave, R0_IDX))
2196 emitcode ("pop", "ar0");
2202 bool bits_popped = FALSE;
2203 for (i = mcs51_nRegs; i >= 0; i--)
2205 if (bitVectBitValue (rsave, i))
2207 bits_popped = popReg (i, bits_popped);
2214 /*-----------------------------------------------------------------*/
2216 /*-----------------------------------------------------------------*/
2218 pushSide (operand * oper, int size)
2223 char *l = aopGet (oper, offset++, FALSE, TRUE);
2224 if (AOP_TYPE (oper) != AOP_REG &&
2225 AOP_TYPE (oper) != AOP_DIR &&
2229 emitcode ("push", "acc");
2233 emitcode ("push", "%s", l);
2238 /*-----------------------------------------------------------------*/
2239 /* assignResultValue - also indicates if acc is in use afterwards */
2240 /*-----------------------------------------------------------------*/
2242 assignResultValue (operand * oper, operand * func)
2245 int size = AOP_SIZE (oper);
2246 bool accuse = FALSE;
2247 bool pushedA = FALSE;
2249 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2255 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2257 emitcode ("push", "acc");
2262 if ((offset == 3) && pushedA)
2263 emitcode ("pop", "acc");
2264 accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2271 /*-----------------------------------------------------------------*/
2272 /* genXpush - pushes onto the external stack */
2273 /*-----------------------------------------------------------------*/
2275 genXpush (iCode * ic)
2277 asmop *aop = newAsmop (0);
2279 int size, offset = 0;
2281 D(emitcode ("; genXpush",""));
2283 aopOp (IC_LEFT (ic), ic, FALSE);
2284 r = getFreePtr (ic, &aop, FALSE);
2286 size = AOP_SIZE (IC_LEFT (ic));
2290 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2291 emitcode ("mov", "%s,%s", r->name, spname);
2292 emitcode ("inc", "%s", spname); // allocate space first
2293 emitcode ("movx", "@%s,a", r->name);
2297 // allocate space first
2298 emitcode ("mov", "%s,%s", r->name, spname);
2300 emitcode ("add", "a,#%d", size);
2301 emitcode ("mov", "%s,a", spname);
2305 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2306 emitcode ("movx", "@%s,a", r->name);
2307 emitcode ("inc", "%s", r->name);
2311 freeAsmop (NULL, aop, ic, TRUE);
2312 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2315 /*-----------------------------------------------------------------*/
2316 /* genIpush - generate code for pushing this gets a little complex */
2317 /*-----------------------------------------------------------------*/
2319 genIpush (iCode * ic)
2321 int size, offset = 0;
2325 D(emitcode ("; genIpush",""));
2327 /* if this is not a parm push : ie. it is spill push
2328 and spill push is always done on the local stack */
2332 /* and the item is spilt then do nothing */
2333 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2336 aopOp (IC_LEFT (ic), ic, FALSE);
2337 size = AOP_SIZE (IC_LEFT (ic));
2338 /* push it on the stack */
2341 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2347 emitcode ("push", "%s", l);
2352 /* this is a parameter push: in this case we call
2353 the routine to find the call and save those
2354 registers that need to be saved */
2357 /* if use external stack then call the external
2358 stack pushing routine */
2359 if (options.useXstack)
2365 /* then do the push */
2366 aopOp (IC_LEFT (ic), ic, FALSE);
2368 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2369 size = AOP_SIZE (IC_LEFT (ic));
2373 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2374 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2375 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2378 if (strcmp (l, prev) || *l == '@')
2380 emitcode ("push", "acc");
2384 emitcode ("push", "%s", l);
2389 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2392 /*-----------------------------------------------------------------*/
2393 /* genIpop - recover the registers: can happen only for spilling */
2394 /*-----------------------------------------------------------------*/
2396 genIpop (iCode * ic)
2400 D(emitcode ("; genIpop",""));
2402 /* if the temp was not pushed then */
2403 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2406 aopOp (IC_LEFT (ic), ic, FALSE);
2407 size = AOP_SIZE (IC_LEFT (ic));
2408 offset = (size - 1);
2410 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2413 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2416 /*-----------------------------------------------------------------*/
2417 /* saveRBank - saves an entire register bank on the stack */
2418 /*-----------------------------------------------------------------*/
2420 saveRBank (int bank, iCode * ic, bool pushPsw)
2423 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2427 if (options.useXstack)
2431 /* Assume r0 is available for use. */
2432 r = mcs51_regWithIdx (R0_IDX);;
2437 r = getFreePtr (ic, &aop, FALSE);
2439 // allocate space first
2440 emitcode ("mov", "%s,%s", r->name, spname);
2442 emitcode ("add", "a,#%d", count);
2443 emitcode ("mov", "%s,a", spname);
2446 for (i = 0; i < 8; i++)
2448 if (options.useXstack)
2450 emitcode ("mov", "a,(%s+%d)",
2451 regs8051[i].base, 8 * bank + regs8051[i].offset);
2452 emitcode ("movx", "@%s,a", r->name);
2454 emitcode ("inc", "%s", r->name);
2457 emitcode ("push", "(%s+%d)",
2458 regs8051[i].base, 8 * bank + regs8051[i].offset);
2461 if (mcs51_nRegs > 8)
2463 if (options.useXstack)
2465 emitcode ("mov", "a,bits");
2466 emitcode ("movx", "@%s,a", r->name);
2468 emitcode ("inc", "%s", r->name);
2472 emitcode ("push", "bits");
2479 if (options.useXstack)
2481 emitcode ("mov", "a,psw");
2482 emitcode ("movx", "@%s,a", r->name);
2487 emitcode ("push", "psw");
2490 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2495 freeAsmop (NULL, aop, ic, TRUE);
2504 /*-----------------------------------------------------------------*/
2505 /* unsaveRBank - restores the register bank from stack */
2506 /*-----------------------------------------------------------------*/
2508 unsaveRBank (int bank, iCode * ic, bool popPsw)
2514 if (options.useXstack)
2518 /* Assume r0 is available for use. */
2519 r = mcs51_regWithIdx (R0_IDX);;
2524 r = getFreePtr (ic, &aop, FALSE);
2526 emitcode ("mov", "%s,%s", r->name, spname);
2531 if (options.useXstack)
2533 emitcode ("dec", "%s", r->name);
2534 emitcode ("movx", "a,@%s", r->name);
2535 emitcode ("mov", "psw,a");
2539 emitcode ("pop", "psw");
2543 if (mcs51_nRegs > 8)
2545 if (options.useXstack)
2547 emitcode ("dec", "%s", r->name);
2548 emitcode ("movx", "a,@%s", r->name);
2549 emitcode ("mov", "bits,a");
2553 emitcode ("pop", "bits");
2557 for (i = 7; i >= 0; i--)
2559 if (options.useXstack)
2561 emitcode ("dec", "%s", r->name);
2562 emitcode ("movx", "a,@%s", r->name);
2563 emitcode ("mov", "(%s+%d),a",
2564 regs8051[i].base, 8 * bank + regs8051[i].offset);
2568 emitcode ("pop", "(%s+%d)",
2569 regs8051[i].base, 8 * bank + regs8051[i].offset);
2573 if (options.useXstack)
2575 emitcode ("mov", "%s,%s", spname, r->name);
2580 freeAsmop (NULL, aop, ic, TRUE);
2584 /*-----------------------------------------------------------------*/
2585 /* genSend - gen code for SEND */
2586 /*-----------------------------------------------------------------*/
2587 static void genSend(set *sendSet)
2592 /* first we do all bit parameters */
2593 for (sic = setFirstItem (sendSet); sic;
2594 sic = setNextItem (sendSet))
2596 aopOp (IC_LEFT (sic), sic, FALSE);
2598 if (sic->argreg > 12)
2600 int bit = sic->argreg-13;
2602 /* if left is a literal then
2603 we know what the value is */
2604 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2606 if (((int) operandLitValue (IC_LEFT (sic))))
2607 emitcode ("setb", "b[%d]", bit);
2609 emitcode ("clr", "b[%d]", bit);
2611 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2613 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2614 if (strcmp (l, "c"))
2615 emitcode ("mov", "c,%s", l);
2616 emitcode ("mov", "b[%d],c", bit);
2621 toBoolean (IC_LEFT (sic));
2622 /* set C, if a >= 1 */
2623 emitcode ("add", "a,#0xff");
2624 emitcode ("mov", "b[%d],c", bit);
2629 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2634 saveRegisters (setFirstItem (sendSet));
2635 emitcode ("mov", "bits,b");
2638 /* then we do all other parameters */
2639 for (sic = setFirstItem (sendSet); sic;
2640 sic = setNextItem (sendSet))
2642 int size, offset = 0;
2643 aopOp (IC_LEFT (sic), sic, FALSE);
2644 size = AOP_SIZE (IC_LEFT (sic));
2646 if (sic->argreg == 1)
2650 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2651 if (strcmp (l, fReturn[offset]))
2652 emitcode ("mov", "%s,%s", fReturn[offset], l);
2656 else if (sic->argreg <= 12)
2660 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2661 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2665 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2669 /*-----------------------------------------------------------------*/
2670 /* selectRegBank - emit code to select the register bank */
2671 /*-----------------------------------------------------------------*/
2673 selectRegBank (short bank, bool keepFlags)
2675 /* if f.e. result is in carry */
2678 emitcode ("anl", "psw,#0xE7");
2680 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2684 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2688 /*-----------------------------------------------------------------*/
2689 /* genCall - generates a call statement */
2690 /*-----------------------------------------------------------------*/
2692 genCall (iCode * ic)
2696 // bool restoreBank = FALSE;
2697 bool swapBanks = FALSE;
2698 bool accuse = FALSE;
2699 bool accPushed = FALSE;
2700 bool resultInF0 = FALSE;
2702 D(emitcode("; genCall",""));
2704 dtype = operandType (IC_LEFT (ic));
2705 etype = getSpec(dtype);
2706 /* if send set is not empty then assign */
2709 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2710 genSend(reverseSet(_G.sendSet));
2712 genSend(_G.sendSet);
2718 /* if we are calling a not _naked function that is not using
2719 the same register bank then we need to save the
2720 destination registers on the stack */
2721 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2722 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2723 !IFFUNC_ISISR (dtype))
2728 /* if caller saves & we have not saved then */
2734 emitcode ("mov", "psw,#0x%02x",
2735 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2739 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2741 if (IFFUNC_CALLEESAVES(dtype))
2743 werror (E_BANKED_WITH_CALLEESAVES);
2747 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2748 OP_SYMBOL (IC_LEFT (ic))->rname :
2749 OP_SYMBOL (IC_LEFT (ic))->name);
2751 emitcode ("mov", "r0,#%s", l);
2752 emitcode ("mov", "r1,#(%s >> 8)", l);
2753 emitcode ("mov", "r2,#(%s >> 16)", l);
2754 emitcode ("lcall", "__sdcc_banked_call");
2759 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2760 OP_SYMBOL (IC_LEFT (ic))->rname :
2761 OP_SYMBOL (IC_LEFT (ic))->name));
2766 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2769 /* if we need assign a result value */
2770 if ((IS_ITEMP (IC_RESULT (ic)) &&
2771 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2772 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2773 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2774 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2775 IS_TRUE_SYMOP (IC_RESULT (ic)))
2779 aopOp (IC_RESULT (ic), ic, FALSE);
2782 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2784 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2787 /* adjust the stack for parameters if required */
2791 if (ic->parmBytes > 3)
2795 emitcode ("push", "acc");
2798 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2799 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2801 emitcode ("mov", "F0,c");
2805 emitcode ("mov", "a,%s", spname);
2806 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2807 emitcode ("mov", "%s,a", spname);
2809 /* unsaveRegisters from xstack needs acc, but */
2810 /* unsaveRegisters from stack needs this popped */
2811 if (accPushed && !options.useXstack)
2813 emitcode ("pop", "acc");
2818 for (i = 0; i < ic->parmBytes; i++)
2819 emitcode ("dec", "%s", spname);
2822 /* if we had saved some registers then unsave them */
2823 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2825 if (accuse && !accPushed && options.useXstack)
2827 /* xstack needs acc, but doesn't touch normal stack */
2828 emitcode ("push", "acc");
2831 unsaveRegisters (ic);
2834 // /* if register bank was saved then pop them */
2836 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2838 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2841 emitcode ("mov", "c,F0");
2843 aopOp (IC_RESULT (ic), ic, FALSE);
2844 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2845 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2849 emitcode ("pop", "acc");
2852 /*-----------------------------------------------------------------*/
2853 /* -10l - generates a call by pointer statement */
2854 /*-----------------------------------------------------------------*/
2856 genPcall (iCode * ic)
2860 symbol *rlbl = newiTempLabel (NULL);
2861 // bool restoreBank=FALSE;
2862 bool swapBanks = FALSE;
2863 bool resultInF0 = FALSE;
2865 D(emitcode("; genPCall",""));
2867 dtype = operandType (IC_LEFT (ic))->next;
2868 etype = getSpec(dtype);
2869 /* if caller saves & we have not saved then */
2873 /* if we are calling a not _naked function that is not using
2874 the same register bank then we need to save the
2875 destination registers on the stack */
2876 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2877 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2878 !IFFUNC_ISISR (dtype))
2880 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2881 // restoreBank=TRUE;
2883 // need caution message to user here
2886 if (IS_LITERAL(etype))
2888 /* if send set is not empty then assign */
2891 genSend(reverseSet(_G.sendSet));
2897 emitcode ("mov", "psw,#0x%02x",
2898 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2901 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2903 if (IFFUNC_CALLEESAVES(dtype))
2905 werror (E_BANKED_WITH_CALLEESAVES);
2909 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2911 emitcode ("mov", "r0,#%s", l);
2912 emitcode ("mov", "r1,#(%s >> 8)", l);
2913 emitcode ("mov", "r2,#(%s >> 16)", l);
2914 emitcode ("lcall", "__sdcc_banked_call");
2919 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2924 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2926 if (IFFUNC_CALLEESAVES(dtype))
2928 werror (E_BANKED_WITH_CALLEESAVES);
2932 aopOp (IC_LEFT (ic), ic, FALSE);
2936 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2937 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2938 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2942 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2943 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2944 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2945 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2948 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2950 /* if send set is not empty then assign */
2953 genSend(reverseSet(_G.sendSet));
2959 emitcode ("mov", "psw,#0x%02x",
2960 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2964 emitcode ("lcall", "__sdcc_banked_call");
2969 /* push the return address on to the stack */
2970 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2971 emitcode ("push", "acc");
2972 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2973 emitcode ("push", "acc");
2975 /* now push the calling address */
2976 aopOp (IC_LEFT (ic), ic, FALSE);
2978 pushSide (IC_LEFT (ic), FPTRSIZE);
2980 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2982 /* if send set is not empty the assign */
2985 genSend(reverseSet(_G.sendSet));
2991 emitcode ("mov", "psw,#0x%02x",
2992 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2996 emitcode ("ret", "");
2997 emitcode ("", "%05d$:", (rlbl->key + 100));
3002 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
3005 /* if we need assign a result value */
3006 if ((IS_ITEMP (IC_RESULT (ic)) &&
3007 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3008 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3009 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3010 IS_TRUE_SYMOP (IC_RESULT (ic)))
3014 aopOp (IC_RESULT (ic), ic, FALSE);
3017 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3019 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3022 /* adjust the stack for parameters if required */
3026 if (ic->parmBytes > 3)
3028 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3029 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3031 emitcode ("mov", "F0,c");
3035 emitcode ("mov", "a,%s", spname);
3036 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3037 emitcode ("mov", "%s,a", spname);
3040 for (i = 0; i < ic->parmBytes; i++)
3041 emitcode ("dec", "%s", spname);
3045 // /* if register bank was saved then unsave them */
3047 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3049 /* if we had saved some registers then unsave them */
3050 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3051 unsaveRegisters (ic);
3053 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3056 emitcode ("mov", "c,F0");
3058 aopOp (IC_RESULT (ic), ic, FALSE);
3059 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3060 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3064 /*-----------------------------------------------------------------*/
3065 /* resultRemat - result is rematerializable */
3066 /*-----------------------------------------------------------------*/
3068 resultRemat (iCode * ic)
3070 if (SKIP_IC (ic) || ic->op == IFX)
3073 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3075 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3076 if (sym->remat && !POINTER_SET (ic))
3083 #if defined(__BORLANDC__) || defined(_MSC_VER)
3084 #define STRCASECMP stricmp
3086 #define STRCASECMP strcasecmp
3089 /*-----------------------------------------------------------------*/
3090 /* inExcludeList - return 1 if the string is in exclude Reg list */
3091 /*-----------------------------------------------------------------*/
3093 regsCmp(void *p1, void *p2)
3095 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3099 inExcludeList (char *s)
3101 const char *p = setFirstItem(options.excludeRegsSet);
3103 if (p == NULL || STRCASECMP(p, "none") == 0)
3107 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3110 /*-----------------------------------------------------------------*/
3111 /* genFunction - generated code for function entry */
3112 /*-----------------------------------------------------------------*/
3114 genFunction (iCode * ic)
3116 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3118 bool switchedPSW = FALSE;
3119 int calleesaves_saved_register = -1;
3120 int stackAdjust = sym->stack;
3121 int accIsFree = sym->recvSize < 4;
3122 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3123 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3126 /* create the function header */
3127 emitcode (";", "-----------------------------------------");
3128 emitcode (";", " function %s", sym->name);
3129 emitcode (";", "-----------------------------------------");
3131 emitcode ("", "%s:", sym->rname);
3132 ftype = operandType (IC_LEFT (ic));
3133 _G.currentFunc = sym;
3135 if (IFFUNC_ISNAKED(ftype))
3137 emitcode(";", "naked function: no prologue.");
3141 /* here we need to generate the equates for the
3142 register bank if required */
3143 if (FUNC_REGBANK (ftype) != rbank)
3147 rbank = FUNC_REGBANK (ftype);
3148 for (i = 0; i < mcs51_nRegs; i++)
3150 if (regs8051[i].type != REG_BIT)
3152 if (strcmp (regs8051[i].base, "0") == 0)
3153 emitcode ("", "%s = 0x%02x",
3155 8 * rbank + regs8051[i].offset);
3157 emitcode ("", "%s = %s + 0x%02x",
3160 8 * rbank + regs8051[i].offset);
3165 /* if this is an interrupt service routine then
3166 save acc, b, dpl, dph */
3167 if (IFFUNC_ISISR (sym->type))
3170 if (!inExcludeList ("acc"))
3171 emitcode ("push", "acc");
3172 if (!inExcludeList ("b"))
3173 emitcode ("push", "b");
3174 if (!inExcludeList ("dpl"))
3175 emitcode ("push", "dpl");
3176 if (!inExcludeList ("dph"))
3177 emitcode ("push", "dph");
3178 /* if this isr has no bank i.e. is going to
3179 run with bank 0 , then we need to save more
3181 if (!FUNC_REGBANK (sym->type))
3184 /* if this function does not call any other
3185 function then we can be economical and
3186 save only those registers that are used */
3187 if (!IFFUNC_HASFCALL(sym->type))
3191 /* if any registers used */
3194 bool bits_pushed = FALSE;
3195 /* save the registers used */
3196 for (i = 0; i < sym->regsUsed->size; i++)
3198 if (bitVectBitValue (sym->regsUsed, i))
3199 bits_pushed = pushReg (i, bits_pushed);
3206 /* this function has a function call. We cannot
3207 determines register usage so we will have to push the
3209 saveRBank (0, ic, FALSE);
3210 if (options.parms_in_bank1) {
3212 for (i=0; i < 8 ; i++ ) {
3213 emitcode ("push","%s",rb1regs[i]);
3220 /* This ISR uses a non-zero bank.
3222 * We assume that the bank is available for our
3225 * However, if this ISR calls a function which uses some
3226 * other bank, we must save that bank entirely.
3228 unsigned long banksToSave = 0;
3230 if (IFFUNC_HASFCALL(sym->type))
3233 #define MAX_REGISTER_BANKS 4
3238 for (i = ic; i; i = i->next)
3240 if (i->op == ENDFUNCTION)
3242 /* we got to the end OK. */
3250 dtype = operandType (IC_LEFT(i));
3252 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3254 /* Mark this bank for saving. */
3255 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3257 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3261 banksToSave |= (1 << FUNC_REGBANK(dtype));
3264 /* And note that we don't need to do it in
3272 /* This is a mess; we have no idea what
3273 * register bank the called function might
3276 * The only thing I can think of to do is
3277 * throw a warning and hope.
3279 werror(W_FUNCPTR_IN_USING_ISR);
3283 if (banksToSave && options.useXstack)
3285 /* Since we aren't passing it an ic,
3286 * saveRBank will assume r0 is available to abuse.
3288 * So switch to our (trashable) bank now, so
3289 * the caller's R0 isn't trashed.
3291 emitcode ("push", "psw");
3292 emitcode ("mov", "psw,#0x%02x",
3293 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3297 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3299 if (banksToSave & (1 << ix))
3301 saveRBank(ix, NULL, FALSE);
3305 // TODO: this needs a closer look
3306 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3309 /* Set the register bank to the desired value if nothing else */
3310 /* has done so yet. */
3313 emitcode ("push", "psw");
3314 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3319 /* This is a non-ISR function. The caller has already switched register */
3320 /* banks, if necessary, so just handle the callee-saves option. */
3322 /* if callee-save to be used for this function
3323 then save the registers being used in this function */
3324 if (IFFUNC_CALLEESAVES(sym->type))
3328 /* if any registers used */
3331 bool bits_pushed = FALSE;
3332 /* save the registers used */
3333 for (i = 0; i < sym->regsUsed->size; i++)
3335 if (bitVectBitValue (sym->regsUsed, i))
3337 /* remember one saved register for later usage */
3338 if (calleesaves_saved_register < 0)
3339 calleesaves_saved_register = i;
3340 bits_pushed = pushReg (i, bits_pushed);
3351 if (options.useXstack)
3353 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3355 emitcode ("mov", "r0,%s", spname);
3356 emitcode ("inc", "%s", spname);
3357 emitcode ("xch", "a,_bpx");
3358 emitcode ("movx", "@r0,a");
3359 emitcode ("inc", "r0");
3360 emitcode ("mov", "a,r0");
3361 emitcode ("xch", "a,_bpx");
3365 emitcode ("push", "_bp"); /* save the callers stack */
3366 emitcode ("mov", "_bp,sp");
3371 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3373 /* set up the stack */
3374 emitcode ("push", "_bp"); /* save the callers stack */
3375 emitcode ("mov", "_bp,sp");
3380 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3381 /* before setting up the stack frame completely. */
3382 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3384 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3388 if (rsym && rsym->regType == REG_CND)
3390 if (rsym && (rsym->accuse || rsym->ruonly))
3392 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3393 rsym = rsym->usl.spillLoc;
3396 /* If the RECEIVE operand immediately spills to the first entry on the */
3397 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3398 /* rather than the usual @r0/r1 machinations. */
3399 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3403 _G.current_iCode = ric;
3404 D(emitcode ("; genReceive",""));
3405 for (ofs=0; ofs < sym->recvSize; ofs++)
3407 if (!strcmp (fReturn[ofs], "a"))
3408 emitcode ("push", "acc");
3410 emitcode ("push", fReturn[ofs]);
3412 stackAdjust -= sym->recvSize;
3415 assert (stackAdjust>=0);
3418 _G.current_iCode = ic;
3422 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3423 /* to free up the accumulator. */
3424 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3428 _G.current_iCode = ric;
3429 D(emitcode ("; genReceive",""));
3430 for (ofs=0; ofs < sym->recvSize; ofs++)
3432 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3434 _G.current_iCode = ic;
3440 /* adjust the stack for the function */
3443 int i = stackAdjust;
3445 werror (W_STACK_OVERFLOW, sym->name);
3447 if (i > 3 && accIsFree)
3449 emitcode ("mov", "a,sp");
3450 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3451 emitcode ("mov", "sp,a");
3455 /* The accumulator is not free, so we will need another register */
3456 /* to clobber. No need to worry about a possible conflict with */
3457 /* the above early RECEIVE optimizations since they would have */
3458 /* freed the accumulator if they were generated. */
3460 if (IFFUNC_CALLEESAVES(sym->type))
3462 /* if it's a callee-saves function we need a saved register */
3463 if (calleesaves_saved_register >= 0)
3465 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3466 emitcode ("mov", "a,sp");
3467 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3468 emitcode ("mov", "sp,a");
3469 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3472 /* do it the hard way */
3474 emitcode ("inc", "sp");
3478 /* not callee-saves, we can clobber r0 */
3479 emitcode ("mov", "r0,a");
3480 emitcode ("mov", "a,sp");
3481 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3482 emitcode ("mov", "sp,a");
3483 emitcode ("mov", "a,r0");
3488 emitcode ("inc", "sp");
3493 char i = ((char) sym->xstack & 0xff);
3495 if (i > 3 && accIsFree)
3497 emitcode ("mov", "a,_spx");
3498 emitcode ("add", "a,#0x%02x", i);
3499 emitcode ("mov", "_spx,a");
3503 emitcode ("push", "acc");
3504 emitcode ("mov", "a,_spx");
3505 emitcode ("add", "a,#0x%02x", i);
3506 emitcode ("mov", "_spx,a");
3507 emitcode ("pop", "acc");
3512 emitcode ("inc", "_spx");
3516 /* if critical function then turn interrupts off */
3517 if (IFFUNC_ISCRITICAL (ftype))
3519 symbol *tlbl = newiTempLabel (NULL);
3520 emitcode ("setb", "c");
3521 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3522 emitcode ("clr", "c");
3523 emitcode ("", "%05d$:", (tlbl->key + 100));
3524 emitcode ("push", "psw"); /* save old ea via c in psw */
3528 /*-----------------------------------------------------------------*/
3529 /* genEndFunction - generates epilogue for functions */
3530 /*-----------------------------------------------------------------*/
3532 genEndFunction (iCode * ic)
3534 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3535 lineNode *lnp = lineCurr;
3537 bitVect *regsUsedPrologue;
3538 bitVect *regsUnneeded;
3541 _G.currentFunc = NULL;
3542 if (IFFUNC_ISNAKED(sym->type))
3544 emitcode(";", "naked function: no epilogue.");
3545 if (options.debug && currFunc)
3546 debugFile->writeEndFunction (currFunc, ic, 0);
3550 if (IFFUNC_ISCRITICAL (sym->type))
3552 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3554 emitcode ("rlc", "a"); /* save c in a */
3555 emitcode ("pop", "psw"); /* restore ea via c in psw */
3556 emitcode ("mov", "ea,c");
3557 emitcode ("rrc", "a"); /* restore c from a */
3561 emitcode ("pop", "psw"); /* restore ea via c in psw */
3562 emitcode ("mov", "ea,c");
3566 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3568 if (options.useXstack)
3572 emitcode ("mov", "sp,_bp");
3573 emitcode ("pop", "_bp");
3575 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3577 emitcode ("xch", "a,_bpx");
3578 emitcode ("mov", "r0,a");
3579 emitcode ("dec", "r0");
3580 emitcode ("movx", "a,@r0");
3581 emitcode ("xch", "a,_bpx");
3582 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3585 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3587 emitcode ("mov", "sp,_bp");
3588 emitcode ("pop", "_bp");
3592 /* restore the register bank */
3593 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3595 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3596 || !options.useXstack)
3598 /* Special case of ISR using non-zero bank with useXstack
3601 emitcode ("pop", "psw");
3605 if (IFFUNC_ISISR (sym->type))
3608 /* now we need to restore the registers */
3609 /* if this isr has no bank i.e. is going to
3610 run with bank 0 , then we need to save more
3612 if (!FUNC_REGBANK (sym->type))
3614 /* if this function does not call any other
3615 function then we can be economical and
3616 save only those registers that are used */
3617 if (!IFFUNC_HASFCALL(sym->type))
3621 /* if any registers used */
3624 bool bits_popped = FALSE;
3625 /* save the registers used */
3626 for (i = sym->regsUsed->size; i >= 0; i--)
3628 if (bitVectBitValue (sym->regsUsed, i))
3629 bits_popped = popReg (i, bits_popped);
3635 if (options.parms_in_bank1) {
3637 for (i = 7 ; i >= 0 ; i-- ) {
3638 emitcode ("pop","%s",rb1regs[i]);
3641 /* this function has a function call cannot
3642 determines register usage so we will have to pop the
3644 unsaveRBank (0, ic, FALSE);
3649 /* This ISR uses a non-zero bank.
3651 * Restore any register banks saved by genFunction
3654 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3657 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3659 if (savedBanks & (1 << ix))
3661 unsaveRBank(ix, NULL, FALSE);
3665 if (options.useXstack)
3667 /* Restore bank AFTER calling unsaveRBank,
3668 * since it can trash r0.
3670 emitcode ("pop", "psw");
3674 if (!inExcludeList ("dph"))
3675 emitcode ("pop", "dph");
3676 if (!inExcludeList ("dpl"))
3677 emitcode ("pop", "dpl");
3678 if (!inExcludeList ("b"))
3679 emitcode ("pop", "b");
3680 if (!inExcludeList ("acc"))
3681 emitcode ("pop", "acc");
3683 /* if debug then send end of function */
3684 if (options.debug && currFunc)
3686 debugFile->writeEndFunction (currFunc, ic, 1);
3689 emitcode ("reti", "");
3693 if (IFFUNC_CALLEESAVES(sym->type))
3697 /* if any registers used */
3700 /* save the registers used */
3701 for (i = sym->regsUsed->size; i >= 0; i--)
3703 if (bitVectBitValue (sym->regsUsed, i) ||
3704 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3705 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3708 else if (mcs51_ptrRegReq)
3710 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3711 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3716 /* if debug then send end of function */
3717 if (options.debug && currFunc)
3719 debugFile->writeEndFunction (currFunc, ic, 1);
3722 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3724 emitcode ("ljmp", "__sdcc_banked_ret");
3728 emitcode ("ret", "");
3732 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3735 /* If this was an interrupt handler using bank 0 that called another */
3736 /* function, then all registers must be saved; nothing to optimized. */
3737 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3738 && !FUNC_REGBANK(sym->type))
3741 /* There are no push/pops to optimize if not callee-saves or ISR */
3742 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3745 /* If there were stack parameters, we cannot optimize without also */
3746 /* fixing all of the stack offsets; this is too dificult to consider. */
3747 if (FUNC_HASSTACKPARM(sym->type))
3750 /* Compute the registers actually used */
3751 regsUsed = newBitVect (mcs51_nRegs);
3752 regsUsedPrologue = newBitVect (mcs51_nRegs);
3755 if (lnp->ic && lnp->ic->op == FUNCTION)
3756 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3758 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3760 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3761 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3768 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3769 && !bitVectBitValue (regsUsed, CND_IDX))
3771 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3772 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3773 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3774 bitVectUnSetBit (regsUsed, CND_IDX);
3777 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3779 /* If this was an interrupt handler that called another function */
3780 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3781 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3783 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3784 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3785 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3786 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3787 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3790 /* Remove the unneeded push/pops */
3791 regsUnneeded = newBitVect (mcs51_nRegs);
3794 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3796 if (!strncmp(lnp->line, "push", 4))
3798 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3799 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3801 connectLine (lnp->prev, lnp->next);
3802 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3805 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3807 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3808 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3810 connectLine (lnp->prev, lnp->next);
3811 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3818 for (idx = 0; idx < regsUnneeded->size; idx++)
3819 if (bitVectBitValue (regsUnneeded, idx))
3820 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3822 freeBitVect (regsUnneeded);
3823 freeBitVect (regsUsed);
3824 freeBitVect (regsUsedPrologue);
3827 /*-----------------------------------------------------------------*/
3828 /* genRet - generate code for return statement */
3829 /*-----------------------------------------------------------------*/
3833 int size, offset = 0, pushed = 0;
3835 D(emitcode ("; genRet",""));
3837 /* if we have no return value then
3838 just generate the "ret" */
3842 /* we have something to return then
3843 move the return value into place */
3844 aopOp (IC_LEFT (ic), ic, FALSE);
3845 size = AOP_SIZE (IC_LEFT (ic));
3848 if (IS_BIT(_G.currentFunc->etype))
3850 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3857 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3860 l = aopGet (IC_LEFT (ic), offset++,
3862 emitcode ("push", "%s", l);
3867 l = aopGet (IC_LEFT (ic), offset,
3869 if (strcmp (fReturn[offset], l))
3870 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3877 if (strcmp (fReturn[pushed], "a"))
3878 emitcode ("pop", fReturn[pushed]);
3880 emitcode ("pop", "acc");
3882 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3885 /* generate a jump to the return label
3886 if the next is not the return statement */
3887 if (!(ic->next && ic->next->op == LABEL &&
3888 IC_LABEL (ic->next) == returnLabel))
3890 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3894 /*-----------------------------------------------------------------*/
3895 /* genLabel - generates a label */
3896 /*-----------------------------------------------------------------*/
3898 genLabel (iCode * ic)
3900 /* special case never generate */
3901 if (IC_LABEL (ic) == entryLabel)
3904 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3907 /*-----------------------------------------------------------------*/
3908 /* genGoto - generates a ljmp */
3909 /*-----------------------------------------------------------------*/
3911 genGoto (iCode * ic)
3913 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3916 /*-----------------------------------------------------------------*/
3917 /* findLabelBackwards: walks back through the iCode chain looking */
3918 /* for the given label. Returns number of iCode instructions */
3919 /* between that label and given ic. */
3920 /* Returns zero if label not found. */
3921 /*-----------------------------------------------------------------*/
3923 findLabelBackwards (iCode * ic, int key)
3932 /* If we have any pushes or pops, we cannot predict the distance.
3933 I don't like this at all, this should be dealt with in the
3935 if (ic->op == IPUSH || ic->op == IPOP) {
3939 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3948 /*-----------------------------------------------------------------*/
3949 /* genPlusIncr :- does addition with increment if possible */
3950 /*-----------------------------------------------------------------*/
3952 genPlusIncr (iCode * ic)
3954 unsigned int icount;
3955 unsigned int size = getDataSize (IC_RESULT (ic));
3957 /* will try to generate an increment */
3958 /* if the right side is not a literal
3960 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3963 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3965 D(emitcode ("; genPlusIncr",""));
3967 /* if increment >=16 bits in register or direct space */
3968 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3969 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3970 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3978 /* If the next instruction is a goto and the goto target
3979 * is < 10 instructions previous to this, we can generate
3980 * jumps straight to that target.
3982 if (ic->next && ic->next->op == GOTO
3983 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3984 && labelRange <= 10)
3986 emitcode (";", "tail increment optimized");
3987 tlbl = IC_LABEL (ic->next);
3992 tlbl = newiTempLabel (NULL);
3995 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3996 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3997 IS_AOP_PREG (IC_RESULT (ic)))
3998 emitcode ("cjne", "%s,#0x00,%05d$",
3999 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4003 emitcode ("clr", "a");
4004 emitcode ("cjne", "a,%s,%05d$",
4005 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4009 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4012 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4013 IS_AOP_PREG (IC_RESULT (ic)))
4014 emitcode ("cjne", "%s,#0x00,%05d$",
4015 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4018 emitcode ("cjne", "a,%s,%05d$",
4019 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4022 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4026 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4027 IS_AOP_PREG (IC_RESULT (ic)))
4028 emitcode ("cjne", "%s,#0x00,%05d$",
4029 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4033 emitcode ("cjne", "a,%s,%05d$",
4034 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4037 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4042 emitcode ("", "%05d$:", tlbl->key + 100);
4047 /* if result is dptr */
4048 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4049 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4050 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4051 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4053 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4059 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4062 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
4063 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
4065 emitcode ("inc", "dptr");
4070 /* if the literal value of the right hand side
4071 is greater than 4 then it is not worth it */
4075 /* if the sizes are greater than 1 then we cannot */
4076 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4077 AOP_SIZE (IC_LEFT (ic)) > 1)
4080 /* we can if the aops of the left & result match or
4081 if they are in registers and the registers are the
4083 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4088 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4089 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4090 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4096 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4105 /*-----------------------------------------------------------------*/
4106 /* outBitAcc - output a bit in acc */
4107 /*-----------------------------------------------------------------*/
4109 outBitAcc (operand * result)
4111 symbol *tlbl = newiTempLabel (NULL);
4112 /* if the result is a bit */
4113 if (AOP_TYPE (result) == AOP_CRY)
4115 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4119 emitcode ("jz", "%05d$", tlbl->key + 100);
4120 emitcode ("mov", "a,%s", one);
4121 emitcode ("", "%05d$:", tlbl->key + 100);
4126 /*-----------------------------------------------------------------*/
4127 /* genPlusBits - generates code for addition of two bits */
4128 /*-----------------------------------------------------------------*/
4130 genPlusBits (iCode * ic)
4132 D(emitcode ("; genPlusBits",""));
4134 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4136 symbol *lbl = newiTempLabel (NULL);
4137 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4138 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4139 emitcode ("cpl", "c");
4140 emitcode ("", "%05d$:", (lbl->key + 100));
4141 outBitC (IC_RESULT (ic));
4145 emitcode ("clr", "a");
4146 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4147 emitcode ("rlc", "a");
4148 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4149 emitcode ("addc", "a,#0x00");
4150 outAcc (IC_RESULT (ic));
4155 /* This is the original version of this code.
4157 * This is being kept around for reference,
4158 * because I am not entirely sure I got it right...
4161 adjustArithmeticResult (iCode * ic)
4163 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4164 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4165 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4166 aopPut (IC_RESULT (ic),
4167 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4169 isOperandVolatile (IC_RESULT (ic), FALSE));
4171 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4172 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4173 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4174 aopPut (IC_RESULT (ic),
4175 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4177 isOperandVolatile (IC_RESULT (ic), FALSE));
4179 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4180 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4181 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4182 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4183 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4186 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4187 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4191 /* This is the pure and virtuous version of this code.
4192 * I'm pretty certain it's right, but not enough to toss the old
4196 adjustArithmeticResult (iCode * ic)
4198 if (opIsGptr (IC_RESULT (ic)) &&
4199 opIsGptr (IC_LEFT (ic)) &&
4200 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4202 aopPut (IC_RESULT (ic),
4203 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4205 isOperandVolatile (IC_RESULT (ic), FALSE));
4208 if (opIsGptr (IC_RESULT (ic)) &&
4209 opIsGptr (IC_RIGHT (ic)) &&
4210 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4212 aopPut (IC_RESULT (ic),
4213 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4215 isOperandVolatile (IC_RESULT (ic), FALSE));
4218 if (opIsGptr (IC_RESULT (ic)) &&
4219 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4220 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4221 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4222 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4225 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4226 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4231 /*-----------------------------------------------------------------*/
4232 /* genPlus - generates code for addition */
4233 /*-----------------------------------------------------------------*/
4235 genPlus (iCode * ic)
4237 int size, offset = 0;
4240 bool swappedLR = FALSE;
4241 operand *leftOp, *rightOp;
4244 /* special cases :- */
4246 D(emitcode ("; genPlus",""));
4248 aopOp (IC_LEFT (ic), ic, FALSE);
4249 aopOp (IC_RIGHT (ic), ic, FALSE);
4250 aopOp (IC_RESULT (ic), ic, TRUE);
4252 /* if literal, literal on the right or
4253 if left requires ACC or right is already
4255 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4256 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4257 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4259 operand *t = IC_RIGHT (ic);
4260 IC_RIGHT (ic) = IC_LEFT (ic);
4265 /* if both left & right are in bit
4267 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4268 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4274 /* if left in bit space & right literal */
4275 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4276 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4278 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4279 /* if result in bit space */
4280 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4282 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4283 emitcode ("cpl", "c");
4284 outBitC (IC_RESULT (ic));
4288 size = getDataSize (IC_RESULT (ic));
4291 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4292 emitcode ("addc", "a,#00");
4293 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4299 /* if I can do an increment instead
4300 of add then GOOD for ME */
4301 if (genPlusIncr (ic) == TRUE)
4304 size = getDataSize (IC_RESULT (ic));
4305 leftOp = IC_LEFT(ic);
4306 rightOp = IC_RIGHT(ic);
4309 /* if this is an add for an array access
4310 at a 256 byte boundary */
4312 && AOP_TYPE (op) == AOP_IMMD
4314 && IS_SPEC (OP_SYM_ETYPE (op))
4315 && SPEC_ABSA (OP_SYM_ETYPE (op))
4316 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4319 D(emitcode ("; genPlus aligned array",""));
4320 aopPut (IC_RESULT (ic),
4321 aopGet (rightOp, 0, FALSE, FALSE),
4323 isOperandVolatile (IC_RESULT (ic), FALSE));
4325 if( 1 == getDataSize (IC_RIGHT (ic)) )
4327 aopPut (IC_RESULT (ic),
4328 aopGet (leftOp, 1, FALSE, FALSE),
4330 isOperandVolatile (IC_RESULT (ic), FALSE));
4334 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4335 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4336 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4341 /* if the lower bytes of a literal are zero skip the addition */
4342 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4344 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4345 (skip_bytes+1 < size))
4350 D(emitcode ("; genPlus shortcut",""));
4355 if( offset >= skip_bytes )
4357 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4360 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4362 emitcode("xch", "a,b");
4363 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4364 emitcode (add, "a,b");
4367 else if (aopGetUsesAcc (leftOp, offset))
4369 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4370 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4374 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4375 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4377 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4378 add = "addc"; /* further adds must propagate carry */
4382 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4383 isOperandVolatile (IC_RESULT (ic), FALSE))
4386 aopPut (IC_RESULT (ic),
4387 aopGet (leftOp, offset, FALSE, FALSE),
4389 isOperandVolatile (IC_RESULT (ic), FALSE));
4395 adjustArithmeticResult (ic);
4398 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4401 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4402 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4406 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4407 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4411 /*-----------------------------------------------------------------*/
4412 /* genMinusDec :- does subtraction with decrement if possible */
4413 /*-----------------------------------------------------------------*/
4415 genMinusDec (iCode * ic)
4417 unsigned int icount;
4418 unsigned int size = getDataSize (IC_RESULT (ic));
4420 /* will try to generate an increment */
4421 /* if the right side is not a literal
4423 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4426 /* if the literal value of the right hand side
4427 is greater than 4 then it is not worth it */
4428 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4431 D(emitcode ("; genMinusDec",""));
4433 /* if decrement >=16 bits in register or direct space */
4434 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4435 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4443 /* If the next instruction is a goto and the goto target
4444 * is <= 10 instructions previous to this, we can generate
4445 * jumps straight to that target.
4447 if (ic->next && ic->next->op == GOTO
4448 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4449 && labelRange <= 10)
4451 emitcode (";", "tail decrement optimized");
4452 tlbl = IC_LABEL (ic->next);
4457 tlbl = newiTempLabel (NULL);
4461 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4462 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4463 IS_AOP_PREG (IC_RESULT (ic)))
4464 emitcode ("cjne", "%s,#0xff,%05d$"
4465 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4469 emitcode ("mov", "a,#0xff");
4470 emitcode ("cjne", "a,%s,%05d$"
4471 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4474 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4477 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4478 IS_AOP_PREG (IC_RESULT (ic)))
4479 emitcode ("cjne", "%s,#0xff,%05d$"
4480 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4484 emitcode ("cjne", "a,%s,%05d$"
4485 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4488 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4492 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4493 IS_AOP_PREG (IC_RESULT (ic)))
4494 emitcode ("cjne", "%s,#0xff,%05d$"
4495 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4499 emitcode ("cjne", "a,%s,%05d$"
4500 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4503 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4507 emitcode ("", "%05d$:", tlbl->key + 100);
4512 /* if the sizes are greater than 1 then we cannot */
4513 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4514 AOP_SIZE (IC_LEFT (ic)) > 1)
4517 /* we can if the aops of the left & result match or
4518 if they are in registers and the registers are the
4520 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4524 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4526 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4531 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4535 emitcode ("dec", "%s", l);
4537 if (AOP_NEEDSACC (IC_RESULT (ic)))
4538 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4546 /*-----------------------------------------------------------------*/
4547 /* addSign - complete with sign */
4548 /*-----------------------------------------------------------------*/
4550 addSign (operand * result, int offset, int sign)
4552 int size = (getDataSize (result) - offset);
4557 emitcode ("rlc", "a");
4558 emitcode ("subb", "a,acc");
4560 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4564 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4568 /*-----------------------------------------------------------------*/
4569 /* genMinusBits - generates code for subtraction of two bits */
4570 /*-----------------------------------------------------------------*/
4572 genMinusBits (iCode * ic)
4574 symbol *lbl = newiTempLabel (NULL);
4576 D(emitcode ("; genMinusBits",""));
4578 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4580 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4581 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4582 emitcode ("cpl", "c");
4583 emitcode ("", "%05d$:", (lbl->key + 100));
4584 outBitC (IC_RESULT (ic));
4588 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4589 emitcode ("subb", "a,acc");
4590 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4591 emitcode ("inc", "a");
4592 emitcode ("", "%05d$:", (lbl->key + 100));
4593 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4594 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4598 /*-----------------------------------------------------------------*/
4599 /* genMinus - generates code for subtraction */
4600 /*-----------------------------------------------------------------*/
4602 genMinus (iCode * ic)
4604 int size, offset = 0;
4606 D(emitcode ("; genMinus",""));
4608 aopOp (IC_LEFT (ic), ic, FALSE);
4609 aopOp (IC_RIGHT (ic), ic, FALSE);
4610 aopOp (IC_RESULT (ic), ic, TRUE);
4612 /* special cases :- */
4613 /* if both left & right are in bit space */
4614 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4615 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4621 /* if I can do an decrement instead
4622 of subtract then GOOD for ME */
4623 if (genMinusDec (ic) == TRUE)
4626 size = getDataSize (IC_RESULT (ic));
4628 /* if literal, add a,#-lit, else normal subb */
4629 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4631 unsigned long lit = 0L;
4632 bool useCarry = FALSE;
4634 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4639 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4641 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4642 if (!offset && !size && lit== (unsigned long) -1)
4644 emitcode ("dec", "a");
4648 /* first add without previous c */
4649 emitcode ("add", "a,#0x%02x",
4650 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4655 emitcode ("addc", "a,#0x%02x",
4656 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4658 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4662 /* no need to add zeroes */
4663 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4665 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4666 offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4674 operand *leftOp, *rightOp;
4676 leftOp = IC_LEFT(ic);
4677 rightOp = IC_RIGHT(ic);
4681 if (aopGetUsesAcc(rightOp, offset)) {
4682 if (aopGetUsesAcc(leftOp, offset)) {
4685 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4687 emitcode ("mov", "b,a");
4690 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4691 emitcode ("subb", "a,b");
4694 /* reverse subtraction with 2's complement */
4696 emitcode( "setb", "c");
4698 emitcode( "cpl", "c");
4699 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4700 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4701 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4702 emitcode("cpl", "a");
4703 if (size) /* skip if last byte */
4704 emitcode( "cpl", "c");
4707 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4710 emitcode ("subb", "a,%s",
4711 aopGet(rightOp, offset, FALSE, TRUE));
4714 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4719 adjustArithmeticResult (ic);
4722 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4723 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4724 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4728 /*-----------------------------------------------------------------*/
4729 /* genMultbits :- multiplication of bits */
4730 /*-----------------------------------------------------------------*/
4732 genMultbits (operand * left,
4736 D(emitcode ("; genMultbits",""));
4738 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4739 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4743 /*-----------------------------------------------------------------*/
4744 /* genMultOneByte : 8*8=8/16 bit multiplication */
4745 /*-----------------------------------------------------------------*/
4747 genMultOneByte (operand * left,
4752 int size = AOP_SIZE (result);
4753 bool runtimeSign, compiletimeSign;
4754 bool lUnsigned, rUnsigned, pushedB;
4756 D(emitcode ("; genMultOneByte",""));
4758 if (size < 1 || size > 2)
4760 /* this should never happen */
4761 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4762 AOP_SIZE(result), __FILE__, lineno);
4766 /* (if two literals: the value is computed before) */
4767 /* if one literal, literal on the right */
4768 if (AOP_TYPE (left) == AOP_LIT)
4773 /* emitcode (";", "swapped left and right"); */
4775 /* if no literal, unsigned on the right: shorter code */
4776 if ( AOP_TYPE (right) != AOP_LIT
4777 && SPEC_USIGN (getSpec (operandType (left))))
4784 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4785 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4789 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4790 no need to take care about the signedness! */
4791 || (lUnsigned && rUnsigned))
4793 /* just an unsigned 8 * 8 = 8 multiply
4795 /* emitcode (";","unsigned"); */
4796 /* TODO: check for accumulator clash between left & right aops? */
4798 if (AOP_TYPE (right) == AOP_LIT)
4800 /* moving to accumulator first helps peepholes */
4801 MOVA (aopGet (left, 0, FALSE, FALSE));
4802 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4806 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4807 MOVA (aopGet (left, 0, FALSE, FALSE));
4810 emitcode ("mul", "ab");
4811 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4813 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4819 /* we have to do a signed multiply */
4820 /* emitcode (";", "signed"); */
4822 /* now sign adjust for both left & right */
4824 /* let's see what's needed: */
4825 /* apply negative sign during runtime */
4826 runtimeSign = FALSE;
4827 /* negative sign from literals */
4828 compiletimeSign = FALSE;
4832 if (AOP_TYPE(left) == AOP_LIT)
4834 /* signed literal */
4835 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4837 compiletimeSign = TRUE;
4840 /* signed but not literal */
4846 if (AOP_TYPE(right) == AOP_LIT)
4848 /* signed literal */
4849 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4851 compiletimeSign ^= TRUE;
4854 /* signed but not literal */
4858 /* initialize F0, which stores the runtime sign */
4861 if (compiletimeSign)
4862 emitcode ("setb", "F0"); /* set sign flag */
4864 emitcode ("clr", "F0"); /* reset sign flag */
4867 /* save the signs of the operands */
4868 if (AOP_TYPE(right) == AOP_LIT)
4870 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4872 if (!rUnsigned && val < 0)
4873 emitcode ("mov", "b,#0x%02x", -val);
4875 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4877 else /* ! literal */
4879 if (rUnsigned) /* emitcode (";", "signed"); */
4881 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4884 MOVA (aopGet (right, 0, FALSE, FALSE));
4885 lbl = newiTempLabel (NULL);
4886 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4887 emitcode ("cpl", "F0"); /* complement sign flag */
4888 emitcode ("cpl", "a"); /* 2's complement */
4889 emitcode ("inc", "a");
4890 emitcode ("", "%05d$:", (lbl->key + 100));
4891 emitcode ("mov", "b,a");
4895 if (AOP_TYPE(left) == AOP_LIT)
4897 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4899 if (!lUnsigned && val < 0)
4900 emitcode ("mov", "a,#0x%02x", -val);
4902 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4904 else /* ! literal */
4906 MOVA (aopGet (left, 0, FALSE, FALSE));
4910 lbl = newiTempLabel (NULL);
4911 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4912 emitcode ("cpl", "F0"); /* complement sign flag */
4913 emitcode ("cpl", "a"); /* 2's complement */
4914 emitcode ("inc", "a");
4915 emitcode ("", "%05d$:", (lbl->key + 100));
4919 /* now the multiplication */
4920 emitcode ("mul", "ab");
4921 if (runtimeSign || compiletimeSign)
4923 lbl = newiTempLabel (NULL);
4925 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4926 emitcode ("cpl", "a"); /* lsb 2's complement */
4928 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4931 emitcode ("add", "a,#1"); /* this sets carry flag */
4932 emitcode ("xch", "a,b");
4933 emitcode ("cpl", "a"); /* msb 2's complement */
4934 emitcode ("addc", "a,#0");
4935 emitcode ("xch", "a,b");
4937 emitcode ("", "%05d$:", (lbl->key + 100));
4939 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4941 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4946 /*-----------------------------------------------------------------*/
4947 /* genMult - generates code for multiplication */
4948 /*-----------------------------------------------------------------*/
4950 genMult (iCode * ic)
4952 operand *left = IC_LEFT (ic);
4953 operand *right = IC_RIGHT (ic);
4954 operand *result = IC_RESULT (ic);
4956 D(emitcode ("; genMult",""));
4958 /* assign the asmops */
4959 aopOp (left, ic, FALSE);
4960 aopOp (right, ic, FALSE);
4961 aopOp (result, ic, TRUE);
4963 /* special cases first */
4965 if (AOP_TYPE (left) == AOP_CRY &&
4966 AOP_TYPE (right) == AOP_CRY)
4968 genMultbits (left, right, result);
4972 /* if both are of size == 1 */
4973 #if 0 // one of them can be a sloc shared with the result
4974 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4976 if (getSize(operandType(left)) == 1 &&
4977 getSize(operandType(right)) == 1)
4980 genMultOneByte (left, right, result);
4984 /* should have been converted to function call */
4985 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4986 getSize(OP_SYMBOL(right)->type));
4990 freeAsmop (result, NULL, ic, TRUE);
4991 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4992 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4995 /*-----------------------------------------------------------------*/
4996 /* genDivbits :- division of bits */
4997 /*-----------------------------------------------------------------*/
4999 genDivbits (operand * left,
5006 D(emitcode ("; genDivbits",""));
5010 /* the result must be bit */
5011 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5012 l = aopGet (left, 0, FALSE, FALSE);
5016 emitcode ("div", "ab");
5017 emitcode ("rrc", "a");
5021 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5024 /*-----------------------------------------------------------------*/
5025 /* genDivOneByte : 8 bit division */
5026 /*-----------------------------------------------------------------*/
5028 genDivOneByte (operand * left,
5032 bool lUnsigned, rUnsigned, pushedB;
5033 bool runtimeSign, compiletimeSign;
5034 bool accuse = FALSE;
5035 bool pushedA = FALSE;
5039 D(emitcode ("; genDivOneByte",""));
5041 /* Why is it necessary that genDivOneByte() can return an int result?
5044 volatile unsigned char uc;
5045 volatile signed char sc1, sc2;
5058 In all cases a one byte result would overflow, the following cast to int
5059 would return the wrong result.
5061 Two possible solution:
5062 a) cast operands to int, if ((unsigned) / (signed)) or
5063 ((signed) / (signed))
5064 b) return an 16 bit signed int; this is what we're doing here!
5067 size = AOP_SIZE (result) - 1;
5069 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5070 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5074 /* signed or unsigned */
5075 if (lUnsigned && rUnsigned)
5077 /* unsigned is easy */
5078 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5079 MOVA (aopGet (left, 0, FALSE, FALSE));
5080 emitcode ("div", "ab");
5081 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5083 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5089 /* signed is a little bit more difficult */
5091 /* now sign adjust for both left & right */
5093 /* let's see what's needed: */
5094 /* apply negative sign during runtime */
5095 runtimeSign = FALSE;
5096 /* negative sign from literals */
5097 compiletimeSign = FALSE;
5101 if (AOP_TYPE(left) == AOP_LIT)
5103 /* signed literal */
5104 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5106 compiletimeSign = TRUE;
5109 /* signed but not literal */
5115 if (AOP_TYPE(right) == AOP_LIT)
5117 /* signed literal */
5118 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5120 compiletimeSign ^= TRUE;
5123 /* signed but not literal */
5127 /* initialize F0, which stores the runtime sign */
5130 if (compiletimeSign)
5131 emitcode ("setb", "F0"); /* set sign flag */
5133 emitcode ("clr", "F0"); /* reset sign flag */
5136 /* save the signs of the operands */
5137 if (AOP_TYPE(right) == AOP_LIT)
5139 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5141 if (!rUnsigned && val < 0)
5142 emitcode ("mov", "b,#0x%02x", -val);
5144 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5146 else /* ! literal */
5149 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5152 MOVA (aopGet (right, 0, FALSE, FALSE));
5153 lbl = newiTempLabel (NULL);
5154 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5155 emitcode ("cpl", "F0"); /* complement sign flag */
5156 emitcode ("cpl", "a"); /* 2's complement */
5157 emitcode ("inc", "a");
5158 emitcode ("", "%05d$:", (lbl->key + 100));
5159 emitcode ("mov", "b,a");
5163 if (AOP_TYPE(left) == AOP_LIT)
5165 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5167 if (!lUnsigned && val < 0)
5168 emitcode ("mov", "a,#0x%02x", -val);
5170 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5172 else /* ! literal */
5174 MOVA (aopGet (left, 0, FALSE, FALSE));
5178 lbl = newiTempLabel (NULL);
5179 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5180 emitcode ("cpl", "F0"); /* complement sign flag */
5181 emitcode ("cpl", "a"); /* 2's complement */
5182 emitcode ("inc", "a");
5183 emitcode ("", "%05d$:", (lbl->key + 100));
5187 /* now the division */
5188 emitcode ("div", "ab");
5190 if (runtimeSign || compiletimeSign)
5192 lbl = newiTempLabel (NULL);
5194 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5195 emitcode ("cpl", "a"); /* lsb 2's complement */
5196 emitcode ("inc", "a");
5197 emitcode ("", "%05d$:", (lbl->key + 100));
5199 accuse = aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5202 /* msb is 0x00 or 0xff depending on the sign */
5207 emitcode ("push", "acc");
5210 emitcode ("mov", "c,F0");
5211 emitcode ("subb", "a,acc");
5213 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5215 else /* compiletimeSign */
5217 if (aopPutUsesAcc (result, "#0xFF", offset))
5219 emitcode ("push", "acc");
5223 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5229 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5231 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5235 emitcode ("pop", "acc");
5239 /*-----------------------------------------------------------------*/
5240 /* genDiv - generates code for division */
5241 /*-----------------------------------------------------------------*/
5245 operand *left = IC_LEFT (ic);
5246 operand *right = IC_RIGHT (ic);
5247 operand *result = IC_RESULT (ic);
5249 D(emitcode ("; genDiv",""));
5251 /* assign the amsops */
5252 aopOp (left, ic, FALSE);
5253 aopOp (right, ic, FALSE);
5254 aopOp (result, ic, TRUE);
5256 /* special cases first */
5258 if (AOP_TYPE (left) == AOP_CRY &&
5259 AOP_TYPE (right) == AOP_CRY)
5261 genDivbits (left, right, result);
5265 /* if both are of size == 1 */
5266 if (AOP_SIZE (left) == 1 &&
5267 AOP_SIZE (right) == 1)
5269 genDivOneByte (left, right, result);
5273 /* should have been converted to function call */
5276 freeAsmop (result, NULL, ic, TRUE);
5277 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5278 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5281 /*-----------------------------------------------------------------*/
5282 /* genModbits :- modulus of bits */
5283 /*-----------------------------------------------------------------*/
5285 genModbits (operand * left,
5292 D(emitcode ("; genModbits",""));
5296 /* the result must be bit */
5297 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5298 l = aopGet (left, 0, FALSE, FALSE);
5302 emitcode ("div", "ab");
5303 emitcode ("mov", "a,b");
5304 emitcode ("rrc", "a");
5308 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5311 /*-----------------------------------------------------------------*/
5312 /* genModOneByte : 8 bit modulus */
5313 /*-----------------------------------------------------------------*/
5315 genModOneByte (operand * left,
5319 bool lUnsigned, rUnsigned, pushedB;
5320 bool runtimeSign, compiletimeSign;
5324 D(emitcode ("; genModOneByte",""));
5326 size = AOP_SIZE (result) - 1;
5328 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5329 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5331 /* if right is a literal, check it for 2^n */
5332 if (AOP_TYPE(right) == AOP_LIT)
5334 unsigned char val = abs((int) operandLitValue(right));
5335 symbol *lbl2 = NULL;
5339 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5348 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5349 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5350 /* because iCode should have been changed to genAnd */
5351 /* see file "SDCCopt.c", function "convertToFcall()" */
5353 MOVA (aopGet (left, 0, FALSE, FALSE));
5354 emitcode ("mov", "c,acc.7");
5355 emitcode ("anl", "a,#0x%02x", val - 1);
5356 lbl = newiTempLabel (NULL);
5357 emitcode ("jz", "%05d$", (lbl->key + 100));
5358 emitcode ("jnc", "%05d$", (lbl->key + 100));
5359 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5365 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5367 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5368 lbl2 = newiTempLabel (NULL);
5369 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5371 emitcode ("", "%05d$:", (lbl->key + 100));
5372 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5374 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5377 emitcode ("", "%05d$:", (lbl2->key + 100));
5388 /* signed or unsigned */
5389 if (lUnsigned && rUnsigned)
5391 /* unsigned is easy */
5392 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5393 MOVA (aopGet (left, 0, FALSE, FALSE));
5394 emitcode ("div", "ab");
5395 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5397 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5403 /* signed is a little bit more difficult */
5405 /* now sign adjust for both left & right */
5407 /* modulus: sign of the right operand has no influence on the result! */
5408 if (AOP_TYPE(right) == AOP_LIT)
5410 signed char val = (char) operandLitValue(right);
5412 if (!rUnsigned && val < 0)
5413 emitcode ("mov", "b,#0x%02x", -val);
5415 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5417 else /* not literal */
5420 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5423 MOVA (aopGet (right, 0, FALSE, FALSE));
5424 lbl = newiTempLabel (NULL);
5425 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5426 emitcode ("cpl", "a"); /* 2's complement */
5427 emitcode ("inc", "a");
5428 emitcode ("", "%05d$:", (lbl->key + 100));
5429 emitcode ("mov", "b,a");
5433 /* let's see what's needed: */
5434 /* apply negative sign during runtime */
5435 runtimeSign = FALSE;
5436 /* negative sign from literals */
5437 compiletimeSign = FALSE;
5439 /* sign adjust left side */
5440 if (AOP_TYPE(left) == AOP_LIT)
5442 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5444 if (!lUnsigned && val < 0)
5446 compiletimeSign = TRUE; /* set sign flag */
5447 emitcode ("mov", "a,#0x%02x", -val);
5450 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5452 else /* ! literal */
5454 MOVA (aopGet (left, 0, FALSE, FALSE));
5459 emitcode ("clr", "F0"); /* clear sign flag */
5461 lbl = newiTempLabel (NULL);
5462 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5463 emitcode ("setb", "F0"); /* set sign flag */
5464 emitcode ("cpl", "a"); /* 2's complement */
5465 emitcode ("inc", "a");
5466 emitcode ("", "%05d$:", (lbl->key + 100));
5470 /* now the modulus */
5471 emitcode ("div", "ab");
5473 if (runtimeSign || compiletimeSign)
5475 emitcode ("mov", "a,b");
5476 lbl = newiTempLabel (NULL);
5478 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5479 emitcode ("cpl", "a"); /* 2's complement */
5480 emitcode ("inc", "a");
5481 emitcode ("", "%05d$:", (lbl->key + 100));
5483 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5486 /* msb is 0x00 or 0xff depending on the sign */
5489 emitcode ("mov", "c,F0");
5490 emitcode ("subb", "a,acc");
5492 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5494 else /* compiletimeSign */
5496 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5501 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5503 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5509 /*-----------------------------------------------------------------*/
5510 /* genMod - generates code for division */
5511 /*-----------------------------------------------------------------*/
5515 operand *left = IC_LEFT (ic);
5516 operand *right = IC_RIGHT (ic);
5517 operand *result = IC_RESULT (ic);
5519 D(emitcode ("; genMod",""));
5521 /* assign the asmops */
5522 aopOp (left, ic, FALSE);
5523 aopOp (right, ic, FALSE);
5524 aopOp (result, ic, TRUE);
5526 /* special cases first */
5528 if (AOP_TYPE (left) == AOP_CRY &&
5529 AOP_TYPE (right) == AOP_CRY)
5531 genModbits (left, right, result);
5535 /* if both are of size == 1 */
5536 if (AOP_SIZE (left) == 1 &&
5537 AOP_SIZE (right) == 1)
5539 genModOneByte (left, right, result);
5543 /* should have been converted to function call */
5547 freeAsmop (result, NULL, ic, TRUE);
5548 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5549 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5552 /*-----------------------------------------------------------------*/
5553 /* genIfxJump :- will create a jump depending on the ifx */
5554 /*-----------------------------------------------------------------*/
5556 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5559 symbol *tlbl = newiTempLabel (NULL);
5562 D(emitcode ("; genIfxJump",""));
5564 /* if true label then we jump if condition
5568 jlbl = IC_TRUE (ic);
5569 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5570 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5574 /* false label is present */
5575 jlbl = IC_FALSE (ic);
5576 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5577 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5579 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5580 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5582 emitcode (inst, "%05d$", tlbl->key + 100);
5583 freeForBranchAsmop (result);
5584 freeForBranchAsmop (right);
5585 freeForBranchAsmop (left);
5586 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5587 emitcode ("", "%05d$:", tlbl->key + 100);
5589 /* mark the icode as generated */
5593 /*-----------------------------------------------------------------*/
5594 /* genCmp :- greater or less than comparison */
5595 /*-----------------------------------------------------------------*/
5597 genCmp (operand * left, operand * right,
5598 operand * result, iCode * ifx, int sign, iCode *ic)
5600 int size, offset = 0;
5601 unsigned long lit = 0L;
5604 D(emitcode ("; genCmp",""));
5606 /* if left & right are bit variables */
5607 if (AOP_TYPE (left) == AOP_CRY &&
5608 AOP_TYPE (right) == AOP_CRY)
5610 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5611 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5615 /* subtract right from left if at the
5616 end the carry flag is set then we know that
5617 left is greater than right */
5618 size = max (AOP_SIZE (left), AOP_SIZE (right));
5620 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5621 if ((size == 1) && !sign &&
5622 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5624 symbol *lbl = newiTempLabel (NULL);
5625 emitcode ("cjne", "%s,%s,%05d$",
5626 aopGet (left, offset, FALSE, FALSE),
5627 aopGet (right, offset, FALSE, FALSE),
5629 emitcode ("", "%05d$:", lbl->key + 100);
5633 if (AOP_TYPE (right) == AOP_LIT)
5635 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5636 /* optimize if(x < 0) or if(x >= 0) */
5645 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5646 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5648 genIfxJump (ifx, "acc.7", left, right, result);
5649 freeAsmop (right, NULL, ic, TRUE);
5650 freeAsmop (left, NULL, ic, TRUE);
5655 emitcode ("rlc", "a");
5663 bool pushedB = FALSE;
5664 rightInB = aopGetUsesAcc(right, offset);
5668 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5670 MOVA (aopGet (left, offset, FALSE, FALSE));
5671 if (sign && size == 0)
5673 emitcode ("xrl", "a,#0x80");
5674 if (AOP_TYPE (right) == AOP_LIT)
5676 unsigned long lit = (unsigned long)
5677 floatFromVal (AOP (right)->aopu.aop_lit);
5678 emitcode ("subb", "a,#0x%02x",
5679 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5687 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5689 emitcode ("xrl", "b,#0x80");
5690 emitcode ("subb", "a,b");
5696 emitcode ("subb", "a,b");
5698 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5708 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5709 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5710 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5716 /* if the result is used in the next
5717 ifx conditional branch then generate
5718 code a little differently */
5720 genIfxJump (ifx, "c", NULL, NULL, result);
5723 /* leave the result in acc */
5727 /*-----------------------------------------------------------------*/
5728 /* genCmpGt :- greater than comparison */
5729 /*-----------------------------------------------------------------*/
5731 genCmpGt (iCode * ic, iCode * ifx)
5733 operand *left, *right, *result;
5734 sym_link *letype, *retype;
5737 D(emitcode ("; genCmpGt",""));
5739 left = IC_LEFT (ic);
5740 right = IC_RIGHT (ic);
5741 result = IC_RESULT (ic);
5743 letype = getSpec (operandType (left));
5744 retype = getSpec (operandType (right));
5745 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5746 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5747 /* assign the amsops */
5748 aopOp (result, ic, TRUE);
5749 aopOp (left, ic, FALSE);
5750 aopOp (right, ic, FALSE);
5752 genCmp (right, left, result, ifx, sign, ic);
5754 freeAsmop (result, NULL, ic, TRUE);
5757 /*-----------------------------------------------------------------*/
5758 /* genCmpLt - less than comparisons */
5759 /*-----------------------------------------------------------------*/
5761 genCmpLt (iCode * ic, iCode * ifx)
5763 operand *left, *right, *result;
5764 sym_link *letype, *retype;
5767 D(emitcode ("; genCmpLt",""));
5769 left = IC_LEFT (ic);
5770 right = IC_RIGHT (ic);
5771 result = IC_RESULT (ic);
5773 letype = getSpec (operandType (left));
5774 retype = getSpec (operandType (right));
5775 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5776 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5777 /* assign the amsops */
5778 aopOp (result, ic, TRUE);
5779 aopOp (left, ic, FALSE);
5780 aopOp (right, ic, FALSE);
5782 genCmp (left, right, result, ifx, sign, ic);
5784 freeAsmop (result, NULL, ic, TRUE);
5787 /*-----------------------------------------------------------------*/
5788 /* gencjneshort - compare and jump if not equal */
5789 /*-----------------------------------------------------------------*/
5791 gencjneshort (operand * left, operand * right, symbol * lbl)
5793 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5795 unsigned long lit = 0L;
5797 /* if the left side is a literal or
5798 if the right is in a pointer register and left
5800 if ((AOP_TYPE (left) == AOP_LIT) ||
5801 (AOP_TYPE (left) == AOP_IMMD) ||
5802 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5809 if (AOP_TYPE (right) == AOP_LIT)
5810 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5812 /* if the right side is a literal then anything goes */
5813 if (AOP_TYPE (right) == AOP_LIT &&
5814 AOP_TYPE (left) != AOP_DIR &&
5815 AOP_TYPE (left) != AOP_IMMD)
5819 emitcode ("cjne", "%s,%s,%05d$",
5820 aopGet (left, offset, FALSE, FALSE),
5821 aopGet (right, offset, FALSE, FALSE),
5827 /* if the right side is in a register or in direct space or
5828 if the left is a pointer register & right is not */
5829 else if (AOP_TYPE (right) == AOP_REG ||
5830 AOP_TYPE (right) == AOP_DIR ||
5831 AOP_TYPE (right) == AOP_LIT ||
5832 AOP_TYPE (right) == AOP_IMMD ||
5833 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5834 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5838 MOVA (aopGet (left, offset, FALSE, FALSE));
5839 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5840 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5841 emitcode ("jnz", "%05d$", lbl->key + 100);
5843 emitcode ("cjne", "a,%s,%05d$",
5844 aopGet (right, offset, FALSE, TRUE),
5851 /* right is a pointer reg need both a & b */
5855 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5856 wassertl(!BINUSE, "B was in use");
5857 l = aopGet (left, offset, FALSE, FALSE);
5858 if (strcmp (l, "b"))
5859 emitcode ("mov", "b,%s", l);
5860 MOVA (aopGet (right, offset, FALSE, FALSE));
5861 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5867 /*-----------------------------------------------------------------*/
5868 /* gencjne - compare and jump if not equal */
5869 /*-----------------------------------------------------------------*/
5871 gencjne (operand * left, operand * right, symbol * lbl)
5873 symbol *tlbl = newiTempLabel (NULL);
5875 gencjneshort (left, right, lbl);
5877 emitcode ("mov", "a,%s", one);
5878 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5879 emitcode ("", "%05d$:", lbl->key + 100);
5880 emitcode ("clr", "a");
5881 emitcode ("", "%05d$:", tlbl->key + 100);
5884 /*-----------------------------------------------------------------*/
5885 /* genCmpEq - generates code for equal to */
5886 /*-----------------------------------------------------------------*/
5888 genCmpEq (iCode * ic, iCode * ifx)
5890 bool swappedLR = FALSE;
5891 operand *left, *right, *result;
5893 D(emitcode ("; genCmpEq",""));
5895 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5896 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5897 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5899 /* if literal, literal on the right or
5900 if the right is in a pointer register and left
5902 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5903 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5905 operand *t = IC_RIGHT (ic);
5906 IC_RIGHT (ic) = IC_LEFT (ic);
5911 if (ifx && !AOP_SIZE (result))
5914 /* if they are both bit variables */
5915 if (AOP_TYPE (left) == AOP_CRY &&
5916 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5918 if (AOP_TYPE (right) == AOP_LIT)
5920 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5923 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5924 emitcode ("cpl", "c");
5928 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5932 emitcode ("clr", "c");
5934 /* AOP_TYPE(right) == AOP_CRY */
5938 symbol *lbl = newiTempLabel (NULL);
5939 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5940 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5941 emitcode ("cpl", "c");
5942 emitcode ("", "%05d$:", (lbl->key + 100));
5944 /* if true label then we jump if condition
5946 tlbl = newiTempLabel (NULL);
5949 emitcode ("jnc", "%05d$", tlbl->key + 100);
5950 freeForBranchAsmop (result);
5951 freeForBranchAsmop (right);
5952 freeForBranchAsmop (left);
5953 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5957 emitcode ("jc", "%05d$", tlbl->key + 100);
5958 freeForBranchAsmop (result);
5959 freeForBranchAsmop (right);
5960 freeForBranchAsmop (left);
5961 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5963 emitcode ("", "%05d$:", tlbl->key + 100);
5967 tlbl = newiTempLabel (NULL);
5968 gencjneshort (left, right, tlbl);
5971 freeForBranchAsmop (result);
5972 freeForBranchAsmop (right);
5973 freeForBranchAsmop (left);
5974 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5975 emitcode ("", "%05d$:", tlbl->key + 100);
5979 symbol *lbl = newiTempLabel (NULL);
5980 emitcode ("sjmp", "%05d$", lbl->key + 100);
5981 emitcode ("", "%05d$:", tlbl->key + 100);
5982 freeForBranchAsmop (result);
5983 freeForBranchAsmop (right);
5984 freeForBranchAsmop (left);
5985 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5986 emitcode ("", "%05d$:", lbl->key + 100);
5989 /* mark the icode as generated */
5994 /* if they are both bit variables */
5995 if (AOP_TYPE (left) == AOP_CRY &&
5996 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5998 if (AOP_TYPE (right) == AOP_LIT)
6000 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
6003 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6004 emitcode ("cpl", "c");
6008 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6012 emitcode ("clr", "c");
6014 /* AOP_TYPE(right) == AOP_CRY */
6018 symbol *lbl = newiTempLabel (NULL);
6019 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6020 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6021 emitcode ("cpl", "c");
6022 emitcode ("", "%05d$:", (lbl->key + 100));
6025 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6032 genIfxJump (ifx, "c", left, right, result);
6035 /* if the result is used in an arithmetic operation
6036 then put the result in place */
6041 gencjne (left, right, newiTempLabel (NULL));
6042 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6044 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6049 genIfxJump (ifx, "a", left, right, result);
6052 /* if the result is used in an arithmetic operation
6053 then put the result in place */
6054 if (AOP_TYPE (result) != AOP_CRY)
6056 /* leave the result in acc */
6060 freeAsmop (result, NULL, ic, TRUE);
6063 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6064 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6068 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6069 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6073 /*-----------------------------------------------------------------*/
6074 /* ifxForOp - returns the icode containing the ifx for operand */
6075 /*-----------------------------------------------------------------*/
6077 ifxForOp (operand * op, iCode * ic)
6079 /* if true symbol then needs to be assigned */
6080 if (IS_TRUE_SYMOP (op))
6083 /* if this has register type condition and
6084 the next instruction is ifx with the same operand
6085 and live to of the operand is upto the ifx only then */
6087 ic->next->op == IFX &&
6088 IC_COND (ic->next)->key == op->key &&
6089 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6095 /*-----------------------------------------------------------------*/
6096 /* hasInc - operand is incremented before any other use */
6097 /*-----------------------------------------------------------------*/
6099 hasInc (operand *op, iCode *ic,int osize)
6101 sym_link *type = operandType(op);
6102 sym_link *retype = getSpec (type);
6103 iCode *lic = ic->next;
6106 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6107 if (!IS_SYMOP(op)) return NULL;
6109 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6110 if (IS_AGGREGATE(type->next)) return NULL;
6111 if (osize != (isize = getSize(type->next))) return NULL;
6114 /* if operand of the form op = op + <sizeof *op> */
6115 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6116 isOperandEqual(IC_RESULT(lic),op) &&
6117 isOperandLiteral(IC_RIGHT(lic)) &&
6118 operandLitValue(IC_RIGHT(lic)) == isize) {
6121 /* if the operand used or deffed */
6122 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6125 /* if GOTO or IFX */
6126 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6132 /*-----------------------------------------------------------------*/
6133 /* genAndOp - for && operation */
6134 /*-----------------------------------------------------------------*/
6136 genAndOp (iCode * ic)
6138 operand *left, *right, *result;
6141 D(emitcode ("; genAndOp",""));
6143 /* note here that && operations that are in an
6144 if statement are taken away by backPatchLabels
6145 only those used in arthmetic operations remain */
6146 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6147 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6148 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6150 /* if both are bit variables */
6151 if (AOP_TYPE (left) == AOP_CRY &&
6152 AOP_TYPE (right) == AOP_CRY)
6154 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6155 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6160 tlbl = newiTempLabel (NULL);
6162 emitcode ("jz", "%05d$", tlbl->key + 100);
6164 emitcode ("", "%05d$:", tlbl->key + 100);
6168 freeAsmop (result, NULL, ic, TRUE);
6169 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6170 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6174 /*-----------------------------------------------------------------*/
6175 /* genOrOp - for || operation */
6176 /*-----------------------------------------------------------------*/
6178 genOrOp (iCode * ic)
6180 operand *left, *right, *result;
6183 D(emitcode ("; genOrOp",""));
6185 /* note here that || operations that are in an
6186 if statement are taken away by backPatchLabels
6187 only those used in arthmetic operations remain */
6188 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6189 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6190 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6192 /* if both are bit variables */
6193 if (AOP_TYPE (left) == AOP_CRY &&
6194 AOP_TYPE (right) == AOP_CRY)
6196 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6197 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6202 tlbl = newiTempLabel (NULL);
6204 emitcode ("jnz", "%05d$", tlbl->key + 100);
6206 emitcode ("", "%05d$:", tlbl->key + 100);
6210 freeAsmop (result, NULL, ic, TRUE);
6211 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6212 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6215 /*-----------------------------------------------------------------*/
6216 /* isLiteralBit - test if lit == 2^n */
6217 /*-----------------------------------------------------------------*/
6219 isLiteralBit (unsigned long lit)
6221 unsigned long pw[32] =
6222 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6223 0x100L, 0x200L, 0x400L, 0x800L,
6224 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6225 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6226 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6227 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6228 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6231 for (idx = 0; idx < 32; idx++)
6237 /*-----------------------------------------------------------------*/
6238 /* continueIfTrue - */
6239 /*-----------------------------------------------------------------*/
6241 continueIfTrue (iCode * ic)
6244 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6248 /*-----------------------------------------------------------------*/
6250 /*-----------------------------------------------------------------*/
6252 jumpIfTrue (iCode * ic)
6255 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6259 /*-----------------------------------------------------------------*/
6260 /* jmpTrueOrFalse - */
6261 /*-----------------------------------------------------------------*/
6263 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6265 // ugly but optimized by peephole
6268 symbol *nlbl = newiTempLabel (NULL);
6269 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6270 emitcode ("", "%05d$:", tlbl->key + 100);
6271 freeForBranchAsmop (result);
6272 freeForBranchAsmop (right);
6273 freeForBranchAsmop (left);
6274 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6275 emitcode ("", "%05d$:", nlbl->key + 100);
6279 freeForBranchAsmop (result);
6280 freeForBranchAsmop (right);
6281 freeForBranchAsmop (left);
6282 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6283 emitcode ("", "%05d$:", tlbl->key + 100);
6288 /*-----------------------------------------------------------------*/
6289 /* genAnd - code for and */
6290 /*-----------------------------------------------------------------*/
6292 genAnd (iCode * ic, iCode * ifx)
6294 operand *left, *right, *result;
6295 int size, offset = 0;
6296 unsigned long lit = 0L;
6300 D(emitcode ("; genAnd",""));
6302 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6303 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6304 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6307 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6309 AOP_TYPE (left), AOP_TYPE (right));
6310 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6312 AOP_SIZE (left), AOP_SIZE (right));
6315 /* if left is a literal & right is not then exchange them */
6316 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6317 AOP_NEEDSACC (left))
6319 operand *tmp = right;
6324 /* if result = right then exchange left and right */
6325 if (sameRegs (AOP (result), AOP (right)))
6327 operand *tmp = right;
6332 /* if right is bit then exchange them */
6333 if (AOP_TYPE (right) == AOP_CRY &&
6334 AOP_TYPE (left) != AOP_CRY)
6336 operand *tmp = right;
6340 if (AOP_TYPE (right) == AOP_LIT)
6341 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6343 size = AOP_SIZE (result);
6346 // result = bit & yy;
6347 if (AOP_TYPE (left) == AOP_CRY)
6349 // c = bit & literal;
6350 if (AOP_TYPE (right) == AOP_LIT)
6354 if (size && sameRegs (AOP (result), AOP (left)))
6357 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6362 if (size && (AOP_TYPE (result) == AOP_CRY))
6364 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6367 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6372 emitcode ("clr", "c");
6377 if (AOP_TYPE (right) == AOP_CRY)
6380 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6381 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6386 MOVA (aopGet (right, 0, FALSE, FALSE));
6388 emitcode ("rrc", "a");
6389 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6397 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6398 genIfxJump (ifx, "c", left, right, result);
6402 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6403 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6404 if ((AOP_TYPE (right) == AOP_LIT) &&
6405 (AOP_TYPE (result) == AOP_CRY) &&
6406 (AOP_TYPE (left) != AOP_CRY))
6408 int posbit = isLiteralBit (lit);
6413 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6417 switch (posbit & 0x07)
6419 case 0: emitcode ("rrc", "a");
6421 case 7: emitcode ("rlc", "a");
6423 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6432 SNPRINTF (buffer, sizeof(buffer),
6433 "acc.%d", posbit & 0x07);
6434 genIfxJump (ifx, buffer, left, right, result);
6437 {// what is this case? just found it in ds390/gen.c
6438 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6445 symbol *tlbl = newiTempLabel (NULL);
6446 int sizel = AOP_SIZE (left);
6448 emitcode ("setb", "c");
6451 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6453 MOVA (aopGet (left, offset, FALSE, FALSE));
6455 if ((posbit = isLiteralBit (bytelit)) != 0)
6456 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6459 if (bytelit != 0x0FFL)
6460 emitcode ("anl", "a,%s",
6461 aopGet (right, offset, FALSE, TRUE));
6462 emitcode ("jnz", "%05d$", tlbl->key + 100);
6467 // bit = left & literal
6470 emitcode ("clr", "c");
6471 emitcode ("", "%05d$:", tlbl->key + 100);
6473 // if(left & literal)
6477 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6479 emitcode ("", "%05d$:", tlbl->key + 100);
6487 /* if left is same as result */
6488 if (sameRegs (AOP (result), AOP (left)))
6490 for (; size--; offset++)
6492 if (AOP_TYPE (right) == AOP_LIT)
6494 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6495 if (bytelit == 0x0FF)
6497 /* dummy read of volatile operand */
6498 if (isOperandVolatile (left, FALSE))
6499 MOVA (aopGet (left, offset, FALSE, FALSE));
6503 else if (bytelit == 0)
6505 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6507 else if (IS_AOP_PREG (result))
6509 MOVA (aopGet (left, offset, FALSE, TRUE));
6510 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6511 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6514 emitcode ("anl", "%s,%s",
6515 aopGet (left, offset, FALSE, TRUE),
6516 aopGet (right, offset, FALSE, FALSE));
6520 if (AOP_TYPE (left) == AOP_ACC)
6523 emitcode("mov", "a,b");
6524 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6526 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6528 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6529 MOVA (aopGet (right, offset, FALSE, FALSE));
6530 emitcode ("anl", "a,b");
6531 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6533 else if (aopGetUsesAcc (left, offset))
6535 MOVA (aopGet (left, offset, FALSE, FALSE));
6536 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6537 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6541 MOVA (aopGet (right, offset, FALSE, FALSE));
6542 if (IS_AOP_PREG (result))
6544 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6545 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6548 emitcode ("anl", "%s,a",
6549 aopGet (left, offset, FALSE, TRUE));
6556 // left & result in different registers
6557 if (AOP_TYPE (result) == AOP_CRY)
6560 // if(size), result in bit
6561 // if(!size && ifx), conditional oper: if(left & right)
6562 symbol *tlbl = newiTempLabel (NULL);
6563 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6565 emitcode ("setb", "c");
6568 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6569 && AOP_TYPE(left)==AOP_ACC)
6572 emitcode("mov", "a,b");
6573 emitcode ("anl", "a,%s",
6574 aopGet (right, offset, FALSE, FALSE));
6576 if (AOP_TYPE(left)==AOP_ACC)
6580 bool pushedB = pushB ();
6581 emitcode("mov", "b,a");
6582 MOVA (aopGet (right, offset, FALSE, FALSE));
6583 emitcode("anl", "a,b");
6588 MOVA (aopGet (right, offset, FALSE, FALSE));
6589 emitcode("anl", "a,b");
6592 MOVA (aopGet (right, offset, FALSE, FALSE));
6593 emitcode ("anl", "a,%s",
6594 aopGet (left, offset, FALSE, FALSE));
6597 emitcode ("jnz", "%05d$", tlbl->key + 100);
6603 emitcode ("", "%05d$:", tlbl->key + 100);
6607 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6609 emitcode ("", "%05d$:", tlbl->key + 100);
6613 for (; (size--); offset++)
6616 // result = left & right
6617 if (AOP_TYPE (right) == AOP_LIT)
6619 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6620 if (bytelit == 0x0FF)
6623 aopGet (left, offset, FALSE, FALSE),
6625 isOperandVolatile (result, FALSE));
6628 else if (bytelit == 0)
6630 /* dummy read of volatile operand */
6631 if (isOperandVolatile (left, FALSE))
6632 MOVA (aopGet (left, offset, FALSE, FALSE));
6633 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6636 else if (AOP_TYPE (left) == AOP_ACC)
6640 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6641 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6646 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6647 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6652 // faster than result <- left, anl result,right
6653 // and better if result is SFR
6654 if (AOP_TYPE (left) == AOP_ACC)
6657 emitcode("mov", "a,b");
6658 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6660 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6662 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6663 MOVA (aopGet (right, offset, FALSE, FALSE));
6664 emitcode ("anl", "a,b");
6666 else if (aopGetUsesAcc (left, offset))
6668 MOVA (aopGet (left, offset, FALSE, FALSE));
6669 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6673 MOVA (aopGet (right, offset, FALSE, FALSE));
6674 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6676 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6682 freeAsmop (result, NULL, ic, TRUE);
6683 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6684 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6687 /*-----------------------------------------------------------------*/
6688 /* genOr - code for or */
6689 /*-----------------------------------------------------------------*/
6691 genOr (iCode * ic, iCode * ifx)
6693 operand *left, *right, *result;
6694 int size, offset = 0;
6695 unsigned long lit = 0L;
6698 D(emitcode ("; genOr",""));
6700 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6701 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6702 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6705 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6707 AOP_TYPE (left), AOP_TYPE (right));
6708 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6710 AOP_SIZE (left), AOP_SIZE (right));
6713 /* if left is a literal & right is not then exchange them */
6714 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6715 AOP_NEEDSACC (left))
6717 operand *tmp = right;
6722 /* if result = right then exchange them */
6723 if (sameRegs (AOP (result), AOP (right)))
6725 operand *tmp = right;
6730 /* if right is bit then exchange them */
6731 if (AOP_TYPE (right) == AOP_CRY &&
6732 AOP_TYPE (left) != AOP_CRY)
6734 operand *tmp = right;
6738 if (AOP_TYPE (right) == AOP_LIT)
6739 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6741 size = AOP_SIZE (result);
6745 if (AOP_TYPE (left) == AOP_CRY)
6747 if (AOP_TYPE (right) == AOP_LIT)
6749 // c = bit | literal;
6752 // lit != 0 => result = 1
6753 if (AOP_TYPE (result) == AOP_CRY)
6756 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6758 continueIfTrue (ifx);
6761 emitcode ("setb", "c");
6765 // lit == 0 => result = left
6766 if (size && sameRegs (AOP (result), AOP (left)))
6768 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6773 if (AOP_TYPE (right) == AOP_CRY)
6776 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6777 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6782 symbol *tlbl = newiTempLabel (NULL);
6783 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6784 emitcode ("setb", "c");
6785 emitcode ("jb", "%s,%05d$",
6786 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6788 emitcode ("jnz", "%05d$", tlbl->key + 100);
6789 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6791 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6797 emitcode ("", "%05d$:", tlbl->key + 100);
6806 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6807 genIfxJump (ifx, "c", left, right, result);
6811 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6812 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6813 if ((AOP_TYPE (right) == AOP_LIT) &&
6814 (AOP_TYPE (result) == AOP_CRY) &&
6815 (AOP_TYPE (left) != AOP_CRY))
6821 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6823 continueIfTrue (ifx);
6828 // lit = 0, result = boolean(left)
6830 emitcode ("setb", "c");
6834 symbol *tlbl = newiTempLabel (NULL);
6835 emitcode ("jnz", "%05d$", tlbl->key + 100);
6837 emitcode ("", "%05d$:", tlbl->key + 100);
6841 genIfxJump (ifx, "a", left, right, result);
6849 /* if left is same as result */
6850 if (sameRegs (AOP (result), AOP (left)))
6852 for (; size--; offset++)
6854 if (AOP_TYPE (right) == AOP_LIT)
6856 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6859 /* dummy read of volatile operand */
6860 if (isOperandVolatile (left, FALSE))
6861 MOVA (aopGet (left, offset, FALSE, FALSE));
6865 else if (bytelit == 0x0FF)
6867 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6869 else if (IS_AOP_PREG (left))
6871 MOVA (aopGet (left, offset, FALSE, TRUE));
6872 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6873 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6877 emitcode ("orl", "%s,%s",
6878 aopGet (left, offset, FALSE, TRUE),
6879 aopGet (right, offset, FALSE, FALSE));
6884 if (AOP_TYPE (left) == AOP_ACC)
6887 emitcode("mov", "a,b");
6888 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6890 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6892 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6893 MOVA (aopGet (right, offset, FALSE, FALSE));
6894 emitcode ("orl", "a,b");
6895 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6897 else if (aopGetUsesAcc (left, offset))
6899 MOVA (aopGet (left, offset, FALSE, FALSE));
6900 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6901 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6905 MOVA (aopGet (right, offset, FALSE, FALSE));
6906 if (IS_AOP_PREG (left))
6908 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6909 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6913 emitcode ("orl", "%s,a",
6914 aopGet (left, offset, FALSE, TRUE));
6922 // left & result in different registers
6923 if (AOP_TYPE (result) == AOP_CRY)
6926 // if(size), result in bit
6927 // if(!size && ifx), conditional oper: if(left | right)
6928 symbol *tlbl = newiTempLabel (NULL);
6929 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6931 emitcode ("setb", "c");
6934 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6936 emitcode("mov", "a,b");
6937 emitcode ("orl", "a,%s",
6938 aopGet (right, offset, FALSE, FALSE));
6940 MOVA (aopGet (right, offset, FALSE, FALSE));
6941 emitcode ("orl", "a,%s",
6942 aopGet (left, offset, FALSE, FALSE));
6944 emitcode ("jnz", "%05d$", tlbl->key + 100);
6950 emitcode ("", "%05d$:", tlbl->key + 100);
6954 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6956 emitcode ("", "%05d$:", tlbl->key + 100);
6960 for (; (size--); offset++)
6963 // result = left | right
6964 if (AOP_TYPE (right) == AOP_LIT)
6966 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6970 aopGet (left, offset, FALSE, FALSE),
6972 isOperandVolatile (result, FALSE));
6975 else if (bytelit == 0x0FF)
6977 /* dummy read of volatile operand */
6978 if (isOperandVolatile (left, FALSE))
6979 MOVA (aopGet (left, offset, FALSE, FALSE));
6980 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6984 // faster than result <- left, anl result,right
6985 // and better if result is SFR
6986 if (AOP_TYPE (left) == AOP_ACC)
6989 emitcode("mov", "a,b");
6990 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6992 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6994 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6995 MOVA (aopGet (right, offset, FALSE, FALSE));
6996 emitcode ("orl", "a,b");
6998 else if (aopGetUsesAcc (left, offset))
7000 MOVA (aopGet (left, offset, FALSE, FALSE));
7001 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7005 MOVA (aopGet (right, offset, FALSE, FALSE));
7006 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
7008 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7014 freeAsmop (result, NULL, ic, TRUE);
7015 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7016 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7019 /*-----------------------------------------------------------------*/
7020 /* genXor - code for xclusive or */
7021 /*-----------------------------------------------------------------*/
7023 genXor (iCode * ic, iCode * ifx)
7025 operand *left, *right, *result;
7026 int size, offset = 0;
7027 unsigned long lit = 0L;
7030 D(emitcode ("; genXor",""));
7032 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7033 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7034 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7037 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7039 AOP_TYPE (left), AOP_TYPE (right));
7040 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7042 AOP_SIZE (left), AOP_SIZE (right));
7045 /* if left is a literal & right is not ||
7046 if left needs acc & right does not */
7047 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7048 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7050 operand *tmp = right;
7055 /* if result = right then exchange them */
7056 if (sameRegs (AOP (result), AOP (right)))
7058 operand *tmp = right;
7063 /* if right is bit then exchange them */
7064 if (AOP_TYPE (right) == AOP_CRY &&
7065 AOP_TYPE (left) != AOP_CRY)
7067 operand *tmp = right;
7071 if (AOP_TYPE (right) == AOP_LIT)
7072 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7074 size = AOP_SIZE (result);
7078 if (AOP_TYPE (left) == AOP_CRY)
7080 if (AOP_TYPE (right) == AOP_LIT)
7082 // c = bit & literal;
7085 // lit>>1 != 0 => result = 1
7086 if (AOP_TYPE (result) == AOP_CRY)
7089 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7091 continueIfTrue (ifx);
7094 emitcode ("setb", "c");
7101 // lit == 0, result = left
7102 if (size && sameRegs (AOP (result), AOP (left)))
7104 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7108 // lit == 1, result = not(left)
7109 if (size && sameRegs (AOP (result), AOP (left)))
7111 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7116 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7117 emitcode ("cpl", "c");
7126 symbol *tlbl = newiTempLabel (NULL);
7127 if (AOP_TYPE (right) == AOP_CRY)
7130 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7134 int sizer = AOP_SIZE (right);
7136 // if val>>1 != 0, result = 1
7137 emitcode ("setb", "c");
7140 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7142 // test the msb of the lsb
7143 emitcode ("anl", "a,#0xfe");
7144 emitcode ("jnz", "%05d$", tlbl->key + 100);
7148 emitcode ("rrc", "a");
7150 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7151 emitcode ("cpl", "c");
7152 emitcode ("", "%05d$:", (tlbl->key + 100));
7159 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7160 genIfxJump (ifx, "c", left, right, result);
7164 /* if left is same as result */
7165 if (sameRegs (AOP (result), AOP (left)))
7167 for (; size--; offset++)
7169 if (AOP_TYPE (right) == AOP_LIT)
7171 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7174 /* dummy read of volatile operand */
7175 if (isOperandVolatile (left, FALSE))
7176 MOVA (aopGet (left, offset, FALSE, FALSE));
7180 else if (IS_AOP_PREG (left))
7182 MOVA (aopGet (left, offset, FALSE, TRUE));
7183 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7184 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7188 emitcode ("xrl", "%s,%s",
7189 aopGet (left, offset, FALSE, TRUE),
7190 aopGet (right, offset, FALSE, FALSE));
7195 if (AOP_TYPE (left) == AOP_ACC)
7198 emitcode("mov", "a,b");
7199 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7201 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7203 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7204 MOVA (aopGet (right, offset, FALSE, FALSE));
7205 emitcode ("xrl", "a,b");
7206 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7208 else if (aopGetUsesAcc (left, offset))
7210 MOVA (aopGet (left, offset, FALSE, FALSE));
7211 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7212 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7216 MOVA (aopGet (right, offset, FALSE, FALSE));
7217 if (IS_AOP_PREG (left))
7219 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7220 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7223 emitcode ("xrl", "%s,a",
7224 aopGet (left, offset, FALSE, TRUE));
7231 // left & result in different registers
7232 if (AOP_TYPE (result) == AOP_CRY)
7235 // if(size), result in bit
7236 // if(!size && ifx), conditional oper: if(left ^ right)
7237 symbol *tlbl = newiTempLabel (NULL);
7238 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7240 emitcode ("setb", "c");
7243 if ((AOP_TYPE (right) == AOP_LIT) &&
7244 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7246 MOVA (aopGet (left, offset, FALSE, FALSE));
7250 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7252 emitcode("mov", "a,b");
7253 emitcode ("xrl", "a,%s",
7254 aopGet (right, offset, FALSE, FALSE));
7256 MOVA (aopGet (right, offset, FALSE, FALSE));
7257 emitcode ("xrl", "a,%s",
7258 aopGet (left, offset, FALSE, FALSE));
7261 emitcode ("jnz", "%05d$", tlbl->key + 100);
7267 emitcode ("", "%05d$:", tlbl->key + 100);
7271 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7275 for (; (size--); offset++)
7278 // result = left & right
7279 if (AOP_TYPE (right) == AOP_LIT)
7281 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7285 aopGet (left, offset, FALSE, FALSE),
7287 isOperandVolatile (result, FALSE));
7291 // faster than result <- left, anl result,right
7292 // and better if result is SFR
7293 if (AOP_TYPE (left) == AOP_ACC)
7296 emitcode("mov", "a,b");
7297 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7299 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7301 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7302 MOVA (aopGet (right, offset, FALSE, FALSE));
7303 emitcode ("xrl", "a,b");
7305 else if (aopGetUsesAcc (left, offset))
7307 MOVA (aopGet (left, offset, FALSE, FALSE));
7308 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7312 MOVA (aopGet (right, offset, FALSE, FALSE));
7313 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7315 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7321 freeAsmop (result, NULL, ic, TRUE);
7322 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7323 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7326 /*-----------------------------------------------------------------*/
7327 /* genInline - write the inline code out */
7328 /*-----------------------------------------------------------------*/
7330 genInline (iCode * ic)
7332 char *buffer, *bp, *bp1;
7334 D(emitcode ("; genInline",""));
7336 _G.inLine += (!options.asmpeep);
7338 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7339 strcpy (buffer, IC_INLINE (ic));
7341 /* emit each line as a code */
7352 /* Add \n for labels, not dirs such as c:\mydir */
7353 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7367 /* emitcode("",buffer); */
7368 _G.inLine -= (!options.asmpeep);
7371 /*-----------------------------------------------------------------*/
7372 /* genRRC - rotate right with carry */
7373 /*-----------------------------------------------------------------*/
7377 operand *left, *result;
7378 int size, offset = 0;
7381 D(emitcode ("; genRRC",""));
7383 /* rotate right with carry */
7384 left = IC_LEFT (ic);
7385 result = IC_RESULT (ic);
7386 aopOp (left, ic, FALSE);
7387 aopOp (result, ic, FALSE);
7389 /* move it to the result */
7390 size = AOP_SIZE (result);
7392 if (size == 1) { /* special case for 1 byte */
7393 l = aopGet (left, offset, FALSE, FALSE);
7395 emitcode ("rr", "a");
7398 /* no need to clear carry, bit7 will be written later */
7401 l = aopGet (left, offset, FALSE, FALSE);
7403 emitcode ("rrc", "a");
7404 if (AOP_SIZE (result) > 1)
7405 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7407 /* now we need to put the carry into the
7408 highest order byte of the result */
7409 if (AOP_SIZE (result) > 1)
7411 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7414 emitcode ("mov", "acc.7,c");
7416 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7417 freeAsmop (result, NULL, ic, TRUE);
7418 freeAsmop (left, NULL, ic, TRUE);
7421 /*-----------------------------------------------------------------*/
7422 /* genRLC - generate code for rotate left with carry */
7423 /*-----------------------------------------------------------------*/
7427 operand *left, *result;
7428 int size, offset = 0;
7431 D(emitcode ("; genRLC",""));
7433 /* rotate right with carry */
7434 left = IC_LEFT (ic);
7435 result = IC_RESULT (ic);
7436 aopOp (left, ic, FALSE);
7437 aopOp (result, ic, FALSE);
7439 /* move it to the result */
7440 size = AOP_SIZE (result);
7444 l = aopGet (left, offset, FALSE, FALSE);
7446 if (size == 0) { /* special case for 1 byte */
7450 emitcode("rlc","a"); /* bit0 will be written later */
7451 if (AOP_SIZE (result) > 1)
7452 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7455 l = aopGet (left, offset, FALSE, FALSE);
7457 emitcode ("rlc", "a");
7458 if (AOP_SIZE (result) > 1)
7459 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7462 /* now we need to put the carry into the
7463 highest order byte of the result */
7464 if (AOP_SIZE (result) > 1)
7466 l = aopGet (result, 0, FALSE, FALSE);
7469 emitcode ("mov", "acc.0,c");
7471 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7472 freeAsmop (result, NULL, ic, TRUE);
7473 freeAsmop (left, NULL, ic, TRUE);
7476 /*-----------------------------------------------------------------*/
7477 /* genGetHbit - generates code get highest order bit */
7478 /*-----------------------------------------------------------------*/
7480 genGetHbit (iCode * ic)
7482 operand *left, *result;
7484 D(emitcode ("; genGetHbit",""));
7486 left = IC_LEFT (ic);
7487 result = IC_RESULT (ic);
7488 aopOp (left, ic, FALSE);
7489 aopOp (result, ic, FALSE);
7491 /* get the highest order byte into a */
7492 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7493 if (AOP_TYPE (result) == AOP_CRY)
7495 emitcode ("rlc", "a");
7500 emitcode ("rl", "a");
7501 emitcode ("anl", "a,#0x01");
7505 freeAsmop (result, NULL, ic, TRUE);
7506 freeAsmop (left, NULL, ic, TRUE);
7509 /*-----------------------------------------------------------------*/
7510 /* genGetAbit - generates code get a single bit */
7511 /*-----------------------------------------------------------------*/
7513 genGetAbit (iCode * ic)
7515 operand *left, *right, *result;
7518 D(emitcode ("; genGetAbit",""));
7520 left = IC_LEFT (ic);
7521 right = IC_RIGHT (ic);
7522 result = IC_RESULT (ic);
7523 aopOp (left, ic, FALSE);
7524 aopOp (right, ic, FALSE);
7525 aopOp (result, ic, FALSE);
7527 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7529 /* get the needed byte into a */
7530 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7532 if (AOP_TYPE (result) == AOP_CRY)
7535 emitcode ("rlc", "a");
7536 else if ((shCount) == 0)
7537 emitcode ("rrc", "a");
7539 emitcode ("mov", "c,acc[%d]", shCount);
7547 emitcode ("rr", "a");
7550 emitcode ("rr", "a");
7553 emitcode ("anl", "a,#0x01");
7557 emitcode ("mov", "c,acc[%d]", shCount);
7558 emitcode ("clr", "a");
7559 emitcode ("rlc", "a");
7562 emitcode ("swap", "a");
7563 emitcode ("anl", "a,#0x01");
7566 emitcode ("rl", "a");
7569 emitcode ("rl", "a");
7570 emitcode ("anl", "a,#0x01");
7576 freeAsmop (result, NULL, ic, TRUE);
7577 freeAsmop (right, NULL, ic, TRUE);
7578 freeAsmop (left, NULL, ic, TRUE);
7581 /*-----------------------------------------------------------------*/
7582 /* genGetByte - generates code get a single byte */
7583 /*-----------------------------------------------------------------*/
7585 genGetByte (iCode * ic)
7587 operand *left, *right, *result;
7590 D(emitcode ("; genGetByte",""));
7592 left = IC_LEFT (ic);
7593 right = IC_RIGHT (ic);
7594 result = IC_RESULT (ic);
7595 aopOp (left, ic, FALSE);
7596 aopOp (right, ic, FALSE);
7597 aopOp (result, ic, FALSE);
7599 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7601 aopGet (left, offset, FALSE, FALSE),
7603 isOperandVolatile (result, FALSE));
7605 freeAsmop (result, NULL, ic, TRUE);
7606 freeAsmop (right, NULL, ic, TRUE);
7607 freeAsmop (left, NULL, ic, TRUE);
7610 /*-----------------------------------------------------------------*/
7611 /* genGetWord - generates code get two bytes */
7612 /*-----------------------------------------------------------------*/
7614 genGetWord (iCode * ic)
7616 operand *left, *right, *result;
7619 D(emitcode ("; genGetWord",""));
7621 left = IC_LEFT (ic);
7622 right = IC_RIGHT (ic);
7623 result = IC_RESULT (ic);
7624 aopOp (left, ic, FALSE);
7625 aopOp (right, ic, FALSE);
7626 aopOp (result, ic, FALSE);
7628 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7630 aopGet (left, offset, FALSE, FALSE),
7632 isOperandVolatile (result, FALSE));
7634 aopGet (left, offset+1, FALSE, FALSE),
7636 isOperandVolatile (result, FALSE));
7638 freeAsmop (result, NULL, ic, TRUE);
7639 freeAsmop (right, NULL, ic, TRUE);
7640 freeAsmop (left, NULL, ic, TRUE);
7643 /*-----------------------------------------------------------------*/
7644 /* genSwap - generates code to swap nibbles or bytes */
7645 /*-----------------------------------------------------------------*/
7647 genSwap (iCode * ic)
7649 operand *left, *result;
7651 D(emitcode ("; genSwap",""));
7653 left = IC_LEFT (ic);
7654 result = IC_RESULT (ic);
7655 aopOp (left, ic, FALSE);
7656 aopOp (result, ic, FALSE);
7658 switch (AOP_SIZE (left))
7660 case 1: /* swap nibbles in byte */
7661 MOVA (aopGet (left, 0, FALSE, FALSE));
7662 emitcode ("swap", "a");
7663 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7665 case 2: /* swap bytes in word */
7666 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7668 MOVA (aopGet (left, 0, FALSE, FALSE));
7669 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7670 0, isOperandVolatile (result, FALSE));
7671 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7673 else if (operandsEqu (left, result))
7676 bool pushedB = FALSE, leftInB = FALSE;
7678 MOVA (aopGet (left, 0, FALSE, FALSE));
7679 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7682 emitcode ("mov", "b,a");
7686 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7687 0, isOperandVolatile (result, FALSE));
7688 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7695 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7696 0, isOperandVolatile (result, FALSE));
7697 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7698 1, isOperandVolatile (result, FALSE));
7702 wassertl(FALSE, "unsupported SWAP operand size");
7705 freeAsmop (result, NULL, ic, TRUE);
7706 freeAsmop (left, NULL, ic, TRUE);
7710 /*-----------------------------------------------------------------*/
7711 /* AccRol - rotate left accumulator by known count */
7712 /*-----------------------------------------------------------------*/
7714 AccRol (int shCount)
7716 shCount &= 0x0007; // shCount : 0..7
7723 emitcode ("rl", "a");
7726 emitcode ("rl", "a");
7727 emitcode ("rl", "a");
7730 emitcode ("swap", "a");
7731 emitcode ("rr", "a");
7734 emitcode ("swap", "a");
7737 emitcode ("swap", "a");
7738 emitcode ("rl", "a");
7741 emitcode ("rr", "a");
7742 emitcode ("rr", "a");
7745 emitcode ("rr", "a");
7750 /*-----------------------------------------------------------------*/
7751 /* AccLsh - left shift accumulator by known count */
7752 /*-----------------------------------------------------------------*/
7754 AccLsh (int shCount)
7759 emitcode ("add", "a,acc");
7760 else if (shCount == 2)
7762 emitcode ("add", "a,acc");
7763 emitcode ("add", "a,acc");
7767 /* rotate left accumulator */
7769 /* and kill the lower order bits */
7770 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7775 /*-----------------------------------------------------------------*/
7776 /* AccRsh - right shift accumulator by known count */
7777 /*-----------------------------------------------------------------*/
7779 AccRsh (int shCount)
7786 emitcode ("rrc", "a");
7790 /* rotate right accumulator */
7791 AccRol (8 - shCount);
7792 /* and kill the higher order bits */
7793 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7798 /*-----------------------------------------------------------------*/
7799 /* AccSRsh - signed right shift accumulator by known count */
7800 /*-----------------------------------------------------------------*/
7802 AccSRsh (int shCount)
7809 emitcode ("mov", "c,acc.7");
7810 emitcode ("rrc", "a");
7812 else if (shCount == 2)
7814 emitcode ("mov", "c,acc.7");
7815 emitcode ("rrc", "a");
7816 emitcode ("mov", "c,acc.7");
7817 emitcode ("rrc", "a");
7821 tlbl = newiTempLabel (NULL);
7822 /* rotate right accumulator */
7823 AccRol (8 - shCount);
7824 /* and kill the higher order bits */
7825 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7826 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7827 emitcode ("orl", "a,#0x%02x",
7828 (unsigned char) ~SRMask[shCount]);
7829 emitcode ("", "%05d$:", tlbl->key + 100);
7834 /*-----------------------------------------------------------------*/
7835 /* shiftR1Left2Result - shift right one byte from left to result */
7836 /*-----------------------------------------------------------------*/
7838 shiftR1Left2Result (operand * left, int offl,
7839 operand * result, int offr,
7840 int shCount, int sign)
7842 MOVA (aopGet (left, offl, FALSE, FALSE));
7843 /* shift right accumulator */
7848 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7851 /*-----------------------------------------------------------------*/
7852 /* shiftL1Left2Result - shift left one byte from left to result */
7853 /*-----------------------------------------------------------------*/
7855 shiftL1Left2Result (operand * left, int offl,
7856 operand * result, int offr, int shCount)
7859 l = aopGet (left, offl, FALSE, FALSE);
7861 /* shift left accumulator */
7863 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7866 /*-----------------------------------------------------------------*/
7867 /* movLeft2Result - move byte from left to result */
7868 /*-----------------------------------------------------------------*/
7870 movLeft2Result (operand * left, int offl,
7871 operand * result, int offr, int sign)
7874 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7876 l = aopGet (left, offl, FALSE, FALSE);
7878 if (*l == '@' && (IS_AOP_PREG (result)))
7880 emitcode ("mov", "a,%s", l);
7881 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7886 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7889 /* MSB sign in acc.7 ! */
7890 if (getDataSize (left) == offl + 1)
7893 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7900 /*-----------------------------------------------------------------*/
7901 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7902 /*-----------------------------------------------------------------*/
7906 emitcode ("rrc", "a");
7907 emitcode ("xch", "a,%s", x);
7908 emitcode ("rrc", "a");
7909 emitcode ("xch", "a,%s", x);
7912 /*-----------------------------------------------------------------*/
7913 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7914 /*-----------------------------------------------------------------*/
7918 emitcode ("xch", "a,%s", x);
7919 emitcode ("rlc", "a");
7920 emitcode ("xch", "a,%s", x);
7921 emitcode ("rlc", "a");
7924 /*-----------------------------------------------------------------*/
7925 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7926 /*-----------------------------------------------------------------*/
7930 emitcode ("xch", "a,%s", x);
7931 emitcode ("add", "a,acc");
7932 emitcode ("xch", "a,%s", x);
7933 emitcode ("rlc", "a");
7936 /*-----------------------------------------------------------------*/
7937 /* AccAXLsh - left shift a:x by known count (0..7) */
7938 /*-----------------------------------------------------------------*/
7940 AccAXLsh (char *x, int shCount)
7955 case 5: // AAAAABBB:CCCCCDDD
7957 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7959 emitcode ("anl", "a,#0x%02x",
7960 SLMask[shCount]); // BBB00000:CCCCCDDD
7962 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7964 AccRol (shCount); // DDDCCCCC:BBB00000
7966 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7968 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7970 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7972 emitcode ("anl", "a,#0x%02x",
7973 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7975 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7977 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7980 case 6: // AAAAAABB:CCCCCCDD
7981 emitcode ("anl", "a,#0x%02x",
7982 SRMask[shCount]); // 000000BB:CCCCCCDD
7983 emitcode ("mov", "c,acc.0"); // c = B
7984 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7986 AccAXRrl1 (x); // BCCCCCCD:D000000B
7987 AccAXRrl1 (x); // BBCCCCCC:DD000000
7989 emitcode("rrc","a");
7990 emitcode("xch","a,%s", x);
7991 emitcode("rrc","a");
7992 emitcode("mov","c,acc.0"); //<< get correct bit
7993 emitcode("xch","a,%s", x);
7995 emitcode("rrc","a");
7996 emitcode("xch","a,%s", x);
7997 emitcode("rrc","a");
7998 emitcode("xch","a,%s", x);
8001 case 7: // a:x <<= 7
8003 emitcode ("anl", "a,#0x%02x",
8004 SRMask[shCount]); // 0000000B:CCCCCCCD
8006 emitcode ("mov", "c,acc.0"); // c = B
8008 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
8010 AccAXRrl1 (x); // BCCCCCCC:D0000000
8018 /*-----------------------------------------------------------------*/
8019 /* AccAXRsh - right shift a:x known count (0..7) */
8020 /*-----------------------------------------------------------------*/
8022 AccAXRsh (char *x, int shCount)
8030 AccAXRrl1 (x); // 0->a:x
8035 AccAXRrl1 (x); // 0->a:x
8038 AccAXRrl1 (x); // 0->a:x
8043 case 5: // AAAAABBB:CCCCCDDD = a:x
8045 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8047 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8049 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8051 emitcode ("anl", "a,#0x%02x",
8052 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8054 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8056 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8058 emitcode ("anl", "a,#0x%02x",
8059 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8061 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8063 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8065 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8068 case 6: // AABBBBBB:CCDDDDDD
8070 emitcode ("mov", "c,acc.7");
8071 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8073 emitcode ("mov", "c,acc.7");
8074 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8076 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8078 emitcode ("anl", "a,#0x%02x",
8079 SRMask[shCount]); // 000000AA:BBBBBBCC
8082 case 7: // ABBBBBBB:CDDDDDDD
8084 emitcode ("mov", "c,acc.7"); // c = A
8086 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8088 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8090 emitcode ("anl", "a,#0x%02x",
8091 SRMask[shCount]); // 0000000A:BBBBBBBC
8099 /*-----------------------------------------------------------------*/
8100 /* AccAXRshS - right shift signed a:x known count (0..7) */
8101 /*-----------------------------------------------------------------*/
8103 AccAXRshS (char *x, int shCount)
8111 emitcode ("mov", "c,acc.7");
8112 AccAXRrl1 (x); // s->a:x
8116 emitcode ("mov", "c,acc.7");
8117 AccAXRrl1 (x); // s->a:x
8119 emitcode ("mov", "c,acc.7");
8120 AccAXRrl1 (x); // s->a:x
8125 case 5: // AAAAABBB:CCCCCDDD = a:x
8127 tlbl = newiTempLabel (NULL);
8128 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8130 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8132 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8134 emitcode ("anl", "a,#0x%02x",
8135 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8137 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8139 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8141 emitcode ("anl", "a,#0x%02x",
8142 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8144 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8146 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8148 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8150 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8151 emitcode ("orl", "a,#0x%02x",
8152 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8154 emitcode ("", "%05d$:", tlbl->key + 100);
8155 break; // SSSSAAAA:BBBCCCCC
8157 case 6: // AABBBBBB:CCDDDDDD
8159 tlbl = newiTempLabel (NULL);
8160 emitcode ("mov", "c,acc.7");
8161 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8163 emitcode ("mov", "c,acc.7");
8164 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8166 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8168 emitcode ("anl", "a,#0x%02x",
8169 SRMask[shCount]); // 000000AA:BBBBBBCC
8171 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8172 emitcode ("orl", "a,#0x%02x",
8173 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8175 emitcode ("", "%05d$:", tlbl->key + 100);
8177 case 7: // ABBBBBBB:CDDDDDDD
8179 tlbl = newiTempLabel (NULL);
8180 emitcode ("mov", "c,acc.7"); // c = A
8182 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8184 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8186 emitcode ("anl", "a,#0x%02x",
8187 SRMask[shCount]); // 0000000A:BBBBBBBC
8189 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8190 emitcode ("orl", "a,#0x%02x",
8191 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8193 emitcode ("", "%05d$:", tlbl->key + 100);
8200 /*-----------------------------------------------------------------*/
8201 /* shiftL2Left2Result - shift left two bytes from left to result */
8202 /*-----------------------------------------------------------------*/
8204 shiftL2Left2Result (operand * left, int offl,
8205 operand * result, int offr, int shCount)
8208 bool pushedB = FALSE;
8211 if (sameRegs (AOP (result), AOP (left)) &&
8212 ((offl + MSB16) == offr))
8214 /* don't crash result[offr] */
8215 MOVA (aopGet (left, offl, FALSE, FALSE));
8216 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8217 x = aopGet (result, offr, FALSE, FALSE);
8219 else if (aopGetUsesAcc (result, offr))
8221 movLeft2Result (left, offl, result, offr, 0);
8224 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8225 MOVA (aopGet (result, offr, FALSE, FALSE));
8226 emitcode ("xch", "a,b");
8231 movLeft2Result (left, offl, result, offr, 0);
8232 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8233 x = aopGet (result, offr, FALSE, FALSE);
8235 /* ax << shCount (x = lsb(result)) */
8236 AccAXLsh (x, shCount);
8239 emitcode ("xch", "a,b");
8240 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8241 aopPut (result, "b", offr + MSB16, isOperandVolatile (result, FALSE));
8246 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8251 /*-----------------------------------------------------------------*/
8252 /* shiftR2Left2Result - shift right two bytes from left to result */
8253 /*-----------------------------------------------------------------*/
8255 shiftR2Left2Result (operand * left, int offl,
8256 operand * result, int offr,
8257 int shCount, int sign)
8260 bool pushedB = FALSE;
8263 if (sameRegs (AOP (result), AOP (left)) &&
8264 ((offl + MSB16) == offr))
8266 /* don't crash result[offr] */
8267 MOVA (aopGet (left, offl, FALSE, FALSE));
8268 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8269 x = aopGet (result, offr, FALSE, FALSE);
8271 else if (aopGetUsesAcc (result, offr))
8273 movLeft2Result (left, offl, result, offr, 0);
8276 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8277 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8282 movLeft2Result (left, offl, result, offr, 0);
8283 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8284 x = aopGet (result, offr, FALSE, FALSE);
8286 /* a:x >> shCount (x = lsb(result)) */
8288 AccAXRshS (x, shCount);
8290 AccAXRsh (x, shCount);
8293 emitcode ("xch", "a,b");
8294 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8295 emitcode ("xch", "a,b");
8298 if (getDataSize (result) > 1)
8299 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8302 /*-----------------------------------------------------------------*/
8303 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8304 /*-----------------------------------------------------------------*/
8306 shiftLLeftOrResult (operand * left, int offl,
8307 operand * result, int offr, int shCount)
8309 MOVA (aopGet (left, offl, FALSE, FALSE));
8310 /* shift left accumulator */
8312 /* or with result */
8313 if (aopGetUsesAcc (result, offr))
8315 emitcode ("xch", "a,b");
8316 MOVA (aopGet (result, offr, FALSE, FALSE));
8317 emitcode ("orl", "a,b");
8321 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8323 /* back to result */
8324 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8327 /*-----------------------------------------------------------------*/
8328 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8329 /*-----------------------------------------------------------------*/
8331 shiftRLeftOrResult (operand * left, int offl,
8332 operand * result, int offr, int shCount)
8334 MOVA (aopGet (left, offl, FALSE, FALSE));
8335 /* shift right accumulator */
8337 /* or with result */
8338 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8339 /* back to result */
8340 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8343 /*-----------------------------------------------------------------*/
8344 /* genlshOne - left shift a one byte quantity by known count */
8345 /*-----------------------------------------------------------------*/
8347 genlshOne (operand * result, operand * left, int shCount)
8349 D(emitcode ("; genlshOne",""));
8351 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8354 /*-----------------------------------------------------------------*/
8355 /* genlshTwo - left shift two bytes by known amount != 0 */
8356 /*-----------------------------------------------------------------*/
8358 genlshTwo (operand * result, operand * left, int shCount)
8362 D(emitcode ("; genlshTwo",""));
8364 size = getDataSize (result);
8366 /* if shCount >= 8 */
8374 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8376 movLeft2Result (left, LSB, result, MSB16, 0);
8378 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8381 /* 1 <= shCount <= 7 */
8385 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8387 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8391 /*-----------------------------------------------------------------*/
8392 /* shiftLLong - shift left one long from left to result */
8393 /* offl = LSB or MSB16 */
8394 /*-----------------------------------------------------------------*/
8396 shiftLLong (operand * left, operand * result, int offr)
8399 int size = AOP_SIZE (result);
8401 if (size >= LSB + offr)
8403 l = aopGet (left, LSB, FALSE, FALSE);
8405 emitcode ("add", "a,acc");
8406 if (sameRegs (AOP (left), AOP (result)) &&
8407 size >= MSB16 + offr && offr != LSB)
8408 emitcode ("xch", "a,%s",
8409 aopGet (left, LSB + offr, FALSE, FALSE));
8411 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8414 if (size >= MSB16 + offr)
8416 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8418 l = aopGet (left, MSB16, FALSE, FALSE);
8421 emitcode ("rlc", "a");
8422 if (sameRegs (AOP (left), AOP (result)) &&
8423 size >= MSB24 + offr && offr != LSB)
8424 emitcode ("xch", "a,%s",
8425 aopGet (left, MSB16 + offr, FALSE, FALSE));
8427 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8430 if (size >= MSB24 + offr)
8432 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8434 l = aopGet (left, MSB24, FALSE, FALSE);
8437 emitcode ("rlc", "a");
8438 if (sameRegs (AOP (left), AOP (result)) &&
8439 size >= MSB32 + offr && offr != LSB)
8440 emitcode ("xch", "a,%s",
8441 aopGet (left, MSB24 + offr, FALSE, FALSE));
8443 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8446 if (size > MSB32 + offr)
8448 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8450 l = aopGet (left, MSB32, FALSE, FALSE);
8453 emitcode ("rlc", "a");
8454 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8457 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8460 /*-----------------------------------------------------------------*/
8461 /* genlshFour - shift four byte by a known amount != 0 */
8462 /*-----------------------------------------------------------------*/
8464 genlshFour (operand * result, operand * left, int shCount)
8468 D(emitcode ("; genlshFour",""));
8470 size = AOP_SIZE (result);
8472 /* if shifting more that 3 bytes */
8477 /* lowest order of left goes to the highest
8478 order of the destination */
8479 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8481 movLeft2Result (left, LSB, result, MSB32, 0);
8482 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8483 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8484 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8488 /* more than two bytes */
8489 else if (shCount >= 16)
8491 /* lower order two bytes goes to higher order two bytes */
8493 /* if some more remaining */
8495 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8498 movLeft2Result (left, MSB16, result, MSB32, 0);
8499 movLeft2Result (left, LSB, result, MSB24, 0);
8501 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8502 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8506 /* if more than 1 byte */
8507 else if (shCount >= 8)
8509 /* lower order three bytes goes to higher order three bytes */
8514 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8516 movLeft2Result (left, LSB, result, MSB16, 0);
8522 movLeft2Result (left, MSB24, result, MSB32, 0);
8523 movLeft2Result (left, MSB16, result, MSB24, 0);
8524 movLeft2Result (left, LSB, result, MSB16, 0);
8525 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8527 else if (shCount == 1)
8528 shiftLLong (left, result, MSB16);
8531 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8532 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8533 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8534 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8539 /* 1 <= shCount <= 7 */
8540 else if (shCount <= 2)
8542 shiftLLong (left, result, LSB);
8544 shiftLLong (result, result, LSB);
8546 /* 3 <= shCount <= 7, optimize */
8549 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8550 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8551 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8555 /*-----------------------------------------------------------------*/
8556 /* genLeftShiftLiteral - left shifting by known count */
8557 /*-----------------------------------------------------------------*/
8559 genLeftShiftLiteral (operand * left,
8564 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8567 D(emitcode ("; genLeftShiftLiteral",""));
8569 freeAsmop (right, NULL, ic, TRUE);
8571 aopOp (left, ic, FALSE);
8572 aopOp (result, ic, FALSE);
8574 size = getSize (operandType (result));
8577 emitcode ("; shift left ", "result %d, left %d", size,
8581 /* I suppose that the left size >= result size */
8586 movLeft2Result (left, size, result, size, 0);
8590 else if (shCount >= (size * 8))
8592 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8598 genlshOne (result, left, shCount);
8602 genlshTwo (result, left, shCount);
8606 genlshFour (result, left, shCount);
8609 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8610 "*** ack! mystery literal shift!\n");
8614 freeAsmop (result, NULL, ic, TRUE);
8615 freeAsmop (left, NULL, ic, TRUE);
8618 /*-----------------------------------------------------------------*/
8619 /* genLeftShift - generates code for left shifting */
8620 /*-----------------------------------------------------------------*/
8622 genLeftShift (iCode * ic)
8624 operand *left, *right, *result;
8627 symbol *tlbl, *tlbl1;
8630 D(emitcode ("; genLeftShift",""));
8632 right = IC_RIGHT (ic);
8633 left = IC_LEFT (ic);
8634 result = IC_RESULT (ic);
8636 aopOp (right, ic, FALSE);
8638 /* if the shift count is known then do it
8639 as efficiently as possible */
8640 if (AOP_TYPE (right) == AOP_LIT)
8642 genLeftShiftLiteral (left, right, result, ic);
8646 /* shift count is unknown then we have to form
8647 a loop get the loop count in B : Note: we take
8648 only the lower order byte since shifting
8649 more that 32 bits make no sense anyway, ( the
8650 largest size of an object can be only 32 bits ) */
8653 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8654 emitcode ("inc", "b");
8655 freeAsmop (right, NULL, ic, TRUE);
8656 aopOp (left, ic, FALSE);
8657 aopOp (result, ic, FALSE);
8659 /* now move the left to the result if they are not the same */
8660 if (!sameRegs (AOP (left), AOP (result)) &&
8661 AOP_SIZE (result) > 1)
8664 size = AOP_SIZE (result);
8668 l = aopGet (left, offset, FALSE, TRUE);
8669 if (*l == '@' && (IS_AOP_PREG (result)))
8672 emitcode ("mov", "a,%s", l);
8673 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8676 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8681 tlbl = newiTempLabel (NULL);
8682 size = AOP_SIZE (result);
8684 tlbl1 = newiTempLabel (NULL);
8686 /* if it is only one byte then */
8689 symbol *tlbl1 = newiTempLabel (NULL);
8691 l = aopGet (left, 0, FALSE, FALSE);
8693 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8694 emitcode ("", "%05d$:", tlbl->key + 100);
8695 emitcode ("add", "a,acc");
8696 emitcode ("", "%05d$:", tlbl1->key + 100);
8697 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8699 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8703 reAdjustPreg (AOP (result));
8705 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8706 emitcode ("", "%05d$:", tlbl->key + 100);
8707 l = aopGet (result, offset, FALSE, FALSE);
8709 emitcode ("add", "a,acc");
8710 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8713 l = aopGet (result, offset, FALSE, FALSE);
8715 emitcode ("rlc", "a");
8716 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8718 reAdjustPreg (AOP (result));
8720 emitcode ("", "%05d$:", tlbl1->key + 100);
8721 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8724 freeAsmop (result, NULL, ic, TRUE);
8725 freeAsmop (left, NULL, ic, TRUE);
8728 /*-----------------------------------------------------------------*/
8729 /* genrshOne - right shift a one byte quantity by known count */
8730 /*-----------------------------------------------------------------*/
8732 genrshOne (operand * result, operand * left,
8733 int shCount, int sign)
8735 D(emitcode ("; genrshOne",""));
8737 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8740 /*-----------------------------------------------------------------*/
8741 /* genrshTwo - right shift two bytes by known amount != 0 */
8742 /*-----------------------------------------------------------------*/
8744 genrshTwo (operand * result, operand * left,
8745 int shCount, int sign)
8747 D(emitcode ("; genrshTwo",""));
8749 /* if shCount >= 8 */
8754 shiftR1Left2Result (left, MSB16, result, LSB,
8757 movLeft2Result (left, MSB16, result, LSB, sign);
8758 addSign (result, MSB16, sign);
8761 /* 1 <= shCount <= 7 */
8763 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8766 /*-----------------------------------------------------------------*/
8767 /* shiftRLong - shift right one long from left to result */
8768 /* offl = LSB or MSB16 */
8769 /*-----------------------------------------------------------------*/
8771 shiftRLong (operand * left, int offl,
8772 operand * result, int sign)
8774 int isSameRegs = sameRegs (AOP (left), AOP (result));
8776 if (isSameRegs && offl>1) {
8777 // we are in big trouble, but this shouldn't happen
8778 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8781 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8786 emitcode ("rlc", "a");
8787 emitcode ("subb", "a,acc");
8789 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8791 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8792 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8795 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8800 emitcode ("clr", "c");
8802 emitcode ("mov", "c,acc.7");
8805 emitcode ("rrc", "a");
8807 if (isSameRegs && offl==MSB16) {
8808 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8810 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8811 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8814 emitcode ("rrc", "a");
8815 if (isSameRegs && offl==1) {
8816 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8818 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8819 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8821 emitcode ("rrc", "a");
8822 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8826 MOVA (aopGet (left, LSB, FALSE, FALSE));
8827 emitcode ("rrc", "a");
8828 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8832 /*-----------------------------------------------------------------*/
8833 /* genrshFour - shift four byte by a known amount != 0 */
8834 /*-----------------------------------------------------------------*/
8836 genrshFour (operand * result, operand * left,
8837 int shCount, int sign)
8839 D(emitcode ("; genrshFour",""));
8841 /* if shifting more that 3 bytes */
8846 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8848 movLeft2Result (left, MSB32, result, LSB, sign);
8849 addSign (result, MSB16, sign);
8851 else if (shCount >= 16)
8855 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8858 movLeft2Result (left, MSB24, result, LSB, 0);
8859 movLeft2Result (left, MSB32, result, MSB16, sign);
8861 addSign (result, MSB24, sign);
8863 else if (shCount >= 8)
8867 shiftRLong (left, MSB16, result, sign);
8868 else if (shCount == 0)
8870 movLeft2Result (left, MSB16, result, LSB, 0);
8871 movLeft2Result (left, MSB24, result, MSB16, 0);
8872 movLeft2Result (left, MSB32, result, MSB24, sign);
8873 addSign (result, MSB32, sign);
8877 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8878 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8879 /* the last shift is signed */
8880 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8881 addSign (result, MSB32, sign);
8885 { /* 1 <= shCount <= 7 */
8888 shiftRLong (left, LSB, result, sign);
8890 shiftRLong (result, LSB, result, sign);
8894 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8895 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8896 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8901 /*-----------------------------------------------------------------*/
8902 /* genRightShiftLiteral - right shifting by known count */
8903 /*-----------------------------------------------------------------*/
8905 genRightShiftLiteral (operand * left,
8911 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8914 D(emitcode ("; genRightShiftLiteral",""));
8916 freeAsmop (right, NULL, ic, TRUE);
8918 aopOp (left, ic, FALSE);
8919 aopOp (result, ic, FALSE);
8922 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8926 size = getDataSize (left);
8927 /* test the LEFT size !!! */
8929 /* I suppose that the left size >= result size */
8932 size = getDataSize (result);
8934 movLeft2Result (left, size, result, size, 0);
8937 else if (shCount >= (size * 8))
8940 /* get sign in acc.7 */
8941 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8943 addSign (result, LSB, sign);
8950 genrshOne (result, left, shCount, sign);
8954 genrshTwo (result, left, shCount, sign);
8958 genrshFour (result, left, shCount, sign);
8964 freeAsmop (result, NULL, ic, TRUE);
8965 freeAsmop (left, NULL, ic, TRUE);
8968 /*-----------------------------------------------------------------*/
8969 /* genSignedRightShift - right shift of signed number */
8970 /*-----------------------------------------------------------------*/
8972 genSignedRightShift (iCode * ic)
8974 operand *right, *left, *result;
8977 symbol *tlbl, *tlbl1;
8980 D(emitcode ("; genSignedRightShift",""));
8982 /* we do it the hard way put the shift count in b
8983 and loop thru preserving the sign */
8985 right = IC_RIGHT (ic);
8986 left = IC_LEFT (ic);
8987 result = IC_RESULT (ic);
8989 aopOp (right, ic, FALSE);
8992 if (AOP_TYPE (right) == AOP_LIT)
8994 genRightShiftLiteral (left, right, result, ic, 1);
8997 /* shift count is unknown then we have to form
8998 a loop get the loop count in B : Note: we take
8999 only the lower order byte since shifting
9000 more that 32 bits make no sense anyway, ( the
9001 largest size of an object can be only 32 bits ) */
9004 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9005 emitcode ("inc", "b");
9006 freeAsmop (right, NULL, ic, TRUE);
9007 aopOp (left, ic, FALSE);
9008 aopOp (result, ic, FALSE);
9010 /* now move the left to the result if they are not the
9012 if (!sameRegs (AOP (left), AOP (result)) &&
9013 AOP_SIZE (result) > 1)
9016 size = AOP_SIZE (result);
9020 l = aopGet (left, offset, FALSE, TRUE);
9021 if (*l == '@' && IS_AOP_PREG (result))
9024 emitcode ("mov", "a,%s", l);
9025 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9028 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9033 /* mov the highest order bit to OVR */
9034 tlbl = newiTempLabel (NULL);
9035 tlbl1 = newiTempLabel (NULL);
9037 size = AOP_SIZE (result);
9039 MOVA (aopGet (left, offset, FALSE, FALSE));
9040 emitcode ("rlc", "a");
9041 emitcode ("mov", "ov,c");
9042 /* if it is only one byte then */
9045 l = aopGet (left, 0, FALSE, FALSE);
9047 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9048 emitcode ("", "%05d$:", tlbl->key + 100);
9049 emitcode ("mov", "c,ov");
9050 emitcode ("rrc", "a");
9051 emitcode ("", "%05d$:", tlbl1->key + 100);
9052 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9054 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9058 reAdjustPreg (AOP (result));
9059 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9060 emitcode ("", "%05d$:", tlbl->key + 100);
9061 emitcode ("mov", "c,ov");
9064 l = aopGet (result, offset, FALSE, FALSE);
9066 emitcode ("rrc", "a");
9067 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9069 reAdjustPreg (AOP (result));
9070 emitcode ("", "%05d$:", tlbl1->key + 100);
9071 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9075 freeAsmop (result, NULL, ic, TRUE);
9076 freeAsmop (left, NULL, ic, TRUE);
9079 /*-----------------------------------------------------------------*/
9080 /* genRightShift - generate code for right shifting */
9081 /*-----------------------------------------------------------------*/
9083 genRightShift (iCode * ic)
9085 operand *right, *left, *result;
9089 symbol *tlbl, *tlbl1;
9092 D(emitcode ("; genRightShift",""));
9094 /* if signed then we do it the hard way preserve the
9095 sign bit moving it inwards */
9096 letype = getSpec (operandType (IC_LEFT (ic)));
9098 if (!SPEC_USIGN (letype))
9100 genSignedRightShift (ic);
9104 /* signed & unsigned types are treated the same : i.e. the
9105 signed is NOT propagated inwards : quoting from the
9106 ANSI - standard : "for E1 >> E2, is equivalent to division
9107 by 2**E2 if unsigned or if it has a non-negative value,
9108 otherwise the result is implementation defined ", MY definition
9109 is that the sign does not get propagated */
9111 right = IC_RIGHT (ic);
9112 left = IC_LEFT (ic);
9113 result = IC_RESULT (ic);
9115 aopOp (right, ic, FALSE);
9117 /* if the shift count is known then do it
9118 as efficiently as possible */
9119 if (AOP_TYPE (right) == AOP_LIT)
9121 genRightShiftLiteral (left, right, result, ic, 0);
9125 /* shift count is unknown then we have to form
9126 a loop get the loop count in B : Note: we take
9127 only the lower order byte since shifting
9128 more that 32 bits make no sense anyway, ( the
9129 largest size of an object can be only 32 bits ) */
9132 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9133 emitcode ("inc", "b");
9134 freeAsmop (right, NULL, ic, TRUE);
9135 aopOp (left, ic, FALSE);
9136 aopOp (result, ic, FALSE);
9138 /* now move the left to the result if they are not the
9140 if (!sameRegs (AOP (left), AOP (result)) &&
9141 AOP_SIZE (result) > 1)
9144 size = AOP_SIZE (result);
9148 l = aopGet (left, offset, FALSE, TRUE);
9149 if (*l == '@' && IS_AOP_PREG (result))
9152 emitcode ("mov", "a,%s", l);
9153 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9156 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9161 tlbl = newiTempLabel (NULL);
9162 tlbl1 = newiTempLabel (NULL);
9163 size = AOP_SIZE (result);
9166 /* if it is only one byte then */
9169 l = aopGet (left, 0, FALSE, FALSE);
9171 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9172 emitcode ("", "%05d$:", tlbl->key + 100);
9174 emitcode ("rrc", "a");
9175 emitcode ("", "%05d$:", tlbl1->key + 100);
9176 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9178 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9182 reAdjustPreg (AOP (result));
9183 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9184 emitcode ("", "%05d$:", tlbl->key + 100);
9188 l = aopGet (result, offset, FALSE, FALSE);
9190 emitcode ("rrc", "a");
9191 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9193 reAdjustPreg (AOP (result));
9195 emitcode ("", "%05d$:", tlbl1->key + 100);
9196 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9200 freeAsmop (result, NULL, ic, TRUE);
9201 freeAsmop (left, NULL, ic, TRUE);
9204 /*-----------------------------------------------------------------*/
9205 /* emitPtrByteGet - emits code to get a byte into A through a */
9206 /* pointer register (R0, R1, or DPTR). The */
9207 /* original value of A can be preserved in B. */
9208 /*-----------------------------------------------------------------*/
9210 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9217 emitcode ("mov", "b,a");
9218 emitcode ("mov", "a,@%s", rname);
9223 emitcode ("mov", "b,a");
9224 emitcode ("movx", "a,@%s", rname);
9229 emitcode ("mov", "b,a");
9230 emitcode ("movx", "a,@dptr");
9235 emitcode ("mov", "b,a");
9236 emitcode ("clr", "a");
9237 emitcode ("movc", "a,@a+dptr");
9243 emitcode ("push", "b");
9244 emitcode ("push", "acc");
9246 emitcode ("lcall", "__gptrget");
9248 emitcode ("pop", "b");
9253 /*-----------------------------------------------------------------*/
9254 /* emitPtrByteSet - emits code to set a byte from src through a */
9255 /* pointer register (R0, R1, or DPTR). */
9256 /*-----------------------------------------------------------------*/
9258 emitPtrByteSet (char *rname, int p_type, char *src)
9267 emitcode ("mov", "@%s,a", rname);
9270 emitcode ("mov", "@%s,%s", rname, src);
9275 emitcode ("movx", "@%s,a", rname);
9280 emitcode ("movx", "@dptr,a");
9285 emitcode ("lcall", "__gptrput");
9290 /*-----------------------------------------------------------------*/
9291 /* genUnpackBits - generates code for unpacking bits */
9292 /*-----------------------------------------------------------------*/
9294 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9296 int offset = 0; /* result byte offset */
9297 int rsize; /* result size */
9298 int rlen = 0; /* remaining bitfield length */
9299 sym_link *etype; /* bitfield type information */
9300 int blen; /* bitfield length */
9301 int bstr; /* bitfield starting bit within byte */
9304 D(emitcode ("; genUnpackBits",""));
9306 etype = getSpec (operandType (result));
9307 rsize = getSize (operandType (result));
9308 blen = SPEC_BLEN (etype);
9309 bstr = SPEC_BSTR (etype);
9311 if (ifx && blen <= 8)
9313 emitPtrByteGet (rname, ptype, FALSE);
9316 SNPRINTF (buffer, sizeof(buffer),
9318 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9323 emitcode ("anl", "a,#0x%02x",
9324 (((unsigned char) -1) >> (8 - blen)) << bstr);
9325 genIfxJump (ifx, "a", NULL, NULL, NULL);
9331 /* If the bitfield length is less than a byte */
9334 emitPtrByteGet (rname, ptype, FALSE);
9336 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9337 if (!SPEC_USIGN (etype))
9339 /* signed bitfield */
9340 symbol *tlbl = newiTempLabel (NULL);
9342 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9343 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9344 emitcode ("", "%05d$:", tlbl->key + 100);
9346 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9350 /* Bit field did not fit in a byte. Copy all
9351 but the partial byte at the end. */
9352 for (rlen=blen;rlen>=8;rlen-=8)
9354 emitPtrByteGet (rname, ptype, FALSE);
9355 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9357 emitcode ("inc", "%s", rname);
9360 /* Handle the partial byte at the end */
9363 emitPtrByteGet (rname, ptype, FALSE);
9364 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9365 if (!SPEC_USIGN (etype))
9367 /* signed bitfield */
9368 symbol *tlbl = newiTempLabel (NULL);
9370 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9371 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9372 emitcode ("", "%05d$:", tlbl->key + 100);
9374 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9382 if (SPEC_USIGN (etype))
9386 /* signed bitfield: sign extension with 0x00 or 0xff */
9387 emitcode ("rlc", "a");
9388 emitcode ("subb", "a,acc");
9394 aopPut (result, source, offset++, isOperandVolatile (result, FALSE));
9399 /*-----------------------------------------------------------------*/
9400 /* genDataPointerGet - generates code when ptr offset is known */
9401 /*-----------------------------------------------------------------*/
9403 genDataPointerGet (operand * left,
9409 int size, offset = 0;
9411 D(emitcode ("; genDataPointerGet",""));
9413 aopOp (result, ic, TRUE);
9415 /* get the string representation of the name */
9416 l = aopGet (left, 0, FALSE, TRUE);
9417 size = AOP_SIZE (result);
9421 sprintf (buffer, "(%s + %d)", l + 1, offset);
9423 sprintf (buffer, "%s", l + 1);
9424 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9427 freeAsmop (result, NULL, ic, TRUE);
9428 freeAsmop (left, NULL, ic, TRUE);
9431 /*-----------------------------------------------------------------*/
9432 /* genNearPointerGet - emitcode for near pointer fetch */
9433 /*-----------------------------------------------------------------*/
9435 genNearPointerGet (operand * left,
9444 sym_link *rtype, *retype;
9445 sym_link *ltype = operandType (left);
9448 D(emitcode ("; genNearPointerGet",""));
9450 rtype = operandType (result);
9451 retype = getSpec (rtype);
9453 aopOp (left, ic, FALSE);
9455 /* if left is rematerialisable and
9456 result is not bitfield variable type and
9457 the left is pointer to data space i.e
9458 lower 128 bytes of space */
9459 if (AOP_TYPE (left) == AOP_IMMD &&
9460 !IS_BITFIELD (retype) &&
9461 DCL_TYPE (ltype) == POINTER)
9463 genDataPointerGet (left, result, ic);
9467 /* if the value is already in a pointer register
9468 then don't need anything more */
9469 if (!AOP_INPREG (AOP (left)))
9471 if (IS_AOP_PREG (left))
9473 // Aha, it is a pointer, just in disguise.
9474 rname = aopGet (left, 0, FALSE, FALSE);
9477 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9478 __FILE__, __LINE__);
9483 emitcode ("mov", "a%s,%s", rname + 1, rname);
9484 rname++; // skip the '@'.
9489 /* otherwise get a free pointer register */
9491 preg = getFreePtr (ic, &aop, FALSE);
9492 emitcode ("mov", "%s,%s",
9494 aopGet (left, 0, FALSE, TRUE));
9499 rname = aopGet (left, 0, FALSE, FALSE);
9501 //aopOp (result, ic, FALSE);
9502 aopOp (result, ic, result?TRUE:FALSE);
9504 /* if bitfield then unpack the bits */
9505 if (IS_BITFIELD (retype))
9506 genUnpackBits (result, rname, POINTER, ifx);
9509 /* we have can just get the values */
9510 int size = AOP_SIZE (result);
9515 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9518 emitcode ("mov", "a,@%s", rname);
9520 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9524 sprintf (buffer, "@%s", rname);
9525 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9529 emitcode ("inc", "%s", rname);
9533 /* now some housekeeping stuff */
9534 if (aop) /* we had to allocate for this iCode */
9536 if (pi) { /* post increment present */
9537 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9539 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9543 /* we did not allocate which means left
9544 already in a pointer register, then
9545 if size > 0 && this could be used again
9546 we have to point it back to where it
9548 if ((AOP_SIZE (result) > 1 &&
9549 !OP_SYMBOL (left)->remat &&
9550 (OP_SYMBOL (left)->liveTo > ic->seq ||
9554 int size = AOP_SIZE (result) - 1;
9556 emitcode ("dec", "%s", rname);
9560 if (ifx && !ifx->generated)
9562 genIfxJump (ifx, "a", left, NULL, result);
9566 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9567 freeAsmop (left, NULL, ic, TRUE);
9568 if (pi) pi->generated = 1;
9571 /*-----------------------------------------------------------------*/
9572 /* genPagedPointerGet - emitcode for paged pointer fetch */
9573 /*-----------------------------------------------------------------*/
9575 genPagedPointerGet (operand * left,
9584 sym_link *rtype, *retype;
9586 D(emitcode ("; genPagedPointerGet",""));
9588 rtype = operandType (result);
9589 retype = getSpec (rtype);
9591 aopOp (left, ic, FALSE);
9593 /* if the value is already in a pointer register
9594 then don't need anything more */
9595 if (!AOP_INPREG (AOP (left)))
9597 /* otherwise get a free pointer register */
9599 preg = getFreePtr (ic, &aop, FALSE);
9600 emitcode ("mov", "%s,%s",
9602 aopGet (left, 0, FALSE, TRUE));
9606 rname = aopGet (left, 0, FALSE, FALSE);
9608 aopOp (result, ic, FALSE);
9610 /* if bitfield then unpack the bits */
9611 if (IS_BITFIELD (retype))
9612 genUnpackBits (result, rname, PPOINTER, ifx);
9615 /* we have can just get the values */
9616 int size = AOP_SIZE (result);
9622 emitcode ("movx", "a,@%s", rname);
9624 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9629 emitcode ("inc", "%s", rname);
9633 /* now some housekeeping stuff */
9634 if (aop) /* we had to allocate for this iCode */
9636 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9637 freeAsmop (NULL, aop, ic, TRUE);
9641 /* we did not allocate which means left
9642 already in a pointer register, then
9643 if size > 0 && this could be used again
9644 we have to point it back to where it
9646 if ((AOP_SIZE (result) > 1 &&
9647 !OP_SYMBOL (left)->remat &&
9648 (OP_SYMBOL (left)->liveTo > ic->seq ||
9652 int size = AOP_SIZE (result) - 1;
9654 emitcode ("dec", "%s", rname);
9658 if (ifx && !ifx->generated)
9660 genIfxJump (ifx, "a", left, NULL, result);
9664 freeAsmop (result, NULL, ic, TRUE);
9665 freeAsmop (left, NULL, ic, TRUE);
9666 if (pi) pi->generated = 1;
9669 /*--------------------------------------------------------------------*/
9670 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9671 /*--------------------------------------------------------------------*/
9673 loadDptrFromOperand (operand *op, bool loadBToo)
9675 if (AOP_TYPE (op) != AOP_STR)
9677 /* if this is rematerializable */
9678 if (AOP_TYPE (op) == AOP_IMMD)
9680 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9683 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9684 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9687 wassertl(FALSE, "need pointerCode");
9688 emitcode ("", "; mov b,???");
9689 /* genPointerGet and genPointerSet originally did different
9690 ** things for this case. Both seem wrong.
9691 ** from genPointerGet:
9692 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9693 ** from genPointerSet:
9694 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9699 else if (AOP_TYPE (op) == AOP_DPTR)
9703 MOVA (aopGet (op, 0, FALSE, FALSE));
9704 emitcode ("push", "acc");
9705 MOVA (aopGet (op, 1, FALSE, FALSE));
9706 emitcode ("push", "acc");
9707 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9708 emitcode ("pop", "dph");
9709 emitcode ("pop", "dpl");
9713 MOVA (aopGet (op, 0, FALSE, FALSE));
9714 emitcode ("push", "acc");
9715 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9716 emitcode ("pop", "dpl");
9720 { /* we need to get it byte by byte */
9721 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9722 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9724 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9729 /*-----------------------------------------------------------------*/
9730 /* genFarPointerGet - gget value from far space */
9731 /*-----------------------------------------------------------------*/
9733 genFarPointerGet (operand * left,
9734 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9737 sym_link *retype = getSpec (operandType (result));
9739 D(emitcode ("; genFarPointerGet",""));
9741 aopOp (left, ic, FALSE);
9742 loadDptrFromOperand (left, FALSE);
9744 /* so dptr now contains the address */
9745 aopOp (result, ic, FALSE);
9747 /* if bit then unpack */
9748 if (IS_BITFIELD (retype))
9749 genUnpackBits (result, "dptr", FPOINTER, ifx);
9752 size = AOP_SIZE (result);
9757 emitcode ("movx", "a,@dptr");
9759 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9761 emitcode ("inc", "dptr");
9765 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9767 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9768 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9772 if (ifx && !ifx->generated)
9774 genIfxJump (ifx, "a", left, NULL, result);
9777 freeAsmop (result, NULL, ic, TRUE);
9778 freeAsmop (left, NULL, ic, TRUE);
9781 /*-----------------------------------------------------------------*/
9782 /* genCodePointerGet - gget value from code space */
9783 /*-----------------------------------------------------------------*/
9785 genCodePointerGet (operand * left,
9786 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9789 sym_link *retype = getSpec (operandType (result));
9791 D(emitcode ("; genCodePointerGet",""));
9793 aopOp (left, ic, FALSE);
9794 loadDptrFromOperand (left, FALSE);
9796 /* so dptr now contains the address */
9797 aopOp (result, ic, FALSE);
9799 /* if bit then unpack */
9800 if (IS_BITFIELD (retype))
9801 genUnpackBits (result, "dptr", CPOINTER, ifx);
9804 size = AOP_SIZE (result);
9811 emitcode ("clr", "a");
9812 emitcode ("movc", "a,@a+dptr");
9814 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9815 emitcode ("inc", "dptr");
9819 emitcode ("mov", "a,#0x%02x", offset);
9820 emitcode ("movc", "a,@a+dptr");
9822 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9827 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9829 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9830 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9834 if (ifx && !ifx->generated)
9836 genIfxJump (ifx, "a", left, NULL, result);
9839 freeAsmop (result, NULL, ic, TRUE);
9840 freeAsmop (left, NULL, ic, TRUE);
9843 /*-----------------------------------------------------------------*/
9844 /* genGenPointerGet - gget value from generic pointer space */
9845 /*-----------------------------------------------------------------*/
9847 genGenPointerGet (operand * left,
9848 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9851 sym_link *retype = getSpec (operandType (result));
9853 D(emitcode ("; genGenPointerGet",""));
9855 aopOp (left, ic, FALSE);
9856 loadDptrFromOperand (left, TRUE);
9858 /* so dptr know contains the address */
9859 aopOp (result, ic, FALSE);
9861 /* if bit then unpack */
9862 if (IS_BITFIELD (retype))
9863 genUnpackBits (result, "dptr", GPOINTER, ifx);
9866 size = AOP_SIZE (result);
9871 emitcode ("lcall", "__gptrget");
9873 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9875 emitcode ("inc", "dptr");
9879 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9881 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9882 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9886 if (ifx && !ifx->generated)
9888 genIfxJump (ifx, "a", left, NULL, result);
9891 freeAsmop (result, NULL, ic, TRUE);
9892 freeAsmop (left, NULL, ic, TRUE);
9895 /*-----------------------------------------------------------------*/
9896 /* genPointerGet - generate code for pointer get */
9897 /*-----------------------------------------------------------------*/
9899 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9901 operand *left, *result;
9902 sym_link *type, *etype;
9905 D(emitcode ("; genPointerGet",""));
9907 left = IC_LEFT (ic);
9908 result = IC_RESULT (ic);
9910 if (getSize (operandType (result))>1)
9913 /* depending on the type of pointer we need to
9914 move it to the correct pointer register */
9915 type = operandType (left);
9916 etype = getSpec (type);
9917 /* if left is of type of pointer then it is simple */
9918 if (IS_PTR (type) && !IS_FUNC (type->next))
9919 p_type = DCL_TYPE (type);
9922 /* we have to go by the storage class */
9923 p_type = PTR_TYPE (SPEC_OCLS (etype));
9926 /* special case when cast remat */
9927 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9928 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9929 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9930 type = operandType (left);
9931 p_type = DCL_TYPE (type);
9933 /* now that we have the pointer type we assign
9934 the pointer values */
9940 genNearPointerGet (left, result, ic, pi, ifx);
9944 genPagedPointerGet (left, result, ic, pi, ifx);
9948 genFarPointerGet (left, result, ic, pi, ifx);
9952 genCodePointerGet (left, result, ic, pi, ifx);
9956 genGenPointerGet (left, result, ic, pi, ifx);
9964 /*-----------------------------------------------------------------*/
9965 /* genPackBits - generates code for packed bit storage */
9966 /*-----------------------------------------------------------------*/
9968 genPackBits (sym_link * etype,
9970 char *rname, int p_type)
9972 int offset = 0; /* source byte offset */
9973 int rlen = 0; /* remaining bitfield length */
9974 int blen; /* bitfield length */
9975 int bstr; /* bitfield starting bit within byte */
9976 int litval; /* source literal value (if AOP_LIT) */
9977 unsigned char mask; /* bitmask within current byte */
9979 D(emitcode ("; genPackBits",""));
9981 blen = SPEC_BLEN (etype);
9982 bstr = SPEC_BSTR (etype);
9984 /* If the bitfield length is less than a byte */
9987 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9988 (unsigned char) (0xFF >> (8 - bstr)));
9990 if (AOP_TYPE (right) == AOP_LIT)
9992 /* Case with a bitfield length <8 and literal source
9994 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9996 litval &= (~mask) & 0xff;
9997 emitPtrByteGet (rname, p_type, FALSE);
9998 if ((mask|litval)!=0xff)
9999 emitcode ("anl","a,#0x%02x", mask);
10001 emitcode ("orl","a,#0x%02x", litval);
10005 if ((blen==1) && (p_type!=GPOINTER))
10007 /* Case with a bitfield length == 1 and no generic pointer
10009 if (AOP_TYPE (right) == AOP_CRY)
10010 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
10013 MOVA (aopGet (right, 0, FALSE, FALSE));
10014 emitcode ("rrc","a");
10016 emitPtrByteGet (rname, p_type, FALSE);
10017 emitcode ("mov","acc.%d,c",bstr);
10022 /* Case with a bitfield length < 8 and arbitrary source
10024 MOVA (aopGet (right, 0, FALSE, FALSE));
10025 /* shift and mask source value */
10027 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10029 pushedB = pushB ();
10030 /* transfer A to B and get next byte */
10031 emitPtrByteGet (rname, p_type, TRUE);
10033 emitcode ("anl", "a,#0x%02x", mask);
10034 emitcode ("orl", "a,b");
10035 if (p_type == GPOINTER)
10036 emitcode ("pop", "b");
10042 emitPtrByteSet (rname, p_type, "a");
10046 /* Bit length is greater than 7 bits. In this case, copy */
10047 /* all except the partial byte at the end */
10048 for (rlen=blen;rlen>=8;rlen-=8)
10050 emitPtrByteSet (rname, p_type,
10051 aopGet (right, offset++, FALSE, TRUE) );
10053 emitcode ("inc", "%s", rname);
10056 /* If there was a partial byte at the end */
10059 mask = (((unsigned char) -1 << rlen) & 0xff);
10061 if (AOP_TYPE (right) == AOP_LIT)
10063 /* Case with partial byte and literal source
10065 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10066 litval >>= (blen-rlen);
10067 litval &= (~mask) & 0xff;
10068 emitPtrByteGet (rname, p_type, FALSE);
10069 if ((mask|litval)!=0xff)
10070 emitcode ("anl","a,#0x%02x", mask);
10072 emitcode ("orl","a,#0x%02x", litval);
10077 /* Case with partial byte and arbitrary source
10079 MOVA (aopGet (right, offset++, FALSE, FALSE));
10080 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10082 pushedB = pushB ();
10083 /* transfer A to B and get next byte */
10084 emitPtrByteGet (rname, p_type, TRUE);
10086 emitcode ("anl", "a,#0x%02x", mask);
10087 emitcode ("orl", "a,b");
10088 if (p_type == GPOINTER)
10089 emitcode ("pop", "b");
10093 emitPtrByteSet (rname, p_type, "a");
10099 /*-----------------------------------------------------------------*/
10100 /* genDataPointerSet - remat pointer to data space */
10101 /*-----------------------------------------------------------------*/
10103 genDataPointerSet (operand * right,
10107 int size, offset = 0;
10108 char *l, buffer[256];
10110 D(emitcode ("; genDataPointerSet",""));
10112 aopOp (right, ic, FALSE);
10114 l = aopGet (result, 0, FALSE, TRUE);
10115 size = AOP_SIZE (right);
10119 sprintf (buffer, "(%s + %d)", l + 1, offset);
10121 sprintf (buffer, "%s", l + 1);
10122 emitcode ("mov", "%s,%s", buffer,
10123 aopGet (right, offset++, FALSE, FALSE));
10126 freeAsmop (result, NULL, ic, TRUE);
10127 freeAsmop (right, NULL, ic, TRUE);
10130 /*-----------------------------------------------------------------*/
10131 /* genNearPointerSet - emitcode for near pointer put */
10132 /*-----------------------------------------------------------------*/
10134 genNearPointerSet (operand * right,
10142 sym_link *retype, *letype;
10143 sym_link *ptype = operandType (result);
10145 D(emitcode ("; genNearPointerSet",""));
10147 retype = getSpec (operandType (right));
10148 letype = getSpec (ptype);
10149 aopOp (result, ic, FALSE);
10151 /* if the result is rematerializable &
10152 in data space & not a bit variable */
10153 if (AOP_TYPE (result) == AOP_IMMD &&
10154 DCL_TYPE (ptype) == POINTER &&
10155 !IS_BITVAR (retype) &&
10156 !IS_BITVAR (letype))
10158 genDataPointerSet (right, result, ic);
10162 /* if the value is already in a pointer register
10163 then don't need anything more */
10164 if (!AOP_INPREG (AOP (result)))
10167 //AOP_TYPE (result) == AOP_STK
10168 IS_AOP_PREG(result)
10171 // Aha, it is a pointer, just in disguise.
10172 rname = aopGet (result, 0, FALSE, FALSE);
10175 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10176 __FILE__, __LINE__);
10181 emitcode ("mov", "a%s,%s", rname + 1, rname);
10182 rname++; // skip the '@'.
10187 /* otherwise get a free pointer register */
10188 aop = newAsmop (0);
10189 preg = getFreePtr (ic, &aop, FALSE);
10190 emitcode ("mov", "%s,%s",
10192 aopGet (result, 0, FALSE, TRUE));
10193 rname = preg->name;
10198 rname = aopGet (result, 0, FALSE, FALSE);
10201 aopOp (right, ic, FALSE);
10203 /* if bitfield then unpack the bits */
10204 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10205 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10208 /* we have can just get the values */
10209 int size = AOP_SIZE (right);
10214 l = aopGet (right, offset, FALSE, TRUE);
10218 emitcode ("mov", "@%s,a", rname);
10221 emitcode ("mov", "@%s,%s", rname, l);
10223 emitcode ("inc", "%s", rname);
10228 /* now some housekeeping stuff */
10229 if (aop) /* we had to allocate for this iCode */
10232 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10233 freeAsmop (NULL, aop, ic, TRUE);
10237 /* we did not allocate which means left
10238 already in a pointer register, then
10239 if size > 0 && this could be used again
10240 we have to point it back to where it
10242 if ((AOP_SIZE (right) > 1 &&
10243 !OP_SYMBOL (result)->remat &&
10244 (OP_SYMBOL (result)->liveTo > ic->seq ||
10248 int size = AOP_SIZE (right) - 1;
10250 emitcode ("dec", "%s", rname);
10255 if (pi) pi->generated = 1;
10256 freeAsmop (result, NULL, ic, TRUE);
10257 freeAsmop (right, NULL, ic, TRUE);
10260 /*-----------------------------------------------------------------*/
10261 /* genPagedPointerSet - emitcode for Paged pointer put */
10262 /*-----------------------------------------------------------------*/
10264 genPagedPointerSet (operand * right,
10272 sym_link *retype, *letype;
10274 D(emitcode ("; genPagedPointerSet",""));
10276 retype = getSpec (operandType (right));
10277 letype = getSpec (operandType (result));
10279 aopOp (result, ic, FALSE);
10281 /* if the value is already in a pointer register
10282 then don't need anything more */
10283 if (!AOP_INPREG (AOP (result)))
10285 /* otherwise get a free pointer register */
10286 aop = newAsmop (0);
10287 preg = getFreePtr (ic, &aop, FALSE);
10288 emitcode ("mov", "%s,%s",
10290 aopGet (result, 0, FALSE, TRUE));
10291 rname = preg->name;
10294 rname = aopGet (result, 0, FALSE, FALSE);
10296 aopOp (right, ic, FALSE);
10298 /* if bitfield then unpack the bits */
10299 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10300 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10303 /* we have can just get the values */
10304 int size = AOP_SIZE (right);
10309 l = aopGet (right, offset, FALSE, TRUE);
10312 emitcode ("movx", "@%s,a", rname);
10315 emitcode ("inc", "%s", rname);
10321 /* now some housekeeping stuff */
10322 if (aop) /* we had to allocate for this iCode */
10325 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10326 freeAsmop (NULL, aop, ic, TRUE);
10330 /* we did not allocate which means left
10331 already in a pointer register, then
10332 if size > 0 && this could be used again
10333 we have to point it back to where it
10335 if (AOP_SIZE (right) > 1 &&
10336 !OP_SYMBOL (result)->remat &&
10337 (OP_SYMBOL (result)->liveTo > ic->seq ||
10340 int size = AOP_SIZE (right) - 1;
10342 emitcode ("dec", "%s", rname);
10347 if (pi) pi->generated = 1;
10348 freeAsmop (result, NULL, ic, TRUE);
10349 freeAsmop (right, NULL, ic, TRUE);
10352 /*-----------------------------------------------------------------*/
10353 /* genFarPointerSet - set value from far space */
10354 /*-----------------------------------------------------------------*/
10356 genFarPointerSet (operand * right,
10357 operand * result, iCode * ic, iCode * pi)
10360 sym_link *retype = getSpec (operandType (right));
10361 sym_link *letype = getSpec (operandType (result));
10363 D(emitcode ("; genFarPointerSet",""));
10365 aopOp (result, ic, FALSE);
10366 loadDptrFromOperand (result, FALSE);
10368 /* so dptr know contains the address */
10369 aopOp (right, ic, FALSE);
10371 /* if bit then unpack */
10372 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10373 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10376 size = AOP_SIZE (right);
10381 char *l = aopGet (right, offset++, FALSE, FALSE);
10383 emitcode ("movx", "@dptr,a");
10385 emitcode ("inc", "dptr");
10388 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10389 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10390 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10393 freeAsmop (result, NULL, ic, TRUE);
10394 freeAsmop (right, NULL, ic, TRUE);
10397 /*-----------------------------------------------------------------*/
10398 /* genGenPointerSet - set value from generic pointer space */
10399 /*-----------------------------------------------------------------*/
10401 genGenPointerSet (operand * right,
10402 operand * result, iCode * ic, iCode * pi)
10405 sym_link *retype = getSpec (operandType (right));
10406 sym_link *letype = getSpec (operandType (result));
10408 D(emitcode ("; genGenPointerSet",""));
10410 aopOp (result, ic, FALSE);
10411 loadDptrFromOperand (result, TRUE);
10413 /* so dptr know contains the address */
10414 aopOp (right, ic, FALSE);
10416 /* if bit then unpack */
10417 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10418 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10421 size = AOP_SIZE (right);
10426 char *l = aopGet (right, offset++, FALSE, FALSE);
10428 emitcode ("lcall", "__gptrput");
10430 emitcode ("inc", "dptr");
10434 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10435 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10436 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10439 freeAsmop (result, NULL, ic, TRUE);
10440 freeAsmop (right, NULL, ic, TRUE);
10443 /*-----------------------------------------------------------------*/
10444 /* genPointerSet - stores the value into a pointer location */
10445 /*-----------------------------------------------------------------*/
10447 genPointerSet (iCode * ic, iCode *pi)
10449 operand *right, *result;
10450 sym_link *type, *etype;
10453 D(emitcode ("; genPointerSet",""));
10455 right = IC_RIGHT (ic);
10456 result = IC_RESULT (ic);
10458 /* depending on the type of pointer we need to
10459 move it to the correct pointer register */
10460 type = operandType (result);
10461 etype = getSpec (type);
10462 /* if left is of type of pointer then it is simple */
10463 if (IS_PTR (type) && !IS_FUNC (type->next))
10465 p_type = DCL_TYPE (type);
10469 /* we have to go by the storage class */
10470 p_type = PTR_TYPE (SPEC_OCLS (etype));
10473 /* special case when cast remat */
10474 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10475 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10476 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10477 type = operandType (result);
10478 p_type = DCL_TYPE (type);
10480 /* now that we have the pointer type we assign
10481 the pointer values */
10487 genNearPointerSet (right, result, ic, pi);
10491 genPagedPointerSet (right, result, ic, pi);
10495 genFarPointerSet (right, result, ic, pi);
10499 genGenPointerSet (right, result, ic, pi);
10503 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10504 "genPointerSet: illegal pointer type");
10509 /*-----------------------------------------------------------------*/
10510 /* genIfx - generate code for Ifx statement */
10511 /*-----------------------------------------------------------------*/
10513 genIfx (iCode * ic, iCode * popIc)
10515 operand *cond = IC_COND (ic);
10519 D(emitcode ("; genIfx",""));
10521 aopOp (cond, ic, FALSE);
10523 /* get the value into acc */
10524 if (AOP_TYPE (cond) != AOP_CRY)
10529 if (AOP(cond)->aopu.aop_dir)
10530 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10532 /* the result is now in the accumulator or a directly addressable bit */
10533 freeAsmop (cond, NULL, ic, TRUE);
10535 /* if there was something to be popped then do it */
10539 /* if the condition is a bit variable */
10541 genIfxJump(ic, dup, NULL, NULL, NULL);
10542 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10543 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10544 else if (isbit && !IS_ITEMP (cond))
10545 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10547 genIfxJump (ic, "a", NULL, NULL, NULL);
10552 /*-----------------------------------------------------------------*/
10553 /* genAddrOf - generates code for address of */
10554 /*-----------------------------------------------------------------*/
10556 genAddrOf (iCode * ic)
10558 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10561 D(emitcode ("; genAddrOf",""));
10563 aopOp (IC_RESULT (ic), ic, FALSE);
10565 /* if the operand is on the stack then we
10566 need to get the stack offset of this
10570 /* if it has an offset then we need to compute
10574 emitcode ("mov", "a,%s", SYM_BP (sym));
10575 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10576 ((char) (sym->stack - _G.nRegsSaved)) :
10577 ((char) sym->stack)) & 0xff);
10578 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10582 /* we can just move _bp */
10583 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10585 /* fill the result with zero */
10586 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10591 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10597 /* object not on stack then we need the name */
10598 size = AOP_SIZE (IC_RESULT (ic));
10603 char s[SDCC_NAME_MAX];
10605 sprintf (s, "#(%s >> %d)",
10609 sprintf (s, "#%s", sym->rname);
10610 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10614 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10618 /*-----------------------------------------------------------------*/
10619 /* genFarFarAssign - assignment when both are in far space */
10620 /*-----------------------------------------------------------------*/
10622 genFarFarAssign (operand * result, operand * right, iCode * ic)
10624 int size = AOP_SIZE (right);
10628 D(emitcode ("; genFarFarAssign",""));
10630 /* first push the right side on to the stack */
10633 l = aopGet (right, offset++, FALSE, FALSE);
10635 emitcode ("push", "acc");
10638 freeAsmop (right, NULL, ic, FALSE);
10639 /* now assign DPTR to result */
10640 aopOp (result, ic, FALSE);
10641 size = AOP_SIZE (result);
10644 emitcode ("pop", "acc");
10645 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10647 freeAsmop (result, NULL, ic, FALSE);
10650 /*-----------------------------------------------------------------*/
10651 /* genAssign - generate code for assignment */
10652 /*-----------------------------------------------------------------*/
10654 genAssign (iCode * ic)
10656 operand *result, *right;
10658 unsigned long lit = 0L;
10660 D(emitcode("; genAssign",""));
10662 result = IC_RESULT (ic);
10663 right = IC_RIGHT (ic);
10665 /* if they are the same */
10666 if (operandsEqu (result, right) &&
10667 !isOperandVolatile (result, FALSE) &&
10668 !isOperandVolatile (right, FALSE))
10671 aopOp (right, ic, FALSE);
10673 /* special case both in far space */
10674 if (AOP_TYPE (right) == AOP_DPTR &&
10675 IS_TRUE_SYMOP (result) &&
10676 isOperandInFarSpace (result))
10679 genFarFarAssign (result, right, ic);
10683 aopOp (result, ic, TRUE);
10685 /* if they are the same registers */
10686 if (sameRegs (AOP (right), AOP (result)) &&
10687 !isOperandVolatile (result, FALSE) &&
10688 !isOperandVolatile (right, FALSE))
10691 /* if the result is a bit */
10692 if (AOP_TYPE (result) == AOP_CRY)
10695 /* if the right size is a literal then
10696 we know what the value is */
10697 if (AOP_TYPE (right) == AOP_LIT)
10699 if (((int) operandLitValue (right)))
10700 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10702 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10706 /* the right is also a bit variable */
10707 if (AOP_TYPE (right) == AOP_CRY)
10709 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10710 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10714 /* we need to or */
10716 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10720 /* bit variables done */
10722 size = AOP_SIZE (result);
10724 if (AOP_TYPE (right) == AOP_LIT)
10725 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10727 (AOP_TYPE (result) != AOP_REG) &&
10728 (AOP_TYPE (right) == AOP_LIT) &&
10729 !IS_FLOAT (operandType (right)) &&
10732 while ((size) && (lit))
10735 aopGet (right, offset, FALSE, FALSE),
10737 isOperandVolatile (result, FALSE));
10742 emitcode ("clr", "a");
10745 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10754 aopGet (right, offset, FALSE, FALSE),
10756 isOperandVolatile (result, FALSE));
10762 freeAsmop (result, NULL, ic, TRUE);
10763 freeAsmop (right, NULL, ic, TRUE);
10766 /*-----------------------------------------------------------------*/
10767 /* genJumpTab - generates code for jump table */
10768 /*-----------------------------------------------------------------*/
10770 genJumpTab (iCode * ic)
10772 symbol *jtab,*jtablo,*jtabhi;
10774 unsigned int count;
10776 D(emitcode ("; genJumpTab",""));
10778 count = elementsInSet( IC_JTLABELS (ic) );
10782 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10783 if the switch argument is in a register.
10784 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10785 /* (MB) What if peephole converts ljmp to sjmp or ret ???
10786 How will multiply by three be updated ???*/
10787 aopOp (IC_JTCOND (ic), ic, FALSE);
10788 /* get the condition into accumulator */
10789 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10791 /* multiply by three */
10792 emitcode ("add", "a,acc");
10793 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10794 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10796 jtab = newiTempLabel (NULL);
10797 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10798 emitcode ("jmp", "@a+dptr");
10799 emitcode ("", "%05d$:", jtab->key + 100);
10800 /* now generate the jump labels */
10801 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10802 jtab = setNextItem (IC_JTLABELS (ic)))
10803 emitcode ("ljmp", "%05d$", jtab->key + 100);
10807 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10808 if the switch argument is in a register.
10809 For n>6 this algorithm may be more compact */
10810 jtablo = newiTempLabel (NULL);
10811 jtabhi = newiTempLabel (NULL);
10813 /* get the condition into accumulator.
10814 Using b as temporary storage, if register push/pop is needed */
10815 aopOp (IC_JTCOND (ic), ic, FALSE);
10816 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10817 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10818 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10820 // (MB) what if B is in use???
10821 wassertl(!BINUSE, "B was in use");
10822 emitcode ("mov", "b,%s", l);
10825 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10829 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10830 emitcode ("movc", "a,@a+pc");
10831 emitcode ("push", "acc");
10834 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10835 emitcode ("movc", "a,@a+pc");
10836 emitcode ("push", "acc");
10840 /* this scales up to n<=255, but needs two more bytes
10841 and changes dptr */
10842 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10843 emitcode ("movc", "a,@a+dptr");
10844 emitcode ("push", "acc");
10847 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10848 emitcode ("movc", "a,@a+dptr");
10849 emitcode ("push", "acc");
10852 emitcode ("ret", "");
10854 /* now generate jump table, LSB */
10855 emitcode ("", "%05d$:", jtablo->key + 100);
10856 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10857 jtab = setNextItem (IC_JTLABELS (ic)))
10858 emitcode (".db", "%05d$", jtab->key + 100);
10860 /* now generate jump table, MSB */
10861 emitcode ("", "%05d$:", jtabhi->key + 100);
10862 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10863 jtab = setNextItem (IC_JTLABELS (ic)))
10864 emitcode (".db", "%05d$>>8", jtab->key + 100);
10868 /*-----------------------------------------------------------------*/
10869 /* genCast - gen code for casting */
10870 /*-----------------------------------------------------------------*/
10872 genCast (iCode * ic)
10874 operand *result = IC_RESULT (ic);
10875 sym_link *ctype = operandType (IC_LEFT (ic));
10876 sym_link *rtype = operandType (IC_RIGHT (ic));
10877 operand *right = IC_RIGHT (ic);
10880 D(emitcode("; genCast",""));
10882 /* if they are equivalent then do nothing */
10883 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10886 aopOp (right, ic, FALSE);
10887 aopOp (result, ic, FALSE);
10889 /* if the result is a bit (and not a bitfield) */
10890 // if (AOP_TYPE (result) == AOP_CRY)
10891 if (IS_BIT (OP_SYMBOL (result)->type))
10892 /* not for bitfields */
10894 /* if the right size is a literal then
10895 we know what the value is */
10896 if (AOP_TYPE (right) == AOP_LIT)
10898 if (((int) operandLitValue (right)))
10899 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10901 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10906 /* the right is also a bit variable */
10907 if (AOP_TYPE (right) == AOP_CRY)
10909 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10910 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10914 /* we need to or */
10916 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10921 /* if they are the same size : or less */
10922 if (AOP_SIZE (result) <= AOP_SIZE (right))
10925 /* if they are in the same place */
10926 if (sameRegs (AOP (right), AOP (result)))
10929 /* if they in different places then copy */
10930 size = AOP_SIZE (result);
10935 aopGet (right, offset, FALSE, FALSE),
10937 isOperandVolatile (result, FALSE));
10944 /* if the result is of type pointer */
10945 if (IS_PTR (ctype))
10949 sym_link *type = operandType (right);
10950 sym_link *etype = getSpec (type);
10952 /* pointer to generic pointer */
10953 if (IS_GENPTR (ctype))
10956 p_type = DCL_TYPE (type);
10959 if (SPEC_SCLS(etype)==S_REGISTER) {
10960 // let's assume it is a generic pointer
10963 /* we have to go by the storage class */
10964 p_type = PTR_TYPE (SPEC_OCLS (etype));
10968 /* the first two bytes are known */
10969 size = GPTRSIZE - 1;
10974 aopGet (right, offset, FALSE, FALSE),
10976 isOperandVolatile (result, FALSE));
10979 /* the last byte depending on type */
10981 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10986 // pointerTypeToGPByte will have bitched.
10990 sprintf(gpValStr, "#0x%x", gpVal);
10991 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10996 /* just copy the pointers */
10997 size = AOP_SIZE (result);
11002 aopGet (right, offset, FALSE, FALSE),
11004 isOperandVolatile (result, FALSE));
11010 /* so we now know that the size of destination is greater
11011 than the size of the source */
11012 /* we move to result for the size of source */
11013 size = AOP_SIZE (right);
11018 aopGet (right, offset, FALSE, FALSE),
11020 isOperandVolatile (result, FALSE));
11024 /* now depending on the sign of the source && destination */
11025 size = AOP_SIZE (result) - AOP_SIZE (right);
11026 /* if unsigned or not an integral type */
11027 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11030 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
11034 /* we need to extend the sign :{ */
11035 char *l = aopGet (right, AOP_SIZE (right) - 1,
11038 emitcode ("rlc", "a");
11039 emitcode ("subb", "a,acc");
11041 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
11044 /* we are done hurray !!!! */
11047 freeAsmop (result, NULL, ic, TRUE);
11048 freeAsmop (right, NULL, ic, TRUE);
11051 /*-----------------------------------------------------------------*/
11052 /* genDjnz - generate decrement & jump if not zero instrucion */
11053 /*-----------------------------------------------------------------*/
11055 genDjnz (iCode * ic, iCode * ifx)
11057 symbol *lbl, *lbl1;
11061 D(emitcode ("; genDjnz",""));
11063 /* if the if condition has a false label
11064 then we cannot save */
11065 if (IC_FALSE (ifx))
11068 /* if the minus is not of the form
11070 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11071 !IS_OP_LITERAL (IC_RIGHT (ic)))
11074 if (operandLitValue (IC_RIGHT (ic)) != 1)
11077 /* if the size of this greater than one then no
11079 if (getSize (operandType (IC_RESULT (ic))) > 1)
11082 /* otherwise we can save BIG */
11083 lbl = newiTempLabel (NULL);
11084 lbl1 = newiTempLabel (NULL);
11086 aopOp (IC_RESULT (ic), ic, FALSE);
11088 if (AOP_NEEDSACC(IC_RESULT(ic)))
11090 /* If the result is accessed indirectly via
11091 * the accumulator, we must explicitly write
11092 * it back after the decrement.
11094 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11096 if (strcmp(rByte, "a"))
11098 /* Something is hopelessly wrong */
11099 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11100 __FILE__, __LINE__);
11101 /* We can just give up; the generated code will be inefficient,
11102 * but what the hey.
11104 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11107 emitcode ("dec", "%s", rByte);
11108 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
11109 emitcode ("jnz", "%05d$", lbl->key + 100);
11111 else if (IS_AOP_PREG (IC_RESULT (ic)))
11113 emitcode ("dec", "%s",
11114 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11115 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11116 emitcode ("jnz", "%05d$", lbl->key + 100);
11120 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11123 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11124 emitcode ("", "%05d$:", lbl->key + 100);
11125 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11126 emitcode ("", "%05d$:", lbl1->key + 100);
11128 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11129 ifx->generated = 1;
11133 /*-----------------------------------------------------------------*/
11134 /* genReceive - generate code for a receive iCode */
11135 /*-----------------------------------------------------------------*/
11137 genReceive (iCode * ic)
11139 int size = getSize (operandType (IC_RESULT (ic)));
11142 D(emitcode ("; genReceive",""));
11144 if (ic->argreg == 1)
11145 { /* first parameter */
11146 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11147 isOperandInPagedSpace (IC_RESULT (ic))) &&
11148 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11149 IS_TRUE_SYMOP (IC_RESULT (ic))))
11152 int receivingA = 0;
11155 for (offset = 0; offset<size; offset++)
11156 if (!strcmp (fReturn[offset], "a"))
11161 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11163 for (offset = size-1; offset>0; offset--)
11164 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11165 emitcode("mov","a,%s", fReturn[0]);
11167 aopOp (IC_RESULT (ic), ic, FALSE);
11169 aopPut (IC_RESULT (ic), "a", offset,
11170 isOperandVolatile (IC_RESULT (ic), FALSE));
11171 for (offset = 1; offset<size; offset++)
11172 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
11173 isOperandVolatile (IC_RESULT (ic), FALSE));
11179 if (getTempRegs(tempRegs, size, ic))
11181 for (offset = 0; offset<size; offset++)
11182 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11183 aopOp (IC_RESULT (ic), ic, FALSE);
11184 for (offset = 0; offset<size; offset++)
11185 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
11186 isOperandVolatile (IC_RESULT (ic), FALSE));
11191 offset = fReturnSizeMCS51 - size;
11194 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11195 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11198 aopOp (IC_RESULT (ic), ic, FALSE);
11199 size = AOP_SIZE (IC_RESULT (ic));
11203 emitcode ("pop", "acc");
11204 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11210 aopOp (IC_RESULT (ic), ic, FALSE);
11212 assignResultValue (IC_RESULT (ic), NULL);
11215 else if (ic->argreg > 12)
11216 { /* bit parameters */
11217 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11219 aopOp (IC_RESULT (ic), ic, FALSE);
11220 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11221 outBitC(IC_RESULT (ic));
11225 { /* other parameters */
11227 aopOp (IC_RESULT (ic), ic, FALSE);
11228 rb1off = ic->argreg;
11231 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11236 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11239 /*-----------------------------------------------------------------*/
11240 /* genDummyRead - generate code for dummy read of volatiles */
11241 /*-----------------------------------------------------------------*/
11243 genDummyRead (iCode * ic)
11248 D(emitcode("; genDummyRead",""));
11250 op = IC_RIGHT (ic);
11251 if (op && IS_SYMOP (op))
11253 aopOp (op, ic, FALSE);
11255 /* if the result is a bit */
11256 if (AOP_TYPE (op) == AOP_CRY)
11257 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11260 /* bit variables done */
11262 size = AOP_SIZE (op);
11266 MOVA (aopGet (op, offset, FALSE, FALSE));
11271 freeAsmop (op, NULL, ic, TRUE);
11275 if (op && IS_SYMOP (op))
11277 aopOp (op, ic, FALSE);
11279 /* if the result is a bit */
11280 if (AOP_TYPE (op) == AOP_CRY)
11281 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11284 /* bit variables done */
11286 size = AOP_SIZE (op);
11290 MOVA (aopGet (op, offset, FALSE, FALSE));
11295 freeAsmop (op, NULL, ic, TRUE);
11299 /*-----------------------------------------------------------------*/
11300 /* genCritical - generate code for start of a critical sequence */
11301 /*-----------------------------------------------------------------*/
11303 genCritical (iCode *ic)
11305 symbol *tlbl = newiTempLabel (NULL);
11307 D(emitcode("; genCritical",""));
11309 if (IC_RESULT (ic))
11311 aopOp (IC_RESULT (ic), ic, TRUE);
11312 aopPut (IC_RESULT (ic), one, 0, 0);
11313 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11314 aopPut (IC_RESULT (ic), zero, 0, 0);
11315 emitcode ("", "%05d$:", (tlbl->key + 100));
11316 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11320 emitcode ("setb", "c");
11321 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11322 emitcode ("clr", "c");
11323 emitcode ("", "%05d$:", (tlbl->key + 100));
11324 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11328 /*-----------------------------------------------------------------*/
11329 /* genEndCritical - generate code for end of a critical sequence */
11330 /*-----------------------------------------------------------------*/
11332 genEndCritical (iCode *ic)
11334 D(emitcode("; genEndCritical",""));
11338 aopOp (IC_RIGHT (ic), ic, FALSE);
11339 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11341 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11342 emitcode ("mov", "ea,c");
11346 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11347 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11348 emitcode ("rrc", "a");
11349 emitcode ("mov", "ea,c");
11351 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11355 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11356 emitcode ("mov", "ea,c");
11360 /*-----------------------------------------------------------------*/
11361 /* gen51Code - generate code for 8051 based controllers */
11362 /*-----------------------------------------------------------------*/
11364 gen51Code (iCode * lic)
11368 /* int cseq = 0; */
11370 _G.currentFunc = NULL;
11371 lineHead = lineCurr = NULL;
11373 /* print the allocation information */
11374 if (allocInfo && currFunc)
11375 printAllocInfo (currFunc, codeOutFile);
11376 /* if debug information required */
11377 if (options.debug && currFunc)
11379 debugFile->writeFunction (currFunc, lic);
11381 /* stack pointer name */
11382 if (options.useXstack)
11388 for (ic = lic; ic; ic = ic->next)
11390 _G.current_iCode = ic;
11392 if (ic->lineno && cln != ic->lineno)
11396 debugFile->writeCLine (ic);
11398 if (!options.noCcodeInAsm) {
11399 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11400 printCLine(ic->filename, ic->lineno));
11405 if (ic->seqPoint && ic->seqPoint != cseq)
11407 emitcode ("", "; sequence point %d", ic->seqPoint);
11408 cseq = ic->seqPoint;
11411 if (options.iCodeInAsm) {
11412 char regsInUse[80];
11416 for (i=0; i<8; i++) {
11417 sprintf (®sInUse[i],
11418 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11421 strcpy (regsInUse, "--------");
11422 for (i=0; i < 8; i++) {
11423 if (bitVectBitValue (ic->rMask, i))
11425 int offset = regs8051[i].offset;
11426 regsInUse[offset] = offset + '0'; /* show rMask */
11430 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11432 /* if the result is marked as
11433 spilt and rematerializable or code for
11434 this has already been generated then
11436 if (resultRemat (ic) || ic->generated)
11439 /* depending on the operation */
11459 /* IPOP happens only when trying to restore a
11460 spilt live range, if there is an ifx statement
11461 following this pop then the if statement might
11462 be using some of the registers being popped which
11463 would destory the contents of the register so
11464 we need to check for this condition and handle it */
11466 ic->next->op == IFX &&
11467 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11468 genIfx (ic->next, ic);
11486 genEndFunction (ic);
11506 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11523 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11527 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11534 /* note these two are xlated by algebraic equivalence
11535 during parsing SDCC.y */
11536 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11537 "got '>=' or '<=' shouldn't have come here");
11541 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11553 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11557 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11561 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11597 genRightShift (ic);
11600 case GET_VALUE_AT_ADDRESS:
11602 hasInc (IC_LEFT (ic), ic,
11603 getSize (operandType (IC_RESULT (ic)))),
11604 ifxForOp (IC_RESULT (ic), ic) );
11608 if (POINTER_SET (ic))
11609 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11635 addSet (&_G.sendSet, ic);
11638 case DUMMY_READ_VOLATILE:
11647 genEndCritical (ic);
11659 _G.current_iCode = NULL;
11661 /* now we are ready to call the
11662 peep hole optimizer */
11663 if (!options.nopeep)
11664 peepHole (&lineHead);
11666 /* now do the actual printing */
11667 printLine (lineHead, codeOutFile);