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));
478 /*-----------------------------------------------------------------*/
479 /* pointerCode - returns the code for a pointer type */
480 /*-----------------------------------------------------------------*/
482 pointerCode (sym_link * etype)
485 return PTR_TYPE (SPEC_OCLS (etype));
489 /*-----------------------------------------------------------------*/
490 /* leftRightUseAcc - returns size of accumulator use by operands */
491 /*-----------------------------------------------------------------*/
493 leftRightUseAcc(iCode *ic)
502 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
503 "null iCode pointer");
510 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
513 size = getSize (OP_SYMBOL (op)->type);
518 else if (ic->op == JUMPTABLE)
521 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
524 size = getSize (OP_SYMBOL (op)->type);
532 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
535 size = getSize (OP_SYMBOL (op)->type);
540 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
543 size = getSize (OP_SYMBOL (op)->type);
555 /*-----------------------------------------------------------------*/
556 /* aopForSym - for a true symbol */
557 /*-----------------------------------------------------------------*/
559 aopForSym (iCode * ic, symbol * sym, bool result)
564 wassertl (ic != NULL, "Got a null iCode");
565 wassertl (sym != NULL, "Got a null symbol");
567 space = SPEC_OCLS (sym->etype);
569 /* if already has one */
573 /* assign depending on the storage class */
574 /* if it is on the stack or indirectly addressable */
575 /* space we need to assign either r0 or r1 to it */
576 if (sym->onStack || sym->iaccess)
578 sym->aop = aop = newAsmop (0);
579 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
580 aop->size = getSize (sym->type);
582 /* now assign the address of the variable to
583 the pointer register */
584 if (aop->type != AOP_STK)
589 char offset = ((sym->stack < 0) ?
590 ((char) (sym->stack - _G.nRegsSaved)) :
591 ((char) sym->stack)) & 0xff;
593 if ((offset >= -3) && (offset <= 3))
595 emitcode ("mov", "%s,%s",
596 aop->aopu.aop_ptr->name, SYM_BP (sym));
599 emitcode ("dec", aop->aopu.aop_ptr->name);
604 emitcode ("inc", aop->aopu.aop_ptr->name);
610 if (_G.accInUse || leftRightUseAcc (ic))
611 emitcode ("push", "acc");
612 emitcode ("mov", "a,%s", SYM_BP (sym));
613 emitcode ("add", "a,#0x%02x", offset);
614 emitcode ("mov", "%s,a",
615 aop->aopu.aop_ptr->name);
616 if (_G.accInUse || leftRightUseAcc (ic))
617 emitcode ("pop", "acc");
621 emitcode ("mov", "%s,#%s",
622 aop->aopu.aop_ptr->name,
624 aop->paged = space->paged;
627 aop->aopu.aop_stk = sym->stack;
631 /* if in bit space */
632 if (IN_BITSPACE (space))
634 sym->aop = aop = newAsmop (AOP_CRY);
635 aop->aopu.aop_dir = sym->rname;
636 aop->size = getSize (sym->type);
639 /* if it is in direct space */
640 if (IN_DIRSPACE (space))
642 //printf("aopForSym, using AOP_DIR for %s (%x)\n", sym->name, sym);
643 //printTypeChainRaw(sym->type, NULL);
644 //printf("space = %s\n", space ? space->sname : "NULL");
645 sym->aop = aop = newAsmop (AOP_DIR);
646 aop->aopu.aop_dir = sym->rname;
647 aop->size = getSize (sym->type);
651 /* special case for a function */
652 if (IS_FUNC (sym->type))
654 sym->aop = aop = newAsmop (AOP_IMMD);
655 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
656 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
657 aop->size = getSize (sym->type);
661 /* only remaining is far space */
662 /* in which case DPTR gets the address */
663 sym->aop = aop = newAsmop (AOP_DPTR);
664 emitcode ("mov", "dptr,#%s", sym->rname);
665 aop->size = getSize (sym->type);
667 /* if it is in code space */
668 if (IN_CODESPACE (space))
674 /*-----------------------------------------------------------------*/
675 /* aopForRemat - rematerialzes an object */
676 /*-----------------------------------------------------------------*/
678 aopForRemat (symbol * sym)
680 iCode *ic = sym->rematiCode;
681 asmop *aop = newAsmop (AOP_IMMD);
688 val += (int) operandLitValue (IC_RIGHT (ic));
689 else if (ic->op == '-')
690 val -= (int) operandLitValue (IC_RIGHT (ic));
691 else if (IS_CAST_ICODE(ic)) {
692 sym_link *from_type = operandType(IC_RIGHT(ic));
693 aop->aopu.aop_immd.from_cast_remat = 1;
694 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
695 ptr_type = pointerTypeToGPByte (DCL_TYPE(from_type), NULL, NULL);
699 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
703 sprintf (buffer, "(%s %c 0x%04x)",
704 OP_SYMBOL (IC_LEFT (ic))->rname,
705 val >= 0 ? '+' : '-',
708 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
710 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
711 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
712 /* set immd2 field if required */
713 if (aop->aopu.aop_immd.from_cast_remat) {
714 sprintf(buffer,"#0x%02x",ptr_type);
715 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
716 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
722 /*-----------------------------------------------------------------*/
723 /* regsInCommon - two operands have some registers in common */
724 /*-----------------------------------------------------------------*/
726 regsInCommon (operand * op1, operand * op2)
731 /* if they have registers in common */
732 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
735 sym1 = OP_SYMBOL (op1);
736 sym2 = OP_SYMBOL (op2);
738 if (sym1->nRegs == 0 || sym2->nRegs == 0)
741 for (i = 0; i < sym1->nRegs; i++)
747 for (j = 0; j < sym2->nRegs; j++)
752 if (sym2->regs[j] == sym1->regs[i])
760 /*-----------------------------------------------------------------*/
761 /* operandsEqu - equivalent */
762 /*-----------------------------------------------------------------*/
764 operandsEqu (operand * op1, operand * op2)
768 /* if they're not symbols */
769 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
772 sym1 = OP_SYMBOL (op1);
773 sym2 = OP_SYMBOL (op2);
775 /* if both are itemps & one is spilt
776 and the other is not then false */
777 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
778 sym1->isspilt != sym2->isspilt)
781 /* if they are the same */
785 /* if they have the same rname */
786 if (sym1->rname[0] && sym2->rname[0] &&
787 strcmp (sym1->rname, sym2->rname) == 0 &&
788 !(IS_PARM (op2) && IS_ITEMP (op1)))
791 /* if left is a tmp & right is not */
792 if (IS_ITEMP (op1) &&
795 (sym1->usl.spillLoc == sym2))
798 if (IS_ITEMP (op2) &&
802 (sym2->usl.spillLoc == sym1))
808 /*-----------------------------------------------------------------*/
809 /* sameRegs - two asmops have the same registers */
810 /*-----------------------------------------------------------------*/
812 sameRegs (asmop * aop1, asmop * aop2)
819 if (aop1->type != AOP_REG && aop1->type != AOP_CRY)
822 if (aop1->type != aop2->type)
825 if (aop1->size != aop2->size)
828 for (i = 0; i < aop1->size; i++)
829 if (aop1->aopu.aop_reg[i] !=
830 aop2->aopu.aop_reg[i])
836 /*-----------------------------------------------------------------*/
837 /* aopOp - allocates an asmop for an operand : */
838 /*-----------------------------------------------------------------*/
840 aopOp (operand * op, iCode * ic, bool result)
849 /* if this a literal */
850 if (IS_OP_LITERAL (op))
852 op->aop = aop = newAsmop (AOP_LIT);
853 aop->aopu.aop_lit = op->operand.valOperand;
854 aop->size = getSize (operandType (op));
858 /* if already has a asmop then continue */
862 /* if the underlying symbol has a aop */
863 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
865 op->aop = OP_SYMBOL (op)->aop;
869 /* if this is a true symbol */
870 if (IS_TRUE_SYMOP (op))
872 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
876 /* this is a temporary : this has
882 e) can be a return use only */
884 sym = OP_SYMBOL (op);
886 /* if the type is a conditional */
887 if (sym->regType == REG_CND)
889 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
894 /* if it is spilt then two situations
896 b) has a spill location */
897 if (sym->isspilt || sym->nRegs == 0)
900 /* rematerialize it NOW */
903 sym->aop = op->aop = aop =
905 aop->size = getSize (sym->type);
912 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
913 aop->size = getSize (sym->type);
914 for (i = 0; i < 2; i++)
915 aop->aopu.aop_str[i] = accUse[i];
923 aop = op->aop = sym->aop = newAsmop (AOP_STR);
924 aop->size = getSize (sym->type);
925 for (i = 0; i < fReturnSizeMCS51; i++)
926 aop->aopu.aop_str[i] = fReturn[i];
930 if (sym->usl.spillLoc)
932 if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
934 /* force a new aop if sizes differ */
935 sym->usl.spillLoc->aop = NULL;
937 sym->aop = op->aop = aop =
938 aopForSym (ic, sym->usl.spillLoc, result);
939 aop->size = getSize (sym->type);
943 /* else must be a dummy iTemp */
944 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
945 aop->size = getSize (sym->type);
949 /* if the type is a bit register */
950 if (sym->regType == REG_BIT)
952 sym->aop = op->aop = aop = newAsmop (AOP_CRY);
953 aop->size = sym->nRegs;//1???
954 aop->aopu.aop_reg[0] = sym->regs[0];
955 aop->aopu.aop_dir = sym->regs[0]->name;
959 /* must be in a register */
960 sym->aop = op->aop = aop = newAsmop (AOP_REG);
961 aop->size = sym->nRegs;
962 for (i = 0; i < sym->nRegs; i++)
963 aop->aopu.aop_reg[i] = sym->regs[i];
966 /*-----------------------------------------------------------------*/
967 /* freeAsmop - free up the asmop given to an operand */
968 /*----------------------------------------------------------------*/
970 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
987 /* depending on the asmop type only three cases need work AOP_RO
988 , AOP_R1 && AOP_STK */
994 emitcode ("mov", "r0,b");
997 else if (_G.r0Pushed)
1001 emitcode ("pop", "ar0");
1005 bitVectUnSetBit (ic->rUsed, R0_IDX);
1011 emitcode ("mov", "r1,b");
1018 emitcode ("pop", "ar1");
1022 bitVectUnSetBit (ic->rUsed, R1_IDX);
1028 int stk = aop->aopu.aop_stk + aop->size - 1;
1029 bitVectUnSetBit (ic->rUsed, R0_IDX);
1030 bitVectUnSetBit (ic->rUsed, R1_IDX);
1032 getFreePtr (ic, &aop, FALSE);
1036 emitcode ("mov", "a,_bp");
1037 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1038 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1042 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1047 emitcode ("pop", "acc");
1048 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1051 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1054 freeAsmop (op, NULL, ic, TRUE);
1057 emitcode ("pop", "ar1");
1063 emitcode ("pop", "ar0");
1070 /* all other cases just dealloc */
1076 OP_SYMBOL (op)->aop = NULL;
1077 /* if the symbol has a spill */
1079 SPIL_LOC (op)->aop = NULL;
1084 /*------------------------------------------------------------------*/
1085 /* freeForBranchAsmop - partial free up of Asmop for a branch; just */
1086 /* pop r0 or r1 off stack if pushed */
1087 /*------------------------------------------------------------------*/
1089 freeForBranchAsmop (operand * op)
1109 emitcode ("mov", "r0,b");
1111 else if (_G.r0Pushed)
1113 emitcode ("pop", "ar0");
1120 emitcode ("mov", "r1,b");
1122 else if (_G.r1Pushed)
1124 emitcode ("pop", "ar1");
1131 int stk = aop->aopu.aop_stk + aop->size - 1;
1133 emitcode ("mov", "b,r0");
1136 emitcode ("mov", "a,_bp");
1137 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
1138 emitcode ("mov", "r0,a");
1142 emitcode ("mov", "r0,_bp");
1147 emitcode ("pop", "acc");
1148 emitcode ("mov", "@r0,a");
1151 emitcode ("dec", "r0");
1153 emitcode ("mov", "r0,b");
1159 /*-----------------------------------------------------------------*/
1160 /* aopGetUsesAcc - indicates ahead of time whether aopGet() will */
1161 /* clobber the accumulator */
1162 /*-----------------------------------------------------------------*/
1164 aopGetUsesAcc (operand * oper, int offset)
1166 asmop * aop = AOP (oper);
1168 if (offset > (aop->size - 1))
1186 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1197 if (strcmp (aop->aopu.aop_str[offset], "a") == 0)
1203 /* Error case --- will have been caught already */
1209 /*-----------------------------------------------------------------*/
1210 /* aopGet - for fetching value of the aop */
1211 /*-----------------------------------------------------------------*/
1213 aopGet (operand * oper, int offset, bool bit16, bool dname)
1217 asmop * aop = AOP (oper);
1219 /* offset is greater than
1221 if (offset > (aop->size - 1) &&
1222 aop->type != AOP_LIT)
1225 /* depending on type */
1233 /* if we need to increment it */
1234 while (offset > aop->coff)
1236 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1240 while (offset < aop->coff)
1242 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1249 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1250 return (dname ? "acc" : "a");
1252 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1253 rs = Safe_calloc (1, strlen (s) + 1);
1258 if (aop->code && aop->coff==0 && offset>=1) {
1259 emitcode ("mov", "a,#0x%02x", offset);
1260 emitcode ("movc", "a,@a+dptr");
1261 return (dname ? "acc" : "a");
1264 while (offset > aop->coff)
1266 emitcode ("inc", "dptr");
1270 while (offset < aop->coff)
1272 emitcode ("lcall", "__decdptr");
1279 emitcode ("clr", "a");
1280 emitcode ("movc", "a,@a+dptr");
1284 emitcode ("movx", "a,@dptr");
1286 return (dname ? "acc" : "a");
1290 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
1291 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1293 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1295 sprintf (s, "#(%s >> %d)",
1296 aop->aopu.aop_immd.aop_immd1,
1300 aop->aopu.aop_immd.aop_immd1);
1301 rs = Safe_calloc (1, strlen (s) + 1);
1306 if (SPEC_SCLS (getSpec (operandType (oper))) == S_SFR && offset)
1307 sprintf (s, "(%s >> %d)",
1308 aop->aopu.aop_dir, offset * 8);
1310 sprintf (s, "(%s + %d)",
1314 sprintf (s, "%s", aop->aopu.aop_dir);
1315 rs = Safe_calloc (1, strlen (s) + 1);
1321 return aop->aopu.aop_reg[offset]->dname;
1323 return aop->aopu.aop_reg[offset]->name;
1326 emitcode ("clr", "a");
1327 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1328 emitcode ("rlc", "a");
1329 return (dname ? "acc" : "a");
1332 if (!offset && dname)
1334 return aop->aopu.aop_str[offset];
1337 return aopLiteral (aop->aopu.aop_lit, offset);
1341 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1345 return aop->aopu.aop_str[offset];
1349 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1350 "aopget got unsupported aop->type");
1354 /*-----------------------------------------------------------------*/
1355 /* aopPutUsesAcc - indicates ahead of time whether aopPut() will */
1356 /* clobber the accumulator */
1357 /*-----------------------------------------------------------------*/
1359 aopPutUsesAcc (operand * oper, const char *s, int offset)
1361 asmop * aop = AOP (oper);
1363 if (offset > (aop->size - 1))
1373 wassert(strcmp(aop->aopu.aop_reg[offset]->name, "a"));
1379 return ((aop->paged) || (*s == '@'));
1383 return (!aop->aopu.aop_dir || strcmp(s, aop->aopu.aop_dir));
1391 /* Error case --- will have been caught already */
1397 /*-----------------------------------------------------------------*/
1398 /* aopPut - puts a string for a aop and indicates if acc is in use */
1399 /*-----------------------------------------------------------------*/
1401 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1404 bool accuse = FALSE;
1405 asmop * aop = AOP (result);
1407 if (aop->size && offset > (aop->size - 1))
1409 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1410 "aopPut got offset > aop->size");
1414 /* will assign value to value */
1415 /* depending on where it is ofcourse */
1419 MOVA (s); /* read s in case it was volatile */
1424 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1425 sprintf (d, "(%s >> %d)", aop->aopu.aop_dir, offset * 8);
1427 sprintf (d, "(%s + %d)", aop->aopu.aop_dir, offset);
1429 sprintf (d, "%s", aop->aopu.aop_dir);
1431 if (strcmp (d, s) || bvolatile)
1432 emitcode ("mov", "%s,%s", d, s);
1433 if (!strcmp (d, "acc"))
1439 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1440 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1443 strcmp (s, "r0") == 0 ||
1444 strcmp (s, "r1") == 0 ||
1445 strcmp (s, "r2") == 0 ||
1446 strcmp (s, "r3") == 0 ||
1447 strcmp (s, "r4") == 0 ||
1448 strcmp (s, "r5") == 0 ||
1449 strcmp (s, "r6") == 0 ||
1450 strcmp (s, "r7") == 0)
1451 emitcode ("mov", "%s,%s",
1452 aop->aopu.aop_reg[offset]->dname, s);
1454 emitcode ("mov", "%s,%s",
1455 aop->aopu.aop_reg[offset]->name, s);
1462 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1463 "aopPut writing to code space");
1467 while (offset > aop->coff)
1470 emitcode ("inc", "dptr");
1473 while (offset < aop->coff)
1476 emitcode ("lcall", "__decdptr");
1481 /* if not in accumulator */
1484 emitcode ("movx", "@dptr,a");
1489 while (offset > aop->coff)
1492 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1494 while (offset < aop->coff)
1497 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1504 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1509 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1511 else if (strcmp (s, "r0") == 0 ||
1512 strcmp (s, "r1") == 0 ||
1513 strcmp (s, "r2") == 0 ||
1514 strcmp (s, "r3") == 0 ||
1515 strcmp (s, "r4") == 0 ||
1516 strcmp (s, "r5") == 0 ||
1517 strcmp (s, "r6") == 0 ||
1518 strcmp (s, "r7") == 0)
1521 sprintf (buffer, "a%s", s);
1522 emitcode ("mov", "@%s,%s",
1523 aop->aopu.aop_ptr->name, buffer);
1526 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1531 if (strcmp (s, "a") == 0)
1532 emitcode ("push", "acc");
1536 emitcode ("push", "acc");
1538 emitcode ("push", s);
1544 /* if not bit variable */
1545 if (!aop->aopu.aop_dir)
1547 /* inefficient: move carry into A and use jz/jnz */
1548 emitcode ("clr", "a");
1549 emitcode ("rlc", "a");
1555 emitcode ("clr", "%s", aop->aopu.aop_dir);
1557 emitcode ("setb", "%s", aop->aopu.aop_dir);
1558 else if (!strcmp (s, "c"))
1559 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1560 else if (strcmp (s, aop->aopu.aop_dir))
1563 /* set C, if a >= 1 */
1564 emitcode ("add", "a,#0xff");
1565 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1572 if (strcmp (aop->aopu.aop_str[offset], s) ||
1574 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1580 if (!offset && (strcmp (s, "acc") == 0) &&
1584 if (strcmp (aop->aopu.aop_str[offset], s) &&
1586 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1590 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1591 "aopPut got unsupported aop->type");
1600 /*-----------------------------------------------------------------*/
1601 /* pointToEnd :- points to the last byte of the operand */
1602 /*-----------------------------------------------------------------*/
1604 pointToEnd (asmop * aop)
1610 aop->coff = count = (aop->size - 1);
1616 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1620 emitcode ("inc", "dptr");
1627 /*-----------------------------------------------------------------*/
1628 /* reAdjustPreg - points a register back to where it should */
1629 /*-----------------------------------------------------------------*/
1631 reAdjustPreg (asmop * aop)
1633 if ((aop->coff==0) || aop->size <= 1)
1641 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1646 emitcode ("lcall", "__decdptr");
1653 /*-----------------------------------------------------------------*/
1654 /* opIsGptr: returns non-zero if the passed operand is */
1655 /* a generic pointer type. */
1656 /*-----------------------------------------------------------------*/
1658 opIsGptr (operand * op)
1660 sym_link *type = operandType (op);
1662 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1669 /*-----------------------------------------------------------------*/
1670 /* getDataSize - get the operand data size */
1671 /*-----------------------------------------------------------------*/
1673 getDataSize (operand * op)
1676 size = AOP_SIZE (op);
1677 if (size == GPTRSIZE)
1679 sym_link *type = operandType (op);
1680 if (IS_GENPTR (type))
1682 /* generic pointer; arithmetic operations
1683 * should ignore the high byte (pointer type).
1691 /*-----------------------------------------------------------------*/
1692 /* outAcc - output Acc */
1693 /*-----------------------------------------------------------------*/
1695 outAcc (operand * result)
1698 size = getDataSize (result);
1701 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1704 /* unsigned or positive */
1707 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1712 /*-----------------------------------------------------------------*/
1713 /* outBitC - output a bit C */
1714 /*-----------------------------------------------------------------*/
1716 outBitC (operand * result)
1718 /* if the result is bit */
1719 if (AOP_TYPE (result) == AOP_CRY)
1720 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1723 emitcode ("clr", "a");
1724 emitcode ("rlc", "a");
1729 /*-----------------------------------------------------------------*/
1730 /* toBoolean - emit code for orl a,operator(sizeop) */
1731 /*-----------------------------------------------------------------*/
1733 toBoolean (operand * oper)
1735 int size = AOP_SIZE (oper) - 1;
1737 bool AccUsed = FALSE;
1740 while (!AccUsed && size--)
1742 AccUsed |= aopGetUsesAcc(oper, offset++);
1745 size = AOP_SIZE (oper) - 1;
1747 MOVA (aopGet (oper, 0, FALSE, FALSE));
1748 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1751 emitcode("mov", "b,a");
1754 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1755 emitcode ("orl", "b,a");
1757 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1758 emitcode ("orl", "a,b");
1765 emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1771 /*-----------------------------------------------------------------*/
1772 /* genNot - generate code for ! operation */
1773 /*-----------------------------------------------------------------*/
1779 D(emitcode ("; genNot",""));
1781 /* assign asmOps to operand & result */
1782 aopOp (IC_LEFT (ic), ic, FALSE);
1783 aopOp (IC_RESULT (ic), ic, TRUE);
1785 /* if in bit space then a special case */
1786 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1788 /* if left==result then cpl bit */
1789 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1791 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1795 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1796 emitcode ("cpl", "c");
1797 outBitC (IC_RESULT (ic));
1802 toBoolean (IC_LEFT (ic));
1804 /* set C, if a == 0 */
1805 tlbl = newiTempLabel (NULL);
1806 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1807 emitcode ("", "%05d$:", tlbl->key + 100);
1808 outBitC (IC_RESULT (ic));
1811 /* release the aops */
1812 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1813 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1817 /*-----------------------------------------------------------------*/
1818 /* genCpl - generate code for complement */
1819 /*-----------------------------------------------------------------*/
1826 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1828 D(emitcode (";", "genCpl"));
1830 /* assign asmOps to operand & result */
1831 aopOp (IC_LEFT (ic), ic, FALSE);
1832 aopOp (IC_RESULT (ic), ic, TRUE);
1834 /* special case if in bit space */
1835 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1839 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1840 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1842 /* promotion rules are responsible for this strange result:
1843 bit -> int -> ~int -> bit
1844 uchar -> int -> ~int -> bit
1846 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1850 tlbl=newiTempLabel(NULL);
1851 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1852 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1853 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1854 IS_AOP_PREG (IC_LEFT (ic)))
1856 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1861 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1863 emitcode ("", "%05d$:", tlbl->key + 100);
1864 outBitC (IC_RESULT(ic));
1868 size = AOP_SIZE (IC_RESULT (ic));
1871 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1873 emitcode ("cpl", "a");
1874 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1879 /* release the aops */
1880 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1881 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1884 /*-----------------------------------------------------------------*/
1885 /* genUminusFloat - unary minus for floating points */
1886 /*-----------------------------------------------------------------*/
1888 genUminusFloat (operand * op, operand * result)
1890 int size, offset = 0;
1893 D(emitcode ("; genUminusFloat",""));
1895 /* for this we just copy and then flip the bit */
1897 size = AOP_SIZE (op) - 1;
1902 aopGet (op, offset, FALSE, FALSE),
1904 isOperandVolatile (result, FALSE));
1908 l = aopGet (op, offset, FALSE, FALSE);
1912 emitcode ("cpl", "acc.7");
1913 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1916 /*-----------------------------------------------------------------*/
1917 /* genUminus - unary minus code generation */
1918 /*-----------------------------------------------------------------*/
1920 genUminus (iCode * ic)
1923 sym_link *optype, *rtype;
1926 D(emitcode ("; genUminus",""));
1929 aopOp (IC_LEFT (ic), ic, FALSE);
1930 aopOp (IC_RESULT (ic), ic, TRUE);
1932 /* if both in bit space then special
1934 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1935 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1938 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1939 emitcode ("cpl", "c");
1940 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1944 optype = operandType (IC_LEFT (ic));
1945 rtype = operandType (IC_RESULT (ic));
1947 /* if float then do float stuff */
1948 if (IS_FLOAT (optype))
1950 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1954 /* otherwise subtract from zero */
1955 size = AOP_SIZE (IC_LEFT (ic));
1960 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1961 if (!strcmp (l, "a"))
1965 emitcode ("cpl", "a");
1966 emitcode ("addc", "a,#0");
1972 emitcode ("clr", "a");
1973 emitcode ("subb", "a,%s", l);
1975 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1978 /* if any remaining bytes in the result */
1979 /* we just need to propagate the sign */
1980 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1982 emitcode ("rlc", "a");
1983 emitcode ("subb", "a,acc");
1985 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1989 /* release the aops */
1990 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1991 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1994 /*-----------------------------------------------------------------*/
1995 /* saveRegisters - will look for a call and save the registers */
1996 /*-----------------------------------------------------------------*/
1998 saveRegisters (iCode * lic)
2005 for (ic = lic; ic; ic = ic->next)
2006 if (ic->op == CALL || ic->op == PCALL)
2011 fprintf (stderr, "found parameter push with no function call\n");
2015 /* if the registers have been saved already or don't need to be then
2019 if (IS_SYMOP(IC_LEFT(ic)) &&
2020 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2021 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2024 /* save the registers in use at this time but skip the
2025 ones for the result */
2026 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2027 mcs51_rUmaskForOp (IC_RESULT(ic)));
2030 if (options.useXstack)
2032 int count = bitVectnBitsOn (rsave);
2036 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2037 if (reg->type == REG_BIT)
2039 emitcode ("mov", "a,%s", reg->base);
2043 emitcode ("mov", "a,%s", reg->name);
2045 emitcode ("mov", "r0,%s", spname);
2046 emitcode ("inc", "%s", spname);// allocate before use
2047 emitcode ("movx", "@r0,a");
2048 if (bitVectBitValue (rsave, R0_IDX))
2049 emitcode ("mov", "r0,a");
2051 else if (count != 0)
2053 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2054 int nBits = bitVectnBitsOn (rsavebits);
2058 count = count - nBits + 1;
2059 /* remove all but the first bits as they are pushed all at once */
2060 rsave = bitVectCplAnd (rsave, rsavebits);
2061 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2064 if (bitVectBitValue (rsave, R0_IDX))
2066 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2068 emitcode ("mov", "r0,%s", spname);
2070 emitcode ("add", "a,#%d", count);
2071 emitcode ("mov", "%s,a", spname);
2072 for (i = 0; i < mcs51_nRegs; i++)
2074 if (bitVectBitValue (rsave, i))
2076 regs * reg = mcs51_regWithIdx (i);
2079 emitcode ("pop", "acc");
2080 emitcode ("push", "acc");
2082 else if (reg->type == REG_BIT)
2084 emitcode ("mov", "a,%s", reg->base);
2088 emitcode ("mov", "a,%s", reg->name);
2090 emitcode ("movx", "@r0,a");
2093 emitcode ("inc", "r0");
2097 if (bitVectBitValue (rsave, R0_IDX))
2099 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2105 bool bits_pushed = FALSE;
2106 for (i = 0; i < mcs51_nRegs; i++)
2108 if (bitVectBitValue (rsave, i))
2110 bits_pushed = pushReg (i, bits_pushed);
2116 /*-----------------------------------------------------------------*/
2117 /* unsaveRegisters - pop the pushed registers */
2118 /*-----------------------------------------------------------------*/
2120 unsaveRegisters (iCode * ic)
2125 /* restore the registers in use at this time but skip the
2126 ones for the result */
2127 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2128 mcs51_rUmaskForOp (IC_RESULT(ic)));
2130 if (options.useXstack)
2132 int count = bitVectnBitsOn (rsave);
2136 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2137 emitcode ("mov", "r0,%s", spname);
2138 emitcode ("dec", "r0");
2139 emitcode ("movx", "a,@r0");
2140 if (reg->type == REG_BIT)
2142 emitcode ("mov", "%s,a", reg->base);
2146 emitcode ("mov", "%s,a", reg->name);
2148 emitcode ("dec", "%s", spname);
2150 else if (count != 0)
2152 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2153 int nBits = bitVectnBitsOn (rsavebits);
2157 count = count - nBits + 1;
2158 /* remove all but the first bits as they are popped all at once */
2159 rsave = bitVectCplAnd (rsave, rsavebits);
2160 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2163 emitcode ("mov", "r0,%s", spname);
2164 for (i = mcs51_nRegs; i >= 0; i--)
2166 if (bitVectBitValue (rsave, i))
2168 regs * reg = mcs51_regWithIdx (i);
2169 emitcode ("dec", "r0");
2170 emitcode ("movx", "a,@r0");
2173 emitcode ("push", "acc");
2175 else if (reg->type == REG_BIT)
2177 emitcode ("mov", "%s,a", reg->base);
2181 emitcode ("mov", "%s,a", reg->name);
2185 emitcode ("mov", "%s,r0", spname);
2186 if (bitVectBitValue (rsave, R0_IDX))
2188 emitcode ("pop", "ar0");
2194 bool bits_popped = FALSE;
2195 for (i = mcs51_nRegs; i >= 0; i--)
2197 if (bitVectBitValue (rsave, i))
2199 bits_popped = popReg (i, bits_popped);
2206 /*-----------------------------------------------------------------*/
2208 /*-----------------------------------------------------------------*/
2210 pushSide (operand * oper, int size)
2215 char *l = aopGet (oper, offset++, FALSE, TRUE);
2216 if (AOP_TYPE (oper) != AOP_REG &&
2217 AOP_TYPE (oper) != AOP_DIR &&
2221 emitcode ("push", "acc");
2225 emitcode ("push", "%s", l);
2230 /*-----------------------------------------------------------------*/
2231 /* assignResultValue - also indicates if acc is in use afterwards */
2232 /*-----------------------------------------------------------------*/
2234 assignResultValue (operand * oper, operand * func)
2237 int size = AOP_SIZE (oper);
2238 bool accuse = FALSE;
2239 bool pushedA = FALSE;
2241 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2247 if ((size > 3) && aopPutUsesAcc (oper, fReturn[offset], offset))
2249 emitcode ("push", "acc");
2254 if ((offset == 3) && pushedA)
2255 emitcode ("pop", "acc");
2256 accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2263 /*-----------------------------------------------------------------*/
2264 /* genXpush - pushes onto the external stack */
2265 /*-----------------------------------------------------------------*/
2267 genXpush (iCode * ic)
2269 asmop *aop = newAsmop (0);
2271 int size, offset = 0;
2273 D(emitcode ("; genXpush",""));
2275 aopOp (IC_LEFT (ic), ic, FALSE);
2276 r = getFreePtr (ic, &aop, FALSE);
2278 size = AOP_SIZE (IC_LEFT (ic));
2282 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2283 emitcode ("mov", "%s,%s", r->name, spname);
2284 emitcode ("inc", "%s", spname); // allocate space first
2285 emitcode ("movx", "@%s,a", r->name);
2289 // allocate space first
2290 emitcode ("mov", "%s,%s", r->name, spname);
2292 emitcode ("add", "a,#%d", size);
2293 emitcode ("mov", "%s,a", spname);
2297 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2298 emitcode ("movx", "@%s,a", r->name);
2299 emitcode ("inc", "%s", r->name);
2303 freeAsmop (NULL, aop, ic, TRUE);
2304 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2307 /*-----------------------------------------------------------------*/
2308 /* genIpush - generate code for pushing this gets a little complex */
2309 /*-----------------------------------------------------------------*/
2311 genIpush (iCode * ic)
2313 int size, offset = 0;
2317 D(emitcode ("; genIpush",""));
2319 /* if this is not a parm push : ie. it is spill push
2320 and spill push is always done on the local stack */
2324 /* and the item is spilt then do nothing */
2325 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2328 aopOp (IC_LEFT (ic), ic, FALSE);
2329 size = AOP_SIZE (IC_LEFT (ic));
2330 /* push it on the stack */
2333 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2339 emitcode ("push", "%s", l);
2344 /* this is a parameter push: in this case we call
2345 the routine to find the call and save those
2346 registers that need to be saved */
2349 /* if use external stack then call the external
2350 stack pushing routine */
2351 if (options.useXstack)
2357 /* then do the push */
2358 aopOp (IC_LEFT (ic), ic, FALSE);
2360 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2361 size = AOP_SIZE (IC_LEFT (ic));
2365 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2366 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2367 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2370 if (strcmp (l, prev) || *l == '@')
2372 emitcode ("push", "acc");
2376 emitcode ("push", "%s", l);
2381 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2384 /*-----------------------------------------------------------------*/
2385 /* genIpop - recover the registers: can happen only for spilling */
2386 /*-----------------------------------------------------------------*/
2388 genIpop (iCode * ic)
2392 D(emitcode ("; genIpop",""));
2394 /* if the temp was not pushed then */
2395 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2398 aopOp (IC_LEFT (ic), ic, FALSE);
2399 size = AOP_SIZE (IC_LEFT (ic));
2400 offset = (size - 1);
2402 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2405 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2408 /*-----------------------------------------------------------------*/
2409 /* saveRBank - saves an entire register bank on the stack */
2410 /*-----------------------------------------------------------------*/
2412 saveRBank (int bank, iCode * ic, bool pushPsw)
2415 int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
2419 if (options.useXstack)
2423 /* Assume r0 is available for use. */
2424 r = mcs51_regWithIdx (R0_IDX);;
2429 r = getFreePtr (ic, &aop, FALSE);
2431 // allocate space first
2432 emitcode ("mov", "%s,%s", r->name, spname);
2434 emitcode ("add", "a,#%d", count);
2435 emitcode ("mov", "%s,a", spname);
2438 for (i = 0; i < 8; i++)
2440 if (options.useXstack)
2442 emitcode ("mov", "a,(%s+%d)",
2443 regs8051[i].base, 8 * bank + regs8051[i].offset);
2444 emitcode ("movx", "@%s,a", r->name);
2446 emitcode ("inc", "%s", r->name);
2449 emitcode ("push", "(%s+%d)",
2450 regs8051[i].base, 8 * bank + regs8051[i].offset);
2453 if (mcs51_nRegs > 8)
2455 if (options.useXstack)
2457 emitcode ("mov", "a,bits");
2458 emitcode ("movx", "@%s,a", r->name);
2460 emitcode ("inc", "%s", r->name);
2464 emitcode ("push", "bits");
2471 if (options.useXstack)
2473 emitcode ("mov", "a,psw");
2474 emitcode ("movx", "@%s,a", r->name);
2479 emitcode ("push", "psw");
2482 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2487 freeAsmop (NULL, aop, ic, TRUE);
2496 /*-----------------------------------------------------------------*/
2497 /* unsaveRBank - restores the register bank from stack */
2498 /*-----------------------------------------------------------------*/
2500 unsaveRBank (int bank, iCode * ic, bool popPsw)
2506 if (options.useXstack)
2510 /* Assume r0 is available for use. */
2511 r = mcs51_regWithIdx (R0_IDX);;
2516 r = getFreePtr (ic, &aop, FALSE);
2518 emitcode ("mov", "%s,%s", r->name, spname);
2523 if (options.useXstack)
2525 emitcode ("dec", "%s", r->name);
2526 emitcode ("movx", "a,@%s", r->name);
2527 emitcode ("mov", "psw,a");
2531 emitcode ("pop", "psw");
2535 if (mcs51_nRegs > 8)
2537 if (options.useXstack)
2539 emitcode ("dec", "%s", r->name);
2540 emitcode ("movx", "a,@%s", r->name);
2541 emitcode ("mov", "bits,a");
2545 emitcode ("pop", "bits");
2549 for (i = 7; i >= 0; i--)
2551 if (options.useXstack)
2553 emitcode ("dec", "%s", r->name);
2554 emitcode ("movx", "a,@%s", r->name);
2555 emitcode ("mov", "(%s+%d),a",
2556 regs8051[i].base, 8 * bank + regs8051[i].offset);
2560 emitcode ("pop", "(%s+%d)",
2561 regs8051[i].base, 8 * bank + regs8051[i].offset);
2565 if (options.useXstack)
2567 emitcode ("mov", "%s,%s", spname, r->name);
2572 freeAsmop (NULL, aop, ic, TRUE);
2576 /*-----------------------------------------------------------------*/
2577 /* genSend - gen code for SEND */
2578 /*-----------------------------------------------------------------*/
2579 static void genSend(set *sendSet)
2584 /* first we do all bit parameters */
2585 for (sic = setFirstItem (sendSet); sic;
2586 sic = setNextItem (sendSet))
2588 aopOp (IC_LEFT (sic), sic, FALSE);
2590 if (sic->argreg > 12)
2592 int bit = sic->argreg-13;
2594 /* if left is a literal then
2595 we know what the value is */
2596 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2598 if (((int) operandLitValue (IC_LEFT (sic))))
2599 emitcode ("setb", "b[%d]", bit);
2601 emitcode ("clr", "b[%d]", bit);
2603 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2605 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2606 if (strcmp (l, "c"))
2607 emitcode ("mov", "c,%s", l);
2608 emitcode ("mov", "b[%d],c", bit);
2613 toBoolean (IC_LEFT (sic));
2614 /* set C, if a >= 1 */
2615 emitcode ("add", "a,#0xff");
2616 emitcode ("mov", "b[%d],c", bit);
2621 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2626 saveRegisters (setFirstItem (sendSet));
2627 emitcode ("mov", "bits,b");
2630 /* then we do all other parameters */
2631 for (sic = setFirstItem (sendSet); sic;
2632 sic = setNextItem (sendSet))
2634 int size, offset = 0;
2635 aopOp (IC_LEFT (sic), sic, FALSE);
2636 size = AOP_SIZE (IC_LEFT (sic));
2638 if (sic->argreg == 1)
2642 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2643 if (strcmp (l, fReturn[offset]))
2644 emitcode ("mov", "%s,%s", fReturn[offset], l);
2648 else if (sic->argreg <= 12)
2652 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2653 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2657 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2661 /*-----------------------------------------------------------------*/
2662 /* selectRegBank - emit code to select the register bank */
2663 /*-----------------------------------------------------------------*/
2665 selectRegBank (short bank, bool keepFlags)
2667 /* if f.e. result is in carry */
2670 emitcode ("anl", "psw,#0xE7");
2672 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2676 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2680 /*-----------------------------------------------------------------*/
2681 /* genCall - generates a call statement */
2682 /*-----------------------------------------------------------------*/
2684 genCall (iCode * ic)
2688 // bool restoreBank = FALSE;
2689 bool swapBanks = FALSE;
2690 bool accuse = FALSE;
2691 bool accPushed = FALSE;
2692 bool resultInF0 = FALSE;
2694 D(emitcode("; genCall",""));
2696 dtype = operandType (IC_LEFT (ic));
2697 etype = getSpec(dtype);
2698 /* if send set is not empty then assign */
2701 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2702 genSend(reverseSet(_G.sendSet));
2704 genSend(_G.sendSet);
2710 /* if we are calling a not _naked function that is not using
2711 the same register bank then we need to save the
2712 destination registers on the stack */
2713 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2714 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2715 !IFFUNC_ISISR (dtype))
2720 /* if caller saves & we have not saved then */
2726 emitcode ("mov", "psw,#0x%02x",
2727 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2731 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2733 if (IFFUNC_CALLEESAVES(dtype))
2735 werror (E_BANKED_WITH_CALLEESAVES);
2739 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2740 OP_SYMBOL (IC_LEFT (ic))->rname :
2741 OP_SYMBOL (IC_LEFT (ic))->name);
2743 emitcode ("mov", "r0,#%s", l);
2744 emitcode ("mov", "r1,#(%s >> 8)", l);
2745 emitcode ("mov", "r2,#(%s >> 16)", l);
2746 emitcode ("lcall", "__sdcc_banked_call");
2751 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2752 OP_SYMBOL (IC_LEFT (ic))->rname :
2753 OP_SYMBOL (IC_LEFT (ic))->name));
2758 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2761 /* if we need assign a result value */
2762 if ((IS_ITEMP (IC_RESULT (ic)) &&
2763 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2764 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2765 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2766 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2767 IS_TRUE_SYMOP (IC_RESULT (ic)))
2771 aopOp (IC_RESULT (ic), ic, FALSE);
2774 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2776 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2779 /* adjust the stack for parameters if required */
2783 if (ic->parmBytes > 3)
2787 emitcode ("push", "acc");
2790 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2791 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2793 emitcode ("mov", "F0,c");
2797 emitcode ("mov", "a,%s", spname);
2798 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2799 emitcode ("mov", "%s,a", spname);
2801 /* unsaveRegisters from xstack needs acc, but */
2802 /* unsaveRegisters from stack needs this popped */
2803 if (accPushed && !options.useXstack)
2805 emitcode ("pop", "acc");
2810 for (i = 0; i < ic->parmBytes; i++)
2811 emitcode ("dec", "%s", spname);
2814 /* if we had saved some registers then unsave them */
2815 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2817 if (accuse && !accPushed && options.useXstack)
2819 /* xstack needs acc, but doesn't touch normal stack */
2820 emitcode ("push", "acc");
2823 unsaveRegisters (ic);
2826 // /* if register bank was saved then pop them */
2828 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2830 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2833 emitcode ("mov", "c,F0");
2835 aopOp (IC_RESULT (ic), ic, FALSE);
2836 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2837 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2841 emitcode ("pop", "acc");
2844 /*-----------------------------------------------------------------*/
2845 /* -10l - generates a call by pointer statement */
2846 /*-----------------------------------------------------------------*/
2848 genPcall (iCode * ic)
2852 symbol *rlbl = newiTempLabel (NULL);
2853 // bool restoreBank=FALSE;
2854 bool swapBanks = FALSE;
2855 bool resultInF0 = FALSE;
2857 D(emitcode("; genPCall",""));
2859 dtype = operandType (IC_LEFT (ic))->next;
2860 etype = getSpec(dtype);
2861 /* if caller saves & we have not saved then */
2865 /* if we are calling a not _naked function that is not using
2866 the same register bank then we need to save the
2867 destination registers on the stack */
2868 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2869 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2870 !IFFUNC_ISISR (dtype))
2872 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2873 // restoreBank=TRUE;
2875 // need caution message to user here
2878 if (IS_LITERAL(etype))
2880 /* if send set is not empty then assign */
2883 genSend(reverseSet(_G.sendSet));
2889 emitcode ("mov", "psw,#0x%02x",
2890 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2893 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2895 if (IFFUNC_CALLEESAVES(dtype))
2897 werror (E_BANKED_WITH_CALLEESAVES);
2901 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2903 emitcode ("mov", "r0,#%s", l);
2904 emitcode ("mov", "r1,#(%s >> 8)", l);
2905 emitcode ("mov", "r2,#(%s >> 16)", l);
2906 emitcode ("lcall", "__sdcc_banked_call");
2911 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2916 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2918 if (IFFUNC_CALLEESAVES(dtype))
2920 werror (E_BANKED_WITH_CALLEESAVES);
2924 aopOp (IC_LEFT (ic), ic, FALSE);
2928 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2929 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2930 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2934 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2935 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2936 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2937 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2940 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2942 /* if send set is not empty then assign */
2945 genSend(reverseSet(_G.sendSet));
2951 emitcode ("mov", "psw,#0x%02x",
2952 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2956 emitcode ("lcall", "__sdcc_banked_call");
2961 /* push the return address on to the stack */
2962 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2963 emitcode ("push", "acc");
2964 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2965 emitcode ("push", "acc");
2967 /* now push the calling address */
2968 aopOp (IC_LEFT (ic), ic, FALSE);
2970 pushSide (IC_LEFT (ic), FPTRSIZE);
2972 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2974 /* if send set is not empty the assign */
2977 genSend(reverseSet(_G.sendSet));
2983 emitcode ("mov", "psw,#0x%02x",
2984 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2988 emitcode ("ret", "");
2989 emitcode ("", "%05d$:", (rlbl->key + 100));
2994 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2997 /* if we need assign a result value */
2998 if ((IS_ITEMP (IC_RESULT (ic)) &&
2999 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
3000 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
3001 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
3002 IS_TRUE_SYMOP (IC_RESULT (ic)))
3006 aopOp (IC_RESULT (ic), ic, FALSE);
3009 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3011 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3014 /* adjust the stack for parameters if required */
3018 if (ic->parmBytes > 3)
3020 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
3021 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3023 emitcode ("mov", "F0,c");
3027 emitcode ("mov", "a,%s", spname);
3028 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
3029 emitcode ("mov", "%s,a", spname);
3032 for (i = 0; i < ic->parmBytes; i++)
3033 emitcode ("dec", "%s", spname);
3037 // /* if register bank was saved then unsave them */
3039 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3041 /* if we had saved some registers then unsave them */
3042 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3043 unsaveRegisters (ic);
3045 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3048 emitcode ("mov", "c,F0");
3050 aopOp (IC_RESULT (ic), ic, FALSE);
3051 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3052 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3056 /*-----------------------------------------------------------------*/
3057 /* resultRemat - result is rematerializable */
3058 /*-----------------------------------------------------------------*/
3060 resultRemat (iCode * ic)
3062 if (SKIP_IC (ic) || ic->op == IFX)
3065 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3067 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3068 if (sym->remat && !POINTER_SET (ic))
3075 #if defined(__BORLANDC__) || defined(_MSC_VER)
3076 #define STRCASECMP stricmp
3078 #define STRCASECMP strcasecmp
3081 /*-----------------------------------------------------------------*/
3082 /* inExcludeList - return 1 if the string is in exclude Reg list */
3083 /*-----------------------------------------------------------------*/
3085 regsCmp(void *p1, void *p2)
3087 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3091 inExcludeList (char *s)
3093 const char *p = setFirstItem(options.excludeRegsSet);
3095 if (p == NULL || STRCASECMP(p, "none") == 0)
3099 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3102 /*-----------------------------------------------------------------*/
3103 /* genFunction - generated code for function entry */
3104 /*-----------------------------------------------------------------*/
3106 genFunction (iCode * ic)
3108 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3110 bool switchedPSW = FALSE;
3111 int calleesaves_saved_register = -1;
3112 int stackAdjust = sym->stack;
3113 int accIsFree = sym->recvSize < 4;
3114 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3115 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3118 /* create the function header */
3119 emitcode (";", "-----------------------------------------");
3120 emitcode (";", " function %s", sym->name);
3121 emitcode (";", "-----------------------------------------");
3123 emitcode ("", "%s:", sym->rname);
3124 ftype = operandType (IC_LEFT (ic));
3125 _G.currentFunc = sym;
3127 if (IFFUNC_ISNAKED(ftype))
3129 emitcode(";", "naked function: no prologue.");
3133 /* here we need to generate the equates for the
3134 register bank if required */
3135 if (FUNC_REGBANK (ftype) != rbank)
3139 rbank = FUNC_REGBANK (ftype);
3140 for (i = 0; i < mcs51_nRegs; i++)
3142 if (regs8051[i].type != REG_BIT)
3144 if (strcmp (regs8051[i].base, "0") == 0)
3145 emitcode ("", "%s = 0x%02x",
3147 8 * rbank + regs8051[i].offset);
3149 emitcode ("", "%s = %s + 0x%02x",
3152 8 * rbank + regs8051[i].offset);
3157 /* if this is an interrupt service routine then
3158 save acc, b, dpl, dph */
3159 if (IFFUNC_ISISR (sym->type))
3162 if (!inExcludeList ("acc"))
3163 emitcode ("push", "acc");
3164 if (!inExcludeList ("b"))
3165 emitcode ("push", "b");
3166 if (!inExcludeList ("dpl"))
3167 emitcode ("push", "dpl");
3168 if (!inExcludeList ("dph"))
3169 emitcode ("push", "dph");
3170 /* if this isr has no bank i.e. is going to
3171 run with bank 0 , then we need to save more
3173 if (!FUNC_REGBANK (sym->type))
3176 /* if this function does not call any other
3177 function then we can be economical and
3178 save only those registers that are used */
3179 if (!IFFUNC_HASFCALL(sym->type))
3183 /* if any registers used */
3186 bool bits_pushed = FALSE;
3187 /* save the registers used */
3188 for (i = 0; i < sym->regsUsed->size; i++)
3190 if (bitVectBitValue (sym->regsUsed, i))
3191 bits_pushed = pushReg (i, bits_pushed);
3198 /* this function has a function call. We cannot
3199 determines register usage so we will have to push the
3201 saveRBank (0, ic, FALSE);
3202 if (options.parms_in_bank1) {
3204 for (i=0; i < 8 ; i++ ) {
3205 emitcode ("push","%s",rb1regs[i]);
3212 /* This ISR uses a non-zero bank.
3214 * We assume that the bank is available for our
3217 * However, if this ISR calls a function which uses some
3218 * other bank, we must save that bank entirely.
3220 unsigned long banksToSave = 0;
3222 if (IFFUNC_HASFCALL(sym->type))
3225 #define MAX_REGISTER_BANKS 4
3230 for (i = ic; i; i = i->next)
3232 if (i->op == ENDFUNCTION)
3234 /* we got to the end OK. */
3242 dtype = operandType (IC_LEFT(i));
3244 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3246 /* Mark this bank for saving. */
3247 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3249 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3253 banksToSave |= (1 << FUNC_REGBANK(dtype));
3256 /* And note that we don't need to do it in
3264 /* This is a mess; we have no idea what
3265 * register bank the called function might
3268 * The only thing I can think of to do is
3269 * throw a warning and hope.
3271 werror(W_FUNCPTR_IN_USING_ISR);
3275 if (banksToSave && options.useXstack)
3277 /* Since we aren't passing it an ic,
3278 * saveRBank will assume r0 is available to abuse.
3280 * So switch to our (trashable) bank now, so
3281 * the caller's R0 isn't trashed.
3283 emitcode ("push", "psw");
3284 emitcode ("mov", "psw,#0x%02x",
3285 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3289 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3291 if (banksToSave & (1 << ix))
3293 saveRBank(ix, NULL, FALSE);
3297 // TODO: this needs a closer look
3298 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3301 /* Set the register bank to the desired value if nothing else */
3302 /* has done so yet. */
3305 emitcode ("push", "psw");
3306 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3311 /* This is a non-ISR function. The caller has already switched register */
3312 /* banks, if necessary, so just handle the callee-saves option. */
3314 /* if callee-save to be used for this function
3315 then save the registers being used in this function */
3316 if (IFFUNC_CALLEESAVES(sym->type))
3320 /* if any registers used */
3323 bool bits_pushed = FALSE;
3324 /* save the registers used */
3325 for (i = 0; i < sym->regsUsed->size; i++)
3327 if (bitVectBitValue (sym->regsUsed, i))
3329 /* remember one saved register for later usage */
3330 if (calleesaves_saved_register < 0)
3331 calleesaves_saved_register = i;
3332 bits_pushed = pushReg (i, bits_pushed);
3343 if (options.useXstack)
3345 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3347 emitcode ("mov", "r0,%s", spname);
3348 emitcode ("inc", "%s", spname);
3349 emitcode ("xch", "a,_bpx");
3350 emitcode ("movx", "@r0,a");
3351 emitcode ("inc", "r0");
3352 emitcode ("mov", "a,r0");
3353 emitcode ("xch", "a,_bpx");
3357 emitcode ("push", "_bp"); /* save the callers stack */
3358 emitcode ("mov", "_bp,sp");
3363 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3365 /* set up the stack */
3366 emitcode ("push", "_bp"); /* save the callers stack */
3367 emitcode ("mov", "_bp,sp");
3372 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3373 /* before setting up the stack frame completely. */
3374 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3376 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3380 if (rsym && rsym->regType == REG_CND)
3382 if (rsym && (rsym->accuse || rsym->ruonly))
3384 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3385 rsym = rsym->usl.spillLoc;
3388 /* If the RECEIVE operand immediately spills to the first entry on the */
3389 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3390 /* rather than the usual @r0/r1 machinations. */
3391 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3395 _G.current_iCode = ric;
3396 D(emitcode ("; genReceive",""));
3397 for (ofs=0; ofs < sym->recvSize; ofs++)
3399 if (!strcmp (fReturn[ofs], "a"))
3400 emitcode ("push", "acc");
3402 emitcode ("push", fReturn[ofs]);
3404 stackAdjust -= sym->recvSize;
3407 assert (stackAdjust>=0);
3410 _G.current_iCode = ic;
3414 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3415 /* to free up the accumulator. */
3416 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3420 _G.current_iCode = ric;
3421 D(emitcode ("; genReceive",""));
3422 for (ofs=0; ofs < sym->recvSize; ofs++)
3424 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3426 _G.current_iCode = ic;
3432 /* adjust the stack for the function */
3435 int i = stackAdjust;
3437 werror (W_STACK_OVERFLOW, sym->name);
3439 if (i > 3 && accIsFree)
3441 emitcode ("mov", "a,sp");
3442 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3443 emitcode ("mov", "sp,a");
3447 /* The accumulator is not free, so we will need another register */
3448 /* to clobber. No need to worry about a possible conflict with */
3449 /* the above early RECEIVE optimizations since they would have */
3450 /* freed the accumulator if they were generated. */
3452 if (IFFUNC_CALLEESAVES(sym->type))
3454 /* if it's a callee-saves function we need a saved register */
3455 if (calleesaves_saved_register >= 0)
3457 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3458 emitcode ("mov", "a,sp");
3459 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3460 emitcode ("mov", "sp,a");
3461 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3464 /* do it the hard way */
3466 emitcode ("inc", "sp");
3470 /* not callee-saves, we can clobber r0 */
3471 emitcode ("mov", "r0,a");
3472 emitcode ("mov", "a,sp");
3473 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3474 emitcode ("mov", "sp,a");
3475 emitcode ("mov", "a,r0");
3480 emitcode ("inc", "sp");
3485 char i = ((char) sym->xstack & 0xff);
3487 if (i > 3 && accIsFree)
3489 emitcode ("mov", "a,_spx");
3490 emitcode ("add", "a,#0x%02x", i);
3491 emitcode ("mov", "_spx,a");
3495 emitcode ("push", "acc");
3496 emitcode ("mov", "a,_spx");
3497 emitcode ("add", "a,#0x%02x", i);
3498 emitcode ("mov", "_spx,a");
3499 emitcode ("pop", "acc");
3504 emitcode ("inc", "_spx");
3508 /* if critical function then turn interrupts off */
3509 if (IFFUNC_ISCRITICAL (ftype))
3511 symbol *tlbl = newiTempLabel (NULL);
3512 emitcode ("setb", "c");
3513 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3514 emitcode ("clr", "c");
3515 emitcode ("", "%05d$:", (tlbl->key + 100));
3516 emitcode ("push", "psw"); /* save old ea via c in psw */
3520 /*-----------------------------------------------------------------*/
3521 /* genEndFunction - generates epilogue for functions */
3522 /*-----------------------------------------------------------------*/
3524 genEndFunction (iCode * ic)
3526 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3527 lineNode *lnp = lineCurr;
3529 bitVect *regsUsedPrologue;
3530 bitVect *regsUnneeded;
3533 _G.currentFunc = NULL;
3534 if (IFFUNC_ISNAKED(sym->type))
3536 emitcode(";", "naked function: no epilogue.");
3537 if (options.debug && currFunc)
3538 debugFile->writeEndFunction (currFunc, ic, 0);
3542 if (IFFUNC_ISCRITICAL (sym->type))
3544 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3546 emitcode ("rlc", "a"); /* save c in a */
3547 emitcode ("pop", "psw"); /* restore ea via c in psw */
3548 emitcode ("mov", "ea,c");
3549 emitcode ("rrc", "a"); /* restore c from a */
3553 emitcode ("pop", "psw"); /* restore ea via c in psw */
3554 emitcode ("mov", "ea,c");
3558 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3560 if (options.useXstack)
3564 emitcode ("mov", "sp,_bp");
3565 emitcode ("pop", "_bp");
3567 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3569 emitcode ("xch", "a,_bpx");
3570 emitcode ("mov", "r0,a");
3571 emitcode ("dec", "r0");
3572 emitcode ("movx", "a,@r0");
3573 emitcode ("xch", "a,_bpx");
3574 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3577 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3579 emitcode ("mov", "sp,_bp");
3580 emitcode ("pop", "_bp");
3584 /* restore the register bank */
3585 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3587 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3588 || !options.useXstack)
3590 /* Special case of ISR using non-zero bank with useXstack
3593 emitcode ("pop", "psw");
3597 if (IFFUNC_ISISR (sym->type))
3600 /* now we need to restore the registers */
3601 /* if this isr has no bank i.e. is going to
3602 run with bank 0 , then we need to save more
3604 if (!FUNC_REGBANK (sym->type))
3606 /* if this function does not call any other
3607 function then we can be economical and
3608 save only those registers that are used */
3609 if (!IFFUNC_HASFCALL(sym->type))
3613 /* if any registers used */
3616 bool bits_popped = FALSE;
3617 /* save the registers used */
3618 for (i = sym->regsUsed->size; i >= 0; i--)
3620 if (bitVectBitValue (sym->regsUsed, i))
3621 bits_popped = popReg (i, bits_popped);
3627 if (options.parms_in_bank1) {
3629 for (i = 7 ; i >= 0 ; i-- ) {
3630 emitcode ("pop","%s",rb1regs[i]);
3633 /* this function has a function call cannot
3634 determines register usage so we will have to pop the
3636 unsaveRBank (0, ic, FALSE);
3641 /* This ISR uses a non-zero bank.
3643 * Restore any register banks saved by genFunction
3646 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3649 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3651 if (savedBanks & (1 << ix))
3653 unsaveRBank(ix, NULL, FALSE);
3657 if (options.useXstack)
3659 /* Restore bank AFTER calling unsaveRBank,
3660 * since it can trash r0.
3662 emitcode ("pop", "psw");
3666 if (!inExcludeList ("dph"))
3667 emitcode ("pop", "dph");
3668 if (!inExcludeList ("dpl"))
3669 emitcode ("pop", "dpl");
3670 if (!inExcludeList ("b"))
3671 emitcode ("pop", "b");
3672 if (!inExcludeList ("acc"))
3673 emitcode ("pop", "acc");
3675 /* if debug then send end of function */
3676 if (options.debug && currFunc)
3678 debugFile->writeEndFunction (currFunc, ic, 1);
3681 emitcode ("reti", "");
3685 if (IFFUNC_CALLEESAVES(sym->type))
3689 /* if any registers used */
3692 /* save the registers used */
3693 for (i = sym->regsUsed->size; i >= 0; i--)
3695 if (bitVectBitValue (sym->regsUsed, i) ||
3696 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3697 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3700 else if (mcs51_ptrRegReq)
3702 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3703 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3708 /* if debug then send end of function */
3709 if (options.debug && currFunc)
3711 debugFile->writeEndFunction (currFunc, ic, 1);
3714 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3716 emitcode ("ljmp", "__sdcc_banked_ret");
3720 emitcode ("ret", "");
3724 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3727 /* If this was an interrupt handler using bank 0 that called another */
3728 /* function, then all registers must be saved; nothing to optimized. */
3729 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3730 && !FUNC_REGBANK(sym->type))
3733 /* There are no push/pops to optimize if not callee-saves or ISR */
3734 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3737 /* If there were stack parameters, we cannot optimize without also */
3738 /* fixing all of the stack offsets; this is too dificult to consider. */
3739 if (FUNC_HASSTACKPARM(sym->type))
3742 /* Compute the registers actually used */
3743 regsUsed = newBitVect (mcs51_nRegs);
3744 regsUsedPrologue = newBitVect (mcs51_nRegs);
3747 if (lnp->ic && lnp->ic->op == FUNCTION)
3748 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3750 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3752 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3753 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3760 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3761 && !bitVectBitValue (regsUsed, CND_IDX))
3763 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3764 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3765 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3766 bitVectUnSetBit (regsUsed, CND_IDX);
3769 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3771 /* If this was an interrupt handler that called another function */
3772 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3773 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3775 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3776 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3777 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3778 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3779 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3782 /* Remove the unneeded push/pops */
3783 regsUnneeded = newBitVect (mcs51_nRegs);
3786 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3788 if (!strncmp(lnp->line, "push", 4))
3790 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3791 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3793 connectLine (lnp->prev, lnp->next);
3794 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3797 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3799 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3800 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3802 connectLine (lnp->prev, lnp->next);
3803 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3810 for (idx = 0; idx < regsUnneeded->size; idx++)
3811 if (bitVectBitValue (regsUnneeded, idx))
3812 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3814 freeBitVect (regsUnneeded);
3815 freeBitVect (regsUsed);
3816 freeBitVect (regsUsedPrologue);
3819 /*-----------------------------------------------------------------*/
3820 /* genRet - generate code for return statement */
3821 /*-----------------------------------------------------------------*/
3825 int size, offset = 0, pushed = 0;
3827 D(emitcode ("; genRet",""));
3829 /* if we have no return value then
3830 just generate the "ret" */
3834 /* we have something to return then
3835 move the return value into place */
3836 aopOp (IC_LEFT (ic), ic, FALSE);
3837 size = AOP_SIZE (IC_LEFT (ic));
3840 if (IS_BIT(_G.currentFunc->etype))
3842 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3849 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3852 l = aopGet (IC_LEFT (ic), offset++,
3854 emitcode ("push", "%s", l);
3859 l = aopGet (IC_LEFT (ic), offset,
3861 if (strcmp (fReturn[offset], l))
3862 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3869 if (strcmp (fReturn[pushed], "a"))
3870 emitcode ("pop", fReturn[pushed]);
3872 emitcode ("pop", "acc");
3874 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3877 /* generate a jump to the return label
3878 if the next is not the return statement */
3879 if (!(ic->next && ic->next->op == LABEL &&
3880 IC_LABEL (ic->next) == returnLabel))
3882 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3886 /*-----------------------------------------------------------------*/
3887 /* genLabel - generates a label */
3888 /*-----------------------------------------------------------------*/
3890 genLabel (iCode * ic)
3892 /* special case never generate */
3893 if (IC_LABEL (ic) == entryLabel)
3896 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3899 /*-----------------------------------------------------------------*/
3900 /* genGoto - generates a ljmp */
3901 /*-----------------------------------------------------------------*/
3903 genGoto (iCode * ic)
3905 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3908 /*-----------------------------------------------------------------*/
3909 /* findLabelBackwards: walks back through the iCode chain looking */
3910 /* for the given label. Returns number of iCode instructions */
3911 /* between that label and given ic. */
3912 /* Returns zero if label not found. */
3913 /*-----------------------------------------------------------------*/
3915 findLabelBackwards (iCode * ic, int key)
3924 /* If we have any pushes or pops, we cannot predict the distance.
3925 I don't like this at all, this should be dealt with in the
3927 if (ic->op == IPUSH || ic->op == IPOP) {
3931 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3940 /*-----------------------------------------------------------------*/
3941 /* genPlusIncr :- does addition with increment if possible */
3942 /*-----------------------------------------------------------------*/
3944 genPlusIncr (iCode * ic)
3946 unsigned int icount;
3947 unsigned int size = getDataSize (IC_RESULT (ic));
3949 /* will try to generate an increment */
3950 /* if the right side is not a literal
3952 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3955 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3957 D(emitcode ("; genPlusIncr",""));
3959 /* if increment >=16 bits in register or direct space */
3960 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3961 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3962 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3970 /* If the next instruction is a goto and the goto target
3971 * is < 10 instructions previous to this, we can generate
3972 * jumps straight to that target.
3974 if (ic->next && ic->next->op == GOTO
3975 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3976 && labelRange <= 10)
3978 emitcode (";", "tail increment optimized");
3979 tlbl = IC_LABEL (ic->next);
3984 tlbl = newiTempLabel (NULL);
3987 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3988 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3989 IS_AOP_PREG (IC_RESULT (ic)))
3990 emitcode ("cjne", "%s,#0x00,%05d$",
3991 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3995 emitcode ("clr", "a");
3996 emitcode ("cjne", "a,%s,%05d$",
3997 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
4001 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4004 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4005 IS_AOP_PREG (IC_RESULT (ic)))
4006 emitcode ("cjne", "%s,#0x00,%05d$",
4007 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4010 emitcode ("cjne", "a,%s,%05d$",
4011 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
4014 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4018 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4019 IS_AOP_PREG (IC_RESULT (ic)))
4020 emitcode ("cjne", "%s,#0x00,%05d$",
4021 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4025 emitcode ("cjne", "a,%s,%05d$",
4026 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
4029 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4034 emitcode ("", "%05d$:", tlbl->key + 100);
4039 /* if result is dptr */
4040 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4041 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4042 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4043 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4045 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4051 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4054 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
4055 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
4057 emitcode ("inc", "dptr");
4062 /* if the literal value of the right hand side
4063 is greater than 4 then it is not worth it */
4067 /* if the sizes are greater than 1 then we cannot */
4068 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4069 AOP_SIZE (IC_LEFT (ic)) > 1)
4072 /* we can if the aops of the left & result match or
4073 if they are in registers and the registers are the
4075 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4080 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4081 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4082 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4088 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4097 /*-----------------------------------------------------------------*/
4098 /* outBitAcc - output a bit in acc */
4099 /*-----------------------------------------------------------------*/
4101 outBitAcc (operand * result)
4103 symbol *tlbl = newiTempLabel (NULL);
4104 /* if the result is a bit */
4105 if (AOP_TYPE (result) == AOP_CRY)
4107 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4111 emitcode ("jz", "%05d$", tlbl->key + 100);
4112 emitcode ("mov", "a,%s", one);
4113 emitcode ("", "%05d$:", tlbl->key + 100);
4118 /*-----------------------------------------------------------------*/
4119 /* genPlusBits - generates code for addition of two bits */
4120 /*-----------------------------------------------------------------*/
4122 genPlusBits (iCode * ic)
4124 D(emitcode ("; genPlusBits",""));
4126 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4128 symbol *lbl = newiTempLabel (NULL);
4129 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4130 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4131 emitcode ("cpl", "c");
4132 emitcode ("", "%05d$:", (lbl->key + 100));
4133 outBitC (IC_RESULT (ic));
4137 emitcode ("clr", "a");
4138 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4139 emitcode ("rlc", "a");
4140 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4141 emitcode ("addc", "a,#0x00");
4142 outAcc (IC_RESULT (ic));
4147 /* This is the original version of this code.
4149 * This is being kept around for reference,
4150 * because I am not entirely sure I got it right...
4153 adjustArithmeticResult (iCode * ic)
4155 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4156 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4157 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4158 aopPut (IC_RESULT (ic),
4159 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4161 isOperandVolatile (IC_RESULT (ic), FALSE));
4163 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4164 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4165 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4166 aopPut (IC_RESULT (ic),
4167 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4169 isOperandVolatile (IC_RESULT (ic), FALSE));
4171 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4172 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4173 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4174 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4175 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4178 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4179 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4183 /* This is the pure and virtuous version of this code.
4184 * I'm pretty certain it's right, but not enough to toss the old
4188 adjustArithmeticResult (iCode * ic)
4190 if (opIsGptr (IC_RESULT (ic)) &&
4191 opIsGptr (IC_LEFT (ic)) &&
4192 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4194 aopPut (IC_RESULT (ic),
4195 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4197 isOperandVolatile (IC_RESULT (ic), FALSE));
4200 if (opIsGptr (IC_RESULT (ic)) &&
4201 opIsGptr (IC_RIGHT (ic)) &&
4202 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4204 aopPut (IC_RESULT (ic),
4205 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4207 isOperandVolatile (IC_RESULT (ic), FALSE));
4210 if (opIsGptr (IC_RESULT (ic)) &&
4211 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4212 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4213 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4214 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4217 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4218 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4223 /*-----------------------------------------------------------------*/
4224 /* genPlus - generates code for addition */
4225 /*-----------------------------------------------------------------*/
4227 genPlus (iCode * ic)
4229 int size, offset = 0;
4232 operand *leftOp, *rightOp;
4235 /* special cases :- */
4237 D(emitcode ("; genPlus",""));
4239 aopOp (IC_LEFT (ic), ic, FALSE);
4240 aopOp (IC_RIGHT (ic), ic, FALSE);
4241 aopOp (IC_RESULT (ic), ic, TRUE);
4243 /* if literal, literal on the right or
4244 if left requires ACC or right is already
4246 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4247 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4248 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4250 operand *t = IC_RIGHT (ic);
4251 IC_RIGHT (ic) = IC_LEFT (ic);
4255 /* if both left & right are in bit
4257 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4258 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4264 /* if left in bit space & right literal */
4265 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4266 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4268 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4269 /* if result in bit space */
4270 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4272 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4273 emitcode ("cpl", "c");
4274 outBitC (IC_RESULT (ic));
4278 size = getDataSize (IC_RESULT (ic));
4281 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4282 emitcode ("addc", "a,#00");
4283 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4289 /* if I can do an increment instead
4290 of add then GOOD for ME */
4291 if (genPlusIncr (ic) == TRUE)
4294 size = getDataSize (IC_RESULT (ic));
4295 leftOp = IC_LEFT(ic);
4296 rightOp = IC_RIGHT(ic);
4299 /* if this is an add for an array access
4300 at a 256 byte boundary */
4302 && AOP_TYPE (op) == AOP_IMMD
4304 && IS_SPEC (OP_SYM_ETYPE (op))
4305 && SPEC_ABSA (OP_SYM_ETYPE (op))
4306 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4309 D(emitcode ("; genPlus aligned array",""));
4310 aopPut (IC_RESULT (ic),
4311 aopGet (rightOp, 0, FALSE, FALSE),
4313 isOperandVolatile (IC_RESULT (ic), FALSE));
4315 if( 1 == getDataSize (IC_RIGHT (ic)) )
4317 aopPut (IC_RESULT (ic),
4318 aopGet (leftOp, 1, FALSE, FALSE),
4320 isOperandVolatile (IC_RESULT (ic), FALSE));
4324 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4325 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4326 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4331 /* if the lower bytes of a literal are zero skip the addition */
4332 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4334 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4335 (skip_bytes+1 < size))
4340 D(emitcode ("; genPlus shortcut",""));
4345 if( offset >= skip_bytes )
4347 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4350 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4352 emitcode("xch", "a,b");
4353 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4354 emitcode (add, "a,b");
4357 else if (aopGetUsesAcc (leftOp, offset))
4359 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4360 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4364 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4365 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4367 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4368 add = "addc"; /* further adds must propagate carry */
4372 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4373 isOperandVolatile (IC_RESULT (ic), FALSE))
4376 aopPut (IC_RESULT (ic),
4377 aopGet (leftOp, offset, FALSE, FALSE),
4379 isOperandVolatile (IC_RESULT (ic), FALSE));
4385 adjustArithmeticResult (ic);
4388 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4389 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4390 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4393 /*-----------------------------------------------------------------*/
4394 /* genMinusDec :- does subtraction with decrement if possible */
4395 /*-----------------------------------------------------------------*/
4397 genMinusDec (iCode * ic)
4399 unsigned int icount;
4400 unsigned int size = getDataSize (IC_RESULT (ic));
4402 /* will try to generate an increment */
4403 /* if the right side is not a literal
4405 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4408 /* if the literal value of the right hand side
4409 is greater than 4 then it is not worth it */
4410 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4413 D(emitcode ("; genMinusDec",""));
4415 /* if decrement >=16 bits in register or direct space */
4416 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4417 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4425 /* If the next instruction is a goto and the goto target
4426 * is <= 10 instructions previous to this, we can generate
4427 * jumps straight to that target.
4429 if (ic->next && ic->next->op == GOTO
4430 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4431 && labelRange <= 10)
4433 emitcode (";", "tail decrement optimized");
4434 tlbl = IC_LABEL (ic->next);
4439 tlbl = newiTempLabel (NULL);
4443 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4444 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4445 IS_AOP_PREG (IC_RESULT (ic)))
4446 emitcode ("cjne", "%s,#0xff,%05d$"
4447 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4451 emitcode ("mov", "a,#0xff");
4452 emitcode ("cjne", "a,%s,%05d$"
4453 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4456 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4459 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4460 IS_AOP_PREG (IC_RESULT (ic)))
4461 emitcode ("cjne", "%s,#0xff,%05d$"
4462 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4466 emitcode ("cjne", "a,%s,%05d$"
4467 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4470 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4474 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4475 IS_AOP_PREG (IC_RESULT (ic)))
4476 emitcode ("cjne", "%s,#0xff,%05d$"
4477 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4481 emitcode ("cjne", "a,%s,%05d$"
4482 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4485 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4489 emitcode ("", "%05d$:", tlbl->key + 100);
4494 /* if the sizes are greater than 1 then we cannot */
4495 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4496 AOP_SIZE (IC_LEFT (ic)) > 1)
4499 /* we can if the aops of the left & result match or
4500 if they are in registers and the registers are the
4502 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4506 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4508 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4513 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4517 emitcode ("dec", "%s", l);
4519 if (AOP_NEEDSACC (IC_RESULT (ic)))
4520 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4528 /*-----------------------------------------------------------------*/
4529 /* addSign - complete with sign */
4530 /*-----------------------------------------------------------------*/
4532 addSign (operand * result, int offset, int sign)
4534 int size = (getDataSize (result) - offset);
4539 emitcode ("rlc", "a");
4540 emitcode ("subb", "a,acc");
4542 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4546 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4550 /*-----------------------------------------------------------------*/
4551 /* genMinusBits - generates code for subtraction of two bits */
4552 /*-----------------------------------------------------------------*/
4554 genMinusBits (iCode * ic)
4556 symbol *lbl = newiTempLabel (NULL);
4558 D(emitcode ("; genMinusBits",""));
4560 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4562 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4563 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4564 emitcode ("cpl", "c");
4565 emitcode ("", "%05d$:", (lbl->key + 100));
4566 outBitC (IC_RESULT (ic));
4570 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4571 emitcode ("subb", "a,acc");
4572 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4573 emitcode ("inc", "a");
4574 emitcode ("", "%05d$:", (lbl->key + 100));
4575 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4576 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4580 /*-----------------------------------------------------------------*/
4581 /* genMinus - generates code for subtraction */
4582 /*-----------------------------------------------------------------*/
4584 genMinus (iCode * ic)
4586 int size, offset = 0;
4588 D(emitcode ("; genMinus",""));
4590 aopOp (IC_LEFT (ic), ic, FALSE);
4591 aopOp (IC_RIGHT (ic), ic, FALSE);
4592 aopOp (IC_RESULT (ic), ic, TRUE);
4594 /* special cases :- */
4595 /* if both left & right are in bit space */
4596 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4597 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4603 /* if I can do an decrement instead
4604 of subtract then GOOD for ME */
4605 if (genMinusDec (ic) == TRUE)
4608 size = getDataSize (IC_RESULT (ic));
4610 /* if literal, add a,#-lit, else normal subb */
4611 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4613 unsigned long lit = 0L;
4614 bool useCarry = FALSE;
4616 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4621 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4623 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4624 if (!offset && !size && lit== (unsigned long) -1)
4626 emitcode ("dec", "a");
4630 /* first add without previous c */
4631 emitcode ("add", "a,#0x%02x",
4632 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4637 emitcode ("addc", "a,#0x%02x",
4638 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4640 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4644 /* no need to add zeroes */
4645 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4647 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4648 offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4656 operand *leftOp, *rightOp;
4658 leftOp = IC_LEFT(ic);
4659 rightOp = IC_RIGHT(ic);
4663 if (aopGetUsesAcc(rightOp, offset)) {
4664 if (aopGetUsesAcc(leftOp, offset)) {
4667 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4669 emitcode ("mov", "b,a");
4672 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4673 emitcode ("subb", "a,b");
4676 /* reverse subtraction with 2's complement */
4678 emitcode( "setb", "c");
4680 emitcode( "cpl", "c");
4681 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4682 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4683 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4684 emitcode("cpl", "a");
4685 if (size) /* skip if last byte */
4686 emitcode( "cpl", "c");
4689 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4692 emitcode ("subb", "a,%s",
4693 aopGet(rightOp, offset, FALSE, TRUE));
4696 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4701 adjustArithmeticResult (ic);
4704 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4705 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4706 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4710 /*-----------------------------------------------------------------*/
4711 /* genMultbits :- multiplication of bits */
4712 /*-----------------------------------------------------------------*/
4714 genMultbits (operand * left,
4718 D(emitcode ("; genMultbits",""));
4720 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4721 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4725 /*-----------------------------------------------------------------*/
4726 /* genMultOneByte : 8*8=8/16 bit multiplication */
4727 /*-----------------------------------------------------------------*/
4729 genMultOneByte (operand * left,
4734 int size = AOP_SIZE (result);
4735 bool runtimeSign, compiletimeSign;
4736 bool lUnsigned, rUnsigned, pushedB;
4738 D(emitcode ("; genMultOneByte",""));
4740 if (size < 1 || size > 2)
4742 /* this should never happen */
4743 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4744 AOP_SIZE(result), __FILE__, lineno);
4748 /* (if two literals: the value is computed before) */
4749 /* if one literal, literal on the right */
4750 if (AOP_TYPE (left) == AOP_LIT)
4755 /* emitcode (";", "swapped left and right"); */
4757 /* if no literal, unsigned on the right: shorter code */
4758 if ( AOP_TYPE (right) != AOP_LIT
4759 && SPEC_USIGN (getSpec (operandType (left))))
4766 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4767 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4771 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4772 no need to take care about the signedness! */
4773 || (lUnsigned && rUnsigned))
4775 /* just an unsigned 8 * 8 = 8 multiply
4777 /* emitcode (";","unsigned"); */
4778 /* TODO: check for accumulator clash between left & right aops? */
4780 if (AOP_TYPE (right) == AOP_LIT)
4782 /* moving to accumulator first helps peepholes */
4783 MOVA (aopGet (left, 0, FALSE, FALSE));
4784 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4788 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4789 MOVA (aopGet (left, 0, FALSE, FALSE));
4792 emitcode ("mul", "ab");
4793 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4795 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4801 /* we have to do a signed multiply */
4802 /* emitcode (";", "signed"); */
4804 /* now sign adjust for both left & right */
4806 /* let's see what's needed: */
4807 /* apply negative sign during runtime */
4808 runtimeSign = FALSE;
4809 /* negative sign from literals */
4810 compiletimeSign = FALSE;
4814 if (AOP_TYPE(left) == AOP_LIT)
4816 /* signed literal */
4817 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4819 compiletimeSign = TRUE;
4822 /* signed but not literal */
4828 if (AOP_TYPE(right) == AOP_LIT)
4830 /* signed literal */
4831 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4833 compiletimeSign ^= TRUE;
4836 /* signed but not literal */
4840 /* initialize F0, which stores the runtime sign */
4843 if (compiletimeSign)
4844 emitcode ("setb", "F0"); /* set sign flag */
4846 emitcode ("clr", "F0"); /* reset sign flag */
4849 /* save the signs of the operands */
4850 if (AOP_TYPE(right) == AOP_LIT)
4852 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4854 if (!rUnsigned && val < 0)
4855 emitcode ("mov", "b,#0x%02x", -val);
4857 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4859 else /* ! literal */
4861 if (rUnsigned) /* emitcode (";", "signed"); */
4863 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4866 MOVA (aopGet (right, 0, FALSE, FALSE));
4867 lbl = newiTempLabel (NULL);
4868 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4869 emitcode ("cpl", "F0"); /* complement sign flag */
4870 emitcode ("cpl", "a"); /* 2's complement */
4871 emitcode ("inc", "a");
4872 emitcode ("", "%05d$:", (lbl->key + 100));
4873 emitcode ("mov", "b,a");
4877 if (AOP_TYPE(left) == AOP_LIT)
4879 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4881 if (!lUnsigned && val < 0)
4882 emitcode ("mov", "a,#0x%02x", -val);
4884 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4886 else /* ! literal */
4888 MOVA (aopGet (left, 0, FALSE, FALSE));
4892 lbl = newiTempLabel (NULL);
4893 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4894 emitcode ("cpl", "F0"); /* complement sign flag */
4895 emitcode ("cpl", "a"); /* 2's complement */
4896 emitcode ("inc", "a");
4897 emitcode ("", "%05d$:", (lbl->key + 100));
4901 /* now the multiplication */
4902 emitcode ("mul", "ab");
4903 if (runtimeSign || compiletimeSign)
4905 lbl = newiTempLabel (NULL);
4907 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4908 emitcode ("cpl", "a"); /* lsb 2's complement */
4910 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4913 emitcode ("add", "a,#1"); /* this sets carry flag */
4914 emitcode ("xch", "a,b");
4915 emitcode ("cpl", "a"); /* msb 2's complement */
4916 emitcode ("addc", "a,#0");
4917 emitcode ("xch", "a,b");
4919 emitcode ("", "%05d$:", (lbl->key + 100));
4921 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4923 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4928 /*-----------------------------------------------------------------*/
4929 /* genMult - generates code for multiplication */
4930 /*-----------------------------------------------------------------*/
4932 genMult (iCode * ic)
4934 operand *left = IC_LEFT (ic);
4935 operand *right = IC_RIGHT (ic);
4936 operand *result = IC_RESULT (ic);
4938 D(emitcode ("; genMult",""));
4940 /* assign the asmops */
4941 aopOp (left, ic, FALSE);
4942 aopOp (right, ic, FALSE);
4943 aopOp (result, ic, TRUE);
4945 /* special cases first */
4947 if (AOP_TYPE (left) == AOP_CRY &&
4948 AOP_TYPE (right) == AOP_CRY)
4950 genMultbits (left, right, result);
4954 /* if both are of size == 1 */
4955 #if 0 // one of them can be a sloc shared with the result
4956 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4958 if (getSize(operandType(left)) == 1 &&
4959 getSize(operandType(right)) == 1)
4962 genMultOneByte (left, right, result);
4966 /* should have been converted to function call */
4967 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4968 getSize(OP_SYMBOL(right)->type));
4972 freeAsmop (result, NULL, ic, TRUE);
4973 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4974 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4977 /*-----------------------------------------------------------------*/
4978 /* genDivbits :- division of bits */
4979 /*-----------------------------------------------------------------*/
4981 genDivbits (operand * left,
4988 D(emitcode ("; genDivbits",""));
4992 /* the result must be bit */
4993 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4994 l = aopGet (left, 0, FALSE, FALSE);
4998 emitcode ("div", "ab");
4999 emitcode ("rrc", "a");
5003 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5006 /*-----------------------------------------------------------------*/
5007 /* genDivOneByte : 8 bit division */
5008 /*-----------------------------------------------------------------*/
5010 genDivOneByte (operand * left,
5014 bool lUnsigned, rUnsigned, pushedB;
5015 bool runtimeSign, compiletimeSign;
5016 bool accuse = FALSE;
5017 bool pushedA = FALSE;
5021 D(emitcode ("; genDivOneByte",""));
5023 /* Why is it necessary that genDivOneByte() can return an int result?
5026 volatile unsigned char uc;
5027 volatile signed char sc1, sc2;
5040 In all cases a one byte result would overflow, the following cast to int
5041 would return the wrong result.
5043 Two possible solution:
5044 a) cast operands to int, if ((unsigned) / (signed)) or
5045 ((signed) / (signed))
5046 b) return an 16 bit signed int; this is what we're doing here!
5049 size = AOP_SIZE (result) - 1;
5051 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5052 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5056 /* signed or unsigned */
5057 if (lUnsigned && rUnsigned)
5059 /* unsigned is easy */
5060 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5061 MOVA (aopGet (left, 0, FALSE, FALSE));
5062 emitcode ("div", "ab");
5063 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5065 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5071 /* signed is a little bit more difficult */
5073 /* now sign adjust for both left & right */
5075 /* let's see what's needed: */
5076 /* apply negative sign during runtime */
5077 runtimeSign = FALSE;
5078 /* negative sign from literals */
5079 compiletimeSign = FALSE;
5083 if (AOP_TYPE(left) == AOP_LIT)
5085 /* signed literal */
5086 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5088 compiletimeSign = TRUE;
5091 /* signed but not literal */
5097 if (AOP_TYPE(right) == AOP_LIT)
5099 /* signed literal */
5100 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5102 compiletimeSign ^= TRUE;
5105 /* signed but not literal */
5109 /* initialize F0, which stores the runtime sign */
5112 if (compiletimeSign)
5113 emitcode ("setb", "F0"); /* set sign flag */
5115 emitcode ("clr", "F0"); /* reset sign flag */
5118 /* save the signs of the operands */
5119 if (AOP_TYPE(right) == AOP_LIT)
5121 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5123 if (!rUnsigned && val < 0)
5124 emitcode ("mov", "b,#0x%02x", -val);
5126 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5128 else /* ! literal */
5131 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5134 MOVA (aopGet (right, 0, FALSE, FALSE));
5135 lbl = newiTempLabel (NULL);
5136 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5137 emitcode ("cpl", "F0"); /* complement sign flag */
5138 emitcode ("cpl", "a"); /* 2's complement */
5139 emitcode ("inc", "a");
5140 emitcode ("", "%05d$:", (lbl->key + 100));
5141 emitcode ("mov", "b,a");
5145 if (AOP_TYPE(left) == AOP_LIT)
5147 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5149 if (!lUnsigned && val < 0)
5150 emitcode ("mov", "a,#0x%02x", -val);
5152 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5154 else /* ! literal */
5156 MOVA (aopGet (left, 0, FALSE, FALSE));
5160 lbl = newiTempLabel (NULL);
5161 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5162 emitcode ("cpl", "F0"); /* complement sign flag */
5163 emitcode ("cpl", "a"); /* 2's complement */
5164 emitcode ("inc", "a");
5165 emitcode ("", "%05d$:", (lbl->key + 100));
5169 /* now the division */
5170 emitcode ("div", "ab");
5172 if (runtimeSign || compiletimeSign)
5174 lbl = newiTempLabel (NULL);
5176 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5177 emitcode ("cpl", "a"); /* lsb 2's complement */
5178 emitcode ("inc", "a");
5179 emitcode ("", "%05d$:", (lbl->key + 100));
5181 accuse = aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5184 /* msb is 0x00 or 0xff depending on the sign */
5189 emitcode ("push", "acc");
5192 emitcode ("mov", "c,F0");
5193 emitcode ("subb", "a,acc");
5195 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5197 else /* compiletimeSign */
5199 if (aopPutUsesAcc (result, "#0xFF", offset))
5201 emitcode ("push", "acc");
5205 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5211 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5213 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5217 emitcode ("pop", "acc");
5221 /*-----------------------------------------------------------------*/
5222 /* genDiv - generates code for division */
5223 /*-----------------------------------------------------------------*/
5227 operand *left = IC_LEFT (ic);
5228 operand *right = IC_RIGHT (ic);
5229 operand *result = IC_RESULT (ic);
5231 D(emitcode ("; genDiv",""));
5233 /* assign the amsops */
5234 aopOp (left, ic, FALSE);
5235 aopOp (right, ic, FALSE);
5236 aopOp (result, ic, TRUE);
5238 /* special cases first */
5240 if (AOP_TYPE (left) == AOP_CRY &&
5241 AOP_TYPE (right) == AOP_CRY)
5243 genDivbits (left, right, result);
5247 /* if both are of size == 1 */
5248 if (AOP_SIZE (left) == 1 &&
5249 AOP_SIZE (right) == 1)
5251 genDivOneByte (left, right, result);
5255 /* should have been converted to function call */
5258 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5259 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5260 freeAsmop (result, NULL, ic, TRUE);
5263 /*-----------------------------------------------------------------*/
5264 /* genModbits :- modulus of bits */
5265 /*-----------------------------------------------------------------*/
5267 genModbits (operand * left,
5274 D(emitcode ("; genModbits",""));
5278 /* the result must be bit */
5279 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5280 l = aopGet (left, 0, FALSE, FALSE);
5284 emitcode ("div", "ab");
5285 emitcode ("mov", "a,b");
5286 emitcode ("rrc", "a");
5290 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5293 /*-----------------------------------------------------------------*/
5294 /* genModOneByte : 8 bit modulus */
5295 /*-----------------------------------------------------------------*/
5297 genModOneByte (operand * left,
5301 bool lUnsigned, rUnsigned, pushedB;
5302 bool runtimeSign, compiletimeSign;
5306 D(emitcode ("; genModOneByte",""));
5308 size = AOP_SIZE (result) - 1;
5310 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5311 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5313 /* if right is a literal, check it for 2^n */
5314 if (AOP_TYPE(right) == AOP_LIT)
5316 unsigned char val = abs((int) operandLitValue(right));
5317 symbol *lbl2 = NULL;
5321 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5330 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5331 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5332 /* because iCode should have been changed to genAnd */
5333 /* see file "SDCCopt.c", function "convertToFcall()" */
5335 MOVA (aopGet (left, 0, FALSE, FALSE));
5336 emitcode ("mov", "c,acc.7");
5337 emitcode ("anl", "a,#0x%02x", val - 1);
5338 lbl = newiTempLabel (NULL);
5339 emitcode ("jz", "%05d$", (lbl->key + 100));
5340 emitcode ("jnc", "%05d$", (lbl->key + 100));
5341 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5347 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5349 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5350 lbl2 = newiTempLabel (NULL);
5351 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5353 emitcode ("", "%05d$:", (lbl->key + 100));
5354 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5356 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5359 emitcode ("", "%05d$:", (lbl2->key + 100));
5370 /* signed or unsigned */
5371 if (lUnsigned && rUnsigned)
5373 /* unsigned is easy */
5374 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5375 MOVA (aopGet (left, 0, FALSE, FALSE));
5376 emitcode ("div", "ab");
5377 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5379 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5385 /* signed is a little bit more difficult */
5387 /* now sign adjust for both left & right */
5389 /* modulus: sign of the right operand has no influence on the result! */
5390 if (AOP_TYPE(right) == AOP_LIT)
5392 signed char val = (char) operandLitValue(right);
5394 if (!rUnsigned && val < 0)
5395 emitcode ("mov", "b,#0x%02x", -val);
5397 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5399 else /* not literal */
5402 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5405 MOVA (aopGet (right, 0, FALSE, FALSE));
5406 lbl = newiTempLabel (NULL);
5407 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5408 emitcode ("cpl", "a"); /* 2's complement */
5409 emitcode ("inc", "a");
5410 emitcode ("", "%05d$:", (lbl->key + 100));
5411 emitcode ("mov", "b,a");
5415 /* let's see what's needed: */
5416 /* apply negative sign during runtime */
5417 runtimeSign = FALSE;
5418 /* negative sign from literals */
5419 compiletimeSign = FALSE;
5421 /* sign adjust left side */
5422 if (AOP_TYPE(left) == AOP_LIT)
5424 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5426 if (!lUnsigned && val < 0)
5428 compiletimeSign = TRUE; /* set sign flag */
5429 emitcode ("mov", "a,#0x%02x", -val);
5432 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5434 else /* ! literal */
5436 MOVA (aopGet (left, 0, FALSE, FALSE));
5441 emitcode ("clr", "F0"); /* clear sign flag */
5443 lbl = newiTempLabel (NULL);
5444 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5445 emitcode ("setb", "F0"); /* set sign flag */
5446 emitcode ("cpl", "a"); /* 2's complement */
5447 emitcode ("inc", "a");
5448 emitcode ("", "%05d$:", (lbl->key + 100));
5452 /* now the modulus */
5453 emitcode ("div", "ab");
5455 if (runtimeSign || compiletimeSign)
5457 emitcode ("mov", "a,b");
5458 lbl = newiTempLabel (NULL);
5460 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5461 emitcode ("cpl", "a"); /* 2's complement */
5462 emitcode ("inc", "a");
5463 emitcode ("", "%05d$:", (lbl->key + 100));
5465 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5468 /* msb is 0x00 or 0xff depending on the sign */
5471 emitcode ("mov", "c,F0");
5472 emitcode ("subb", "a,acc");
5474 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5476 else /* compiletimeSign */
5478 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5483 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5485 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5491 /*-----------------------------------------------------------------*/
5492 /* genMod - generates code for division */
5493 /*-----------------------------------------------------------------*/
5497 operand *left = IC_LEFT (ic);
5498 operand *right = IC_RIGHT (ic);
5499 operand *result = IC_RESULT (ic);
5501 D(emitcode ("; genMod",""));
5503 /* assign the asmops */
5504 aopOp (left, ic, FALSE);
5505 aopOp (right, ic, FALSE);
5506 aopOp (result, ic, TRUE);
5508 /* special cases first */
5510 if (AOP_TYPE (left) == AOP_CRY &&
5511 AOP_TYPE (right) == AOP_CRY)
5513 genModbits (left, right, result);
5517 /* if both are of size == 1 */
5518 if (AOP_SIZE (left) == 1 &&
5519 AOP_SIZE (right) == 1)
5521 genModOneByte (left, right, result);
5525 /* should have been converted to function call */
5529 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5530 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5531 freeAsmop (result, NULL, ic, TRUE);
5534 /*-----------------------------------------------------------------*/
5535 /* genIfxJump :- will create a jump depending on the ifx */
5536 /*-----------------------------------------------------------------*/
5538 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5541 symbol *tlbl = newiTempLabel (NULL);
5544 D(emitcode ("; genIfxJump",""));
5546 /* if true label then we jump if condition
5550 jlbl = IC_TRUE (ic);
5551 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5552 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5556 /* false label is present */
5557 jlbl = IC_FALSE (ic);
5558 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5559 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5561 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5562 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5564 emitcode (inst, "%05d$", tlbl->key + 100);
5565 freeForBranchAsmop (result);
5566 freeForBranchAsmop (right);
5567 freeForBranchAsmop (left);
5568 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5569 emitcode ("", "%05d$:", tlbl->key + 100);
5571 /* mark the icode as generated */
5575 /*-----------------------------------------------------------------*/
5576 /* genCmp :- greater or less than comparison */
5577 /*-----------------------------------------------------------------*/
5579 genCmp (operand * left, operand * right,
5580 operand * result, iCode * ifx, int sign, iCode *ic)
5582 int size, offset = 0;
5583 unsigned long lit = 0L;
5586 D(emitcode ("; genCmp",""));
5588 /* if left & right are bit variables */
5589 if (AOP_TYPE (left) == AOP_CRY &&
5590 AOP_TYPE (right) == AOP_CRY)
5592 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5593 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5597 /* subtract right from left if at the
5598 end the carry flag is set then we know that
5599 left is greater than right */
5600 size = max (AOP_SIZE (left), AOP_SIZE (right));
5602 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5603 if ((size == 1) && !sign &&
5604 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5606 symbol *lbl = newiTempLabel (NULL);
5607 emitcode ("cjne", "%s,%s,%05d$",
5608 aopGet (left, offset, FALSE, FALSE),
5609 aopGet (right, offset, FALSE, FALSE),
5611 emitcode ("", "%05d$:", lbl->key + 100);
5615 if (AOP_TYPE (right) == AOP_LIT)
5617 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5618 /* optimize if(x < 0) or if(x >= 0) */
5627 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5628 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5630 genIfxJump (ifx, "acc.7", left, right, result);
5631 freeAsmop (right, NULL, ic, TRUE);
5632 freeAsmop (left, NULL, ic, TRUE);
5637 emitcode ("rlc", "a");
5645 bool pushedB = FALSE;
5646 rightInB = aopGetUsesAcc(right, offset);
5650 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5652 MOVA (aopGet (left, offset, FALSE, FALSE));
5653 if (sign && size == 0)
5655 emitcode ("xrl", "a,#0x80");
5656 if (AOP_TYPE (right) == AOP_LIT)
5658 unsigned long lit = (unsigned long)
5659 floatFromVal (AOP (right)->aopu.aop_lit);
5660 emitcode ("subb", "a,#0x%02x",
5661 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5669 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5671 emitcode ("xrl", "b,#0x80");
5672 emitcode ("subb", "a,b");
5678 emitcode ("subb", "a,b");
5680 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5690 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5691 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5692 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5698 /* if the result is used in the next
5699 ifx conditional branch then generate
5700 code a little differently */
5702 genIfxJump (ifx, "c", NULL, NULL, result);
5705 /* leave the result in acc */
5709 /*-----------------------------------------------------------------*/
5710 /* genCmpGt :- greater than comparison */
5711 /*-----------------------------------------------------------------*/
5713 genCmpGt (iCode * ic, iCode * ifx)
5715 operand *left, *right, *result;
5716 sym_link *letype, *retype;
5719 D(emitcode ("; genCmpGt",""));
5721 left = IC_LEFT (ic);
5722 right = IC_RIGHT (ic);
5723 result = IC_RESULT (ic);
5725 letype = getSpec (operandType (left));
5726 retype = getSpec (operandType (right));
5727 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5728 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5729 /* assign the amsops */
5730 aopOp (left, ic, FALSE);
5731 aopOp (right, ic, FALSE);
5732 aopOp (result, ic, TRUE);
5734 genCmp (right, left, result, ifx, sign, ic);
5736 freeAsmop (result, NULL, ic, TRUE);
5739 /*-----------------------------------------------------------------*/
5740 /* genCmpLt - less than comparisons */
5741 /*-----------------------------------------------------------------*/
5743 genCmpLt (iCode * ic, iCode * ifx)
5745 operand *left, *right, *result;
5746 sym_link *letype, *retype;
5749 D(emitcode ("; genCmpLt",""));
5751 left = IC_LEFT (ic);
5752 right = IC_RIGHT (ic);
5753 result = IC_RESULT (ic);
5755 letype = getSpec (operandType (left));
5756 retype = getSpec (operandType (right));
5757 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5758 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5759 /* assign the amsops */
5760 aopOp (left, ic, FALSE);
5761 aopOp (right, ic, FALSE);
5762 aopOp (result, ic, TRUE);
5764 genCmp (left, right, result, ifx, sign, ic);
5766 freeAsmop (result, NULL, ic, TRUE);
5769 /*-----------------------------------------------------------------*/
5770 /* gencjneshort - compare and jump if not equal */
5771 /*-----------------------------------------------------------------*/
5773 gencjneshort (operand * left, operand * right, symbol * lbl)
5775 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5777 unsigned long lit = 0L;
5779 /* if the left side is a literal or
5780 if the right is in a pointer register and left
5782 if ((AOP_TYPE (left) == AOP_LIT) ||
5783 (AOP_TYPE (left) == AOP_IMMD) ||
5784 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5791 if (AOP_TYPE (right) == AOP_LIT)
5792 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5794 /* if the right side is a literal then anything goes */
5795 if (AOP_TYPE (right) == AOP_LIT &&
5796 AOP_TYPE (left) != AOP_DIR &&
5797 AOP_TYPE (left) != AOP_IMMD)
5801 emitcode ("cjne", "%s,%s,%05d$",
5802 aopGet (left, offset, FALSE, FALSE),
5803 aopGet (right, offset, FALSE, FALSE),
5809 /* if the right side is in a register or in direct space or
5810 if the left is a pointer register & right is not */
5811 else if (AOP_TYPE (right) == AOP_REG ||
5812 AOP_TYPE (right) == AOP_DIR ||
5813 AOP_TYPE (right) == AOP_LIT ||
5814 AOP_TYPE (right) == AOP_IMMD ||
5815 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5816 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5820 MOVA (aopGet (left, offset, FALSE, FALSE));
5821 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5822 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5823 emitcode ("jnz", "%05d$", lbl->key + 100);
5825 emitcode ("cjne", "a,%s,%05d$",
5826 aopGet (right, offset, FALSE, TRUE),
5833 /* right is a pointer reg need both a & b */
5837 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5838 wassertl(!BINUSE, "B was in use");
5839 l = aopGet (left, offset, FALSE, FALSE);
5840 if (strcmp (l, "b"))
5841 emitcode ("mov", "b,%s", l);
5842 MOVA (aopGet (right, offset, FALSE, FALSE));
5843 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5849 /*-----------------------------------------------------------------*/
5850 /* gencjne - compare and jump if not equal */
5851 /*-----------------------------------------------------------------*/
5853 gencjne (operand * left, operand * right, symbol * lbl)
5855 symbol *tlbl = newiTempLabel (NULL);
5857 gencjneshort (left, right, lbl);
5859 emitcode ("mov", "a,%s", one);
5860 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5861 emitcode ("", "%05d$:", lbl->key + 100);
5862 emitcode ("clr", "a");
5863 emitcode ("", "%05d$:", tlbl->key + 100);
5866 /*-----------------------------------------------------------------*/
5867 /* genCmpEq - generates code for equal to */
5868 /*-----------------------------------------------------------------*/
5870 genCmpEq (iCode * ic, iCode * ifx)
5872 operand *left, *right, *result;
5874 D(emitcode ("; genCmpEq",""));
5876 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5877 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5878 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5880 /* if literal, literal on the right or
5881 if the right is in a pointer register and left
5883 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5884 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5886 operand *t = IC_RIGHT (ic);
5887 IC_RIGHT (ic) = IC_LEFT (ic);
5891 if (ifx && !AOP_SIZE (result))
5894 /* if they are both bit variables */
5895 if (AOP_TYPE (left) == AOP_CRY &&
5896 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5898 if (AOP_TYPE (right) == AOP_LIT)
5900 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5903 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5904 emitcode ("cpl", "c");
5908 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5912 emitcode ("clr", "c");
5914 /* AOP_TYPE(right) == AOP_CRY */
5918 symbol *lbl = newiTempLabel (NULL);
5919 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5920 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5921 emitcode ("cpl", "c");
5922 emitcode ("", "%05d$:", (lbl->key + 100));
5924 /* if true label then we jump if condition
5926 tlbl = newiTempLabel (NULL);
5929 emitcode ("jnc", "%05d$", tlbl->key + 100);
5930 freeForBranchAsmop (result);
5931 freeForBranchAsmop (right);
5932 freeForBranchAsmop (left);
5933 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5937 emitcode ("jc", "%05d$", tlbl->key + 100);
5938 freeForBranchAsmop (result);
5939 freeForBranchAsmop (right);
5940 freeForBranchAsmop (left);
5941 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5943 emitcode ("", "%05d$:", tlbl->key + 100);
5947 tlbl = newiTempLabel (NULL);
5948 gencjneshort (left, right, tlbl);
5951 freeForBranchAsmop (result);
5952 freeForBranchAsmop (right);
5953 freeForBranchAsmop (left);
5954 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5955 emitcode ("", "%05d$:", tlbl->key + 100);
5959 symbol *lbl = newiTempLabel (NULL);
5960 emitcode ("sjmp", "%05d$", lbl->key + 100);
5961 emitcode ("", "%05d$:", tlbl->key + 100);
5962 freeForBranchAsmop (result);
5963 freeForBranchAsmop (right);
5964 freeForBranchAsmop (left);
5965 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5966 emitcode ("", "%05d$:", lbl->key + 100);
5969 /* mark the icode as generated */
5974 /* if they are both bit variables */
5975 if (AOP_TYPE (left) == AOP_CRY &&
5976 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5978 if (AOP_TYPE (right) == AOP_LIT)
5980 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5983 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5984 emitcode ("cpl", "c");
5988 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5992 emitcode ("clr", "c");
5994 /* AOP_TYPE(right) == AOP_CRY */
5998 symbol *lbl = newiTempLabel (NULL);
5999 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6000 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
6001 emitcode ("cpl", "c");
6002 emitcode ("", "%05d$:", (lbl->key + 100));
6005 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6012 genIfxJump (ifx, "c", left, right, result);
6015 /* if the result is used in an arithmetic operation
6016 then put the result in place */
6021 gencjne (left, right, newiTempLabel (NULL));
6022 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
6024 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
6029 genIfxJump (ifx, "a", left, right, result);
6032 /* if the result is used in an arithmetic operation
6033 then put the result in place */
6034 if (AOP_TYPE (result) != AOP_CRY)
6036 /* leave the result in acc */
6040 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6041 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6042 freeAsmop (result, NULL, ic, TRUE);
6045 /*-----------------------------------------------------------------*/
6046 /* ifxForOp - returns the icode containing the ifx for operand */
6047 /*-----------------------------------------------------------------*/
6049 ifxForOp (operand * op, iCode * ic)
6051 /* if true symbol then needs to be assigned */
6052 if (IS_TRUE_SYMOP (op))
6055 /* if this has register type condition and
6056 the next instruction is ifx with the same operand
6057 and live to of the operand is upto the ifx only then */
6059 ic->next->op == IFX &&
6060 IC_COND (ic->next)->key == op->key &&
6061 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6067 /*-----------------------------------------------------------------*/
6068 /* hasInc - operand is incremented before any other use */
6069 /*-----------------------------------------------------------------*/
6071 hasInc (operand *op, iCode *ic,int osize)
6073 sym_link *type = operandType(op);
6074 sym_link *retype = getSpec (type);
6075 iCode *lic = ic->next;
6078 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6079 if (!IS_SYMOP(op)) return NULL;
6081 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6082 if (IS_AGGREGATE(type->next)) return NULL;
6083 if (osize != (isize = getSize(type->next))) return NULL;
6086 /* if operand of the form op = op + <sizeof *op> */
6087 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6088 isOperandEqual(IC_RESULT(lic),op) &&
6089 isOperandLiteral(IC_RIGHT(lic)) &&
6090 operandLitValue(IC_RIGHT(lic)) == isize) {
6093 /* if the operand used or deffed */
6094 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6097 /* if GOTO or IFX */
6098 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6104 /*-----------------------------------------------------------------*/
6105 /* genAndOp - for && operation */
6106 /*-----------------------------------------------------------------*/
6108 genAndOp (iCode * ic)
6110 operand *left, *right, *result;
6113 D(emitcode ("; genAndOp",""));
6115 /* note here that && operations that are in an
6116 if statement are taken away by backPatchLabels
6117 only those used in arthmetic operations remain */
6118 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6119 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6120 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6122 /* if both are bit variables */
6123 if (AOP_TYPE (left) == AOP_CRY &&
6124 AOP_TYPE (right) == AOP_CRY)
6126 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6127 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6132 tlbl = newiTempLabel (NULL);
6134 emitcode ("jz", "%05d$", tlbl->key + 100);
6136 emitcode ("", "%05d$:", tlbl->key + 100);
6140 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6141 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6142 freeAsmop (result, NULL, ic, TRUE);
6146 /*-----------------------------------------------------------------*/
6147 /* genOrOp - for || operation */
6148 /*-----------------------------------------------------------------*/
6150 genOrOp (iCode * ic)
6152 operand *left, *right, *result;
6155 D(emitcode ("; genOrOp",""));
6157 /* note here that || operations that are in an
6158 if statement are taken away by backPatchLabels
6159 only those used in arthmetic operations remain */
6160 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6161 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6162 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6164 /* if both are bit variables */
6165 if (AOP_TYPE (left) == AOP_CRY &&
6166 AOP_TYPE (right) == AOP_CRY)
6168 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6169 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6174 tlbl = newiTempLabel (NULL);
6176 emitcode ("jnz", "%05d$", tlbl->key + 100);
6178 emitcode ("", "%05d$:", tlbl->key + 100);
6182 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6183 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6184 freeAsmop (result, NULL, ic, TRUE);
6187 /*-----------------------------------------------------------------*/
6188 /* isLiteralBit - test if lit == 2^n */
6189 /*-----------------------------------------------------------------*/
6191 isLiteralBit (unsigned long lit)
6193 unsigned long pw[32] =
6194 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6195 0x100L, 0x200L, 0x400L, 0x800L,
6196 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6197 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6198 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6199 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6200 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6203 for (idx = 0; idx < 32; idx++)
6209 /*-----------------------------------------------------------------*/
6210 /* continueIfTrue - */
6211 /*-----------------------------------------------------------------*/
6213 continueIfTrue (iCode * ic)
6216 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6220 /*-----------------------------------------------------------------*/
6222 /*-----------------------------------------------------------------*/
6224 jumpIfTrue (iCode * ic)
6227 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6231 /*-----------------------------------------------------------------*/
6232 /* jmpTrueOrFalse - */
6233 /*-----------------------------------------------------------------*/
6235 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6237 // ugly but optimized by peephole
6240 symbol *nlbl = newiTempLabel (NULL);
6241 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6242 emitcode ("", "%05d$:", tlbl->key + 100);
6243 freeForBranchAsmop (result);
6244 freeForBranchAsmop (right);
6245 freeForBranchAsmop (left);
6246 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6247 emitcode ("", "%05d$:", nlbl->key + 100);
6251 freeForBranchAsmop (result);
6252 freeForBranchAsmop (right);
6253 freeForBranchAsmop (left);
6254 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6255 emitcode ("", "%05d$:", tlbl->key + 100);
6260 /*-----------------------------------------------------------------*/
6261 /* genAnd - code for and */
6262 /*-----------------------------------------------------------------*/
6264 genAnd (iCode * ic, iCode * ifx)
6266 operand *left, *right, *result;
6267 int size, offset = 0;
6268 unsigned long lit = 0L;
6272 D(emitcode ("; genAnd",""));
6274 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6275 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6276 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6279 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6281 AOP_TYPE (left), AOP_TYPE (right));
6282 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6284 AOP_SIZE (left), AOP_SIZE (right));
6287 /* if left is a literal & right is not then exchange them */
6288 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6289 AOP_NEEDSACC (left))
6291 operand *tmp = right;
6296 /* if result = right then exchange left and right */
6297 if (sameRegs (AOP (result), AOP (right)))
6299 operand *tmp = right;
6304 /* if right is bit then exchange them */
6305 if (AOP_TYPE (right) == AOP_CRY &&
6306 AOP_TYPE (left) != AOP_CRY)
6308 operand *tmp = right;
6312 if (AOP_TYPE (right) == AOP_LIT)
6313 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6315 size = AOP_SIZE (result);
6318 // result = bit & yy;
6319 if (AOP_TYPE (left) == AOP_CRY)
6321 // c = bit & literal;
6322 if (AOP_TYPE (right) == AOP_LIT)
6326 if (size && sameRegs (AOP (result), AOP (left)))
6329 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6334 if (size && (AOP_TYPE (result) == AOP_CRY))
6336 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6339 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6344 emitcode ("clr", "c");
6349 if (AOP_TYPE (right) == AOP_CRY)
6352 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6353 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6358 MOVA (aopGet (right, 0, FALSE, FALSE));
6360 emitcode ("rrc", "a");
6361 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6369 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6370 genIfxJump (ifx, "c", left, right, result);
6374 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6375 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6376 if ((AOP_TYPE (right) == AOP_LIT) &&
6377 (AOP_TYPE (result) == AOP_CRY) &&
6378 (AOP_TYPE (left) != AOP_CRY))
6380 int posbit = isLiteralBit (lit);
6385 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6389 switch (posbit & 0x07)
6391 case 0: emitcode ("rrc", "a");
6393 case 7: emitcode ("rlc", "a");
6395 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6404 SNPRINTF (buffer, sizeof(buffer),
6405 "acc.%d", posbit & 0x07);
6406 genIfxJump (ifx, buffer, left, right, result);
6409 {// what is this case? just found it in ds390/gen.c
6410 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6417 symbol *tlbl = newiTempLabel (NULL);
6418 int sizel = AOP_SIZE (left);
6420 emitcode ("setb", "c");
6423 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6425 MOVA (aopGet (left, offset, FALSE, FALSE));
6427 if ((posbit = isLiteralBit (bytelit)) != 0)
6428 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6431 if (bytelit != 0x0FFL)
6432 emitcode ("anl", "a,%s",
6433 aopGet (right, offset, FALSE, TRUE));
6434 emitcode ("jnz", "%05d$", tlbl->key + 100);
6439 // bit = left & literal
6442 emitcode ("clr", "c");
6443 emitcode ("", "%05d$:", tlbl->key + 100);
6445 // if(left & literal)
6449 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6451 emitcode ("", "%05d$:", tlbl->key + 100);
6459 /* if left is same as result */
6460 if (sameRegs (AOP (result), AOP (left)))
6462 for (; size--; offset++)
6464 if (AOP_TYPE (right) == AOP_LIT)
6466 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6467 if (bytelit == 0x0FF)
6469 /* dummy read of volatile operand */
6470 if (isOperandVolatile (left, FALSE))
6471 MOVA (aopGet (left, offset, FALSE, FALSE));
6475 else if (bytelit == 0)
6477 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6479 else if (IS_AOP_PREG (result))
6481 MOVA (aopGet (left, offset, FALSE, TRUE));
6482 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6483 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6486 emitcode ("anl", "%s,%s",
6487 aopGet (left, offset, FALSE, TRUE),
6488 aopGet (right, offset, FALSE, FALSE));
6492 if (AOP_TYPE (left) == AOP_ACC)
6495 emitcode("mov", "a,b");
6496 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6498 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6500 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6501 MOVA (aopGet (right, offset, FALSE, FALSE));
6502 emitcode ("anl", "a,b");
6503 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6505 else if (aopGetUsesAcc (left, offset))
6507 MOVA (aopGet (left, offset, FALSE, FALSE));
6508 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6509 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6513 MOVA (aopGet (right, offset, FALSE, FALSE));
6514 if (IS_AOP_PREG (result))
6516 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6517 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6520 emitcode ("anl", "%s,a",
6521 aopGet (left, offset, FALSE, TRUE));
6528 // left & result in different registers
6529 if (AOP_TYPE (result) == AOP_CRY)
6532 // if(size), result in bit
6533 // if(!size && ifx), conditional oper: if(left & right)
6534 symbol *tlbl = newiTempLabel (NULL);
6535 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6537 emitcode ("setb", "c");
6540 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6541 && AOP_TYPE(left)==AOP_ACC)
6544 emitcode("mov", "a,b");
6545 emitcode ("anl", "a,%s",
6546 aopGet (right, offset, FALSE, FALSE));
6548 if (AOP_TYPE(left)==AOP_ACC)
6552 bool pushedB = pushB ();
6553 emitcode("mov", "b,a");
6554 MOVA (aopGet (right, offset, FALSE, FALSE));
6555 emitcode("anl", "a,b");
6560 MOVA (aopGet (right, offset, FALSE, FALSE));
6561 emitcode("anl", "a,b");
6564 MOVA (aopGet (right, offset, FALSE, FALSE));
6565 emitcode ("anl", "a,%s",
6566 aopGet (left, offset, FALSE, FALSE));
6569 emitcode ("jnz", "%05d$", tlbl->key + 100);
6575 emitcode ("", "%05d$:", tlbl->key + 100);
6579 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6581 emitcode ("", "%05d$:", tlbl->key + 100);
6585 for (; (size--); offset++)
6588 // result = left & right
6589 if (AOP_TYPE (right) == AOP_LIT)
6591 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6592 if (bytelit == 0x0FF)
6595 aopGet (left, offset, FALSE, FALSE),
6597 isOperandVolatile (result, FALSE));
6600 else if (bytelit == 0)
6602 /* dummy read of volatile operand */
6603 if (isOperandVolatile (left, FALSE))
6604 MOVA (aopGet (left, offset, FALSE, FALSE));
6605 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6608 else if (AOP_TYPE (left) == AOP_ACC)
6612 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6613 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6618 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6619 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6624 // faster than result <- left, anl result,right
6625 // and better if result is SFR
6626 if (AOP_TYPE (left) == AOP_ACC)
6629 emitcode("mov", "a,b");
6630 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6632 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6634 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6635 MOVA (aopGet (right, offset, FALSE, FALSE));
6636 emitcode ("anl", "a,b");
6638 else if (aopGetUsesAcc (left, offset))
6640 MOVA (aopGet (left, offset, FALSE, FALSE));
6641 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6645 MOVA (aopGet (right, offset, FALSE, FALSE));
6646 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6648 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6654 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6655 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6656 freeAsmop (result, NULL, ic, TRUE);
6659 /*-----------------------------------------------------------------*/
6660 /* genOr - code for or */
6661 /*-----------------------------------------------------------------*/
6663 genOr (iCode * ic, iCode * ifx)
6665 operand *left, *right, *result;
6666 int size, offset = 0;
6667 unsigned long lit = 0L;
6670 D(emitcode ("; genOr",""));
6672 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6673 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6674 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6677 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6679 AOP_TYPE (left), AOP_TYPE (right));
6680 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6682 AOP_SIZE (left), AOP_SIZE (right));
6685 /* if left is a literal & right is not then exchange them */
6686 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6687 AOP_NEEDSACC (left))
6689 operand *tmp = right;
6694 /* if result = right then exchange them */
6695 if (sameRegs (AOP (result), AOP (right)))
6697 operand *tmp = right;
6702 /* if right is bit then exchange them */
6703 if (AOP_TYPE (right) == AOP_CRY &&
6704 AOP_TYPE (left) != AOP_CRY)
6706 operand *tmp = right;
6710 if (AOP_TYPE (right) == AOP_LIT)
6711 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6713 size = AOP_SIZE (result);
6717 if (AOP_TYPE (left) == AOP_CRY)
6719 if (AOP_TYPE (right) == AOP_LIT)
6721 // c = bit | literal;
6724 // lit != 0 => result = 1
6725 if (AOP_TYPE (result) == AOP_CRY)
6728 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6730 continueIfTrue (ifx);
6733 emitcode ("setb", "c");
6737 // lit == 0 => result = left
6738 if (size && sameRegs (AOP (result), AOP (left)))
6740 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6745 if (AOP_TYPE (right) == AOP_CRY)
6748 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6749 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6754 symbol *tlbl = newiTempLabel (NULL);
6755 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6756 emitcode ("setb", "c");
6757 emitcode ("jb", "%s,%05d$",
6758 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6760 emitcode ("jnz", "%05d$", tlbl->key + 100);
6761 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6763 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6769 emitcode ("", "%05d$:", tlbl->key + 100);
6778 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6779 genIfxJump (ifx, "c", left, right, result);
6783 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6784 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6785 if ((AOP_TYPE (right) == AOP_LIT) &&
6786 (AOP_TYPE (result) == AOP_CRY) &&
6787 (AOP_TYPE (left) != AOP_CRY))
6793 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6795 continueIfTrue (ifx);
6800 // lit = 0, result = boolean(left)
6802 emitcode ("setb", "c");
6806 symbol *tlbl = newiTempLabel (NULL);
6807 emitcode ("jnz", "%05d$", tlbl->key + 100);
6809 emitcode ("", "%05d$:", tlbl->key + 100);
6813 genIfxJump (ifx, "a", left, right, result);
6821 /* if left is same as result */
6822 if (sameRegs (AOP (result), AOP (left)))
6824 for (; size--; offset++)
6826 if (AOP_TYPE (right) == AOP_LIT)
6828 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6831 /* dummy read of volatile operand */
6832 if (isOperandVolatile (left, FALSE))
6833 MOVA (aopGet (left, offset, FALSE, FALSE));
6837 else if (bytelit == 0x0FF)
6839 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6841 else if (IS_AOP_PREG (left))
6843 MOVA (aopGet (left, offset, FALSE, TRUE));
6844 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6845 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6849 emitcode ("orl", "%s,%s",
6850 aopGet (left, offset, FALSE, TRUE),
6851 aopGet (right, offset, FALSE, FALSE));
6856 if (AOP_TYPE (left) == AOP_ACC)
6859 emitcode("mov", "a,b");
6860 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6862 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6864 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6865 MOVA (aopGet (right, offset, FALSE, FALSE));
6866 emitcode ("orl", "a,b");
6867 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6869 else if (aopGetUsesAcc (left, offset))
6871 MOVA (aopGet (left, offset, FALSE, FALSE));
6872 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6873 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6877 MOVA (aopGet (right, offset, FALSE, FALSE));
6878 if (IS_AOP_PREG (left))
6880 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6881 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6885 emitcode ("orl", "%s,a",
6886 aopGet (left, offset, FALSE, TRUE));
6894 // left & result in different registers
6895 if (AOP_TYPE (result) == AOP_CRY)
6898 // if(size), result in bit
6899 // if(!size && ifx), conditional oper: if(left | right)
6900 symbol *tlbl = newiTempLabel (NULL);
6901 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6903 emitcode ("setb", "c");
6906 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6908 emitcode("mov", "a,b");
6909 emitcode ("orl", "a,%s",
6910 aopGet (right, offset, FALSE, FALSE));
6912 MOVA (aopGet (right, offset, FALSE, FALSE));
6913 emitcode ("orl", "a,%s",
6914 aopGet (left, offset, FALSE, FALSE));
6916 emitcode ("jnz", "%05d$", tlbl->key + 100);
6922 emitcode ("", "%05d$:", tlbl->key + 100);
6926 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6928 emitcode ("", "%05d$:", tlbl->key + 100);
6932 for (; (size--); offset++)
6935 // result = left | right
6936 if (AOP_TYPE (right) == AOP_LIT)
6938 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6942 aopGet (left, offset, FALSE, FALSE),
6944 isOperandVolatile (result, FALSE));
6947 else if (bytelit == 0x0FF)
6949 /* dummy read of volatile operand */
6950 if (isOperandVolatile (left, FALSE))
6951 MOVA (aopGet (left, offset, FALSE, FALSE));
6952 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6956 // faster than result <- left, anl result,right
6957 // and better if result is SFR
6958 if (AOP_TYPE (left) == AOP_ACC)
6961 emitcode("mov", "a,b");
6962 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6964 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6966 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6967 MOVA (aopGet (right, offset, FALSE, FALSE));
6968 emitcode ("orl", "a,b");
6970 else if (aopGetUsesAcc (left, offset))
6972 MOVA (aopGet (left, offset, FALSE, FALSE));
6973 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6977 MOVA (aopGet (right, offset, FALSE, FALSE));
6978 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6980 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6986 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6987 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6988 freeAsmop (result, NULL, ic, TRUE);
6991 /*-----------------------------------------------------------------*/
6992 /* genXor - code for xclusive or */
6993 /*-----------------------------------------------------------------*/
6995 genXor (iCode * ic, iCode * ifx)
6997 operand *left, *right, *result;
6998 int size, offset = 0;
6999 unsigned long lit = 0L;
7002 D(emitcode ("; genXor",""));
7004 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
7005 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
7006 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
7009 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
7011 AOP_TYPE (left), AOP_TYPE (right));
7012 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
7014 AOP_SIZE (left), AOP_SIZE (right));
7017 /* if left is a literal & right is not ||
7018 if left needs acc & right does not */
7019 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
7020 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
7022 operand *tmp = right;
7027 /* if result = right then exchange them */
7028 if (sameRegs (AOP (result), AOP (right)))
7030 operand *tmp = right;
7035 /* if right is bit then exchange them */
7036 if (AOP_TYPE (right) == AOP_CRY &&
7037 AOP_TYPE (left) != AOP_CRY)
7039 operand *tmp = right;
7043 if (AOP_TYPE (right) == AOP_LIT)
7044 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7046 size = AOP_SIZE (result);
7050 if (AOP_TYPE (left) == AOP_CRY)
7052 if (AOP_TYPE (right) == AOP_LIT)
7054 // c = bit & literal;
7057 // lit>>1 != 0 => result = 1
7058 if (AOP_TYPE (result) == AOP_CRY)
7061 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7063 continueIfTrue (ifx);
7066 emitcode ("setb", "c");
7073 // lit == 0, result = left
7074 if (size && sameRegs (AOP (result), AOP (left)))
7076 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7080 // lit == 1, result = not(left)
7081 if (size && sameRegs (AOP (result), AOP (left)))
7083 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7088 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7089 emitcode ("cpl", "c");
7098 symbol *tlbl = newiTempLabel (NULL);
7099 if (AOP_TYPE (right) == AOP_CRY)
7102 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7106 int sizer = AOP_SIZE (right);
7108 // if val>>1 != 0, result = 1
7109 emitcode ("setb", "c");
7112 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7114 // test the msb of the lsb
7115 emitcode ("anl", "a,#0xfe");
7116 emitcode ("jnz", "%05d$", tlbl->key + 100);
7120 emitcode ("rrc", "a");
7122 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7123 emitcode ("cpl", "c");
7124 emitcode ("", "%05d$:", (tlbl->key + 100));
7131 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7132 genIfxJump (ifx, "c", left, right, result);
7136 /* if left is same as result */
7137 if (sameRegs (AOP (result), AOP (left)))
7139 for (; size--; offset++)
7141 if (AOP_TYPE (right) == AOP_LIT)
7143 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7146 /* dummy read of volatile operand */
7147 if (isOperandVolatile (left, FALSE))
7148 MOVA (aopGet (left, offset, FALSE, FALSE));
7152 else if (IS_AOP_PREG (left))
7154 MOVA (aopGet (left, offset, FALSE, TRUE));
7155 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7156 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7160 emitcode ("xrl", "%s,%s",
7161 aopGet (left, offset, FALSE, TRUE),
7162 aopGet (right, offset, FALSE, FALSE));
7167 if (AOP_TYPE (left) == AOP_ACC)
7170 emitcode("mov", "a,b");
7171 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7173 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7175 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7176 MOVA (aopGet (right, offset, FALSE, FALSE));
7177 emitcode ("xrl", "a,b");
7178 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7180 else if (aopGetUsesAcc (left, offset))
7182 MOVA (aopGet (left, offset, FALSE, FALSE));
7183 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7184 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7188 MOVA (aopGet (right, offset, FALSE, FALSE));
7189 if (IS_AOP_PREG (left))
7191 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7192 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7195 emitcode ("xrl", "%s,a",
7196 aopGet (left, offset, FALSE, TRUE));
7203 // left & result in different registers
7204 if (AOP_TYPE (result) == AOP_CRY)
7207 // if(size), result in bit
7208 // if(!size && ifx), conditional oper: if(left ^ right)
7209 symbol *tlbl = newiTempLabel (NULL);
7210 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7212 emitcode ("setb", "c");
7215 if ((AOP_TYPE (right) == AOP_LIT) &&
7216 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7218 MOVA (aopGet (left, offset, FALSE, FALSE));
7222 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7224 emitcode("mov", "a,b");
7225 emitcode ("xrl", "a,%s",
7226 aopGet (right, offset, FALSE, FALSE));
7228 MOVA (aopGet (right, offset, FALSE, FALSE));
7229 emitcode ("xrl", "a,%s",
7230 aopGet (left, offset, FALSE, FALSE));
7233 emitcode ("jnz", "%05d$", tlbl->key + 100);
7239 emitcode ("", "%05d$:", tlbl->key + 100);
7243 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7247 for (; (size--); offset++)
7250 // result = left & right
7251 if (AOP_TYPE (right) == AOP_LIT)
7253 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7257 aopGet (left, offset, FALSE, FALSE),
7259 isOperandVolatile (result, FALSE));
7263 // faster than result <- left, anl result,right
7264 // and better if result is SFR
7265 if (AOP_TYPE (left) == AOP_ACC)
7268 emitcode("mov", "a,b");
7269 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7271 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7273 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7274 MOVA (aopGet (right, offset, FALSE, FALSE));
7275 emitcode ("xrl", "a,b");
7277 else if (aopGetUsesAcc (left, offset))
7279 MOVA (aopGet (left, offset, FALSE, FALSE));
7280 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7284 MOVA (aopGet (right, offset, FALSE, FALSE));
7285 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7287 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7293 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7294 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7295 freeAsmop (result, NULL, ic, TRUE);
7298 /*-----------------------------------------------------------------*/
7299 /* genInline - write the inline code out */
7300 /*-----------------------------------------------------------------*/
7302 genInline (iCode * ic)
7304 char *buffer, *bp, *bp1;
7306 D(emitcode ("; genInline",""));
7308 _G.inLine += (!options.asmpeep);
7310 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7311 strcpy (buffer, IC_INLINE (ic));
7313 /* emit each line as a code */
7324 /* Add \n for labels, not dirs such as c:\mydir */
7325 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7339 /* emitcode("",buffer); */
7340 _G.inLine -= (!options.asmpeep);
7343 /*-----------------------------------------------------------------*/
7344 /* genRRC - rotate right with carry */
7345 /*-----------------------------------------------------------------*/
7349 operand *left, *result;
7350 int size, offset = 0;
7353 D(emitcode ("; genRRC",""));
7355 /* rotate right with carry */
7356 left = IC_LEFT (ic);
7357 result = IC_RESULT (ic);
7358 aopOp (left, ic, FALSE);
7359 aopOp (result, ic, FALSE);
7361 /* move it to the result */
7362 size = AOP_SIZE (result);
7364 if (size == 1) { /* special case for 1 byte */
7365 l = aopGet (left, offset, FALSE, FALSE);
7367 emitcode ("rr", "a");
7370 /* no need to clear carry, bit7 will be written later */
7373 l = aopGet (left, offset, FALSE, FALSE);
7375 emitcode ("rrc", "a");
7376 if (AOP_SIZE (result) > 1)
7377 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7379 /* now we need to put the carry into the
7380 highest order byte of the result */
7381 if (AOP_SIZE (result) > 1)
7383 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7386 emitcode ("mov", "acc.7,c");
7388 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7389 freeAsmop (left, NULL, ic, TRUE);
7390 freeAsmop (result, NULL, ic, TRUE);
7393 /*-----------------------------------------------------------------*/
7394 /* genRLC - generate code for rotate left with carry */
7395 /*-----------------------------------------------------------------*/
7399 operand *left, *result;
7400 int size, offset = 0;
7403 D(emitcode ("; genRLC",""));
7405 /* rotate right with carry */
7406 left = IC_LEFT (ic);
7407 result = IC_RESULT (ic);
7408 aopOp (left, ic, FALSE);
7409 aopOp (result, ic, FALSE);
7411 /* move it to the result */
7412 size = AOP_SIZE (result);
7416 l = aopGet (left, offset, FALSE, FALSE);
7418 if (size == 0) { /* special case for 1 byte */
7422 emitcode("rlc","a"); /* bit0 will be written later */
7423 if (AOP_SIZE (result) > 1)
7424 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7427 l = aopGet (left, offset, FALSE, FALSE);
7429 emitcode ("rlc", "a");
7430 if (AOP_SIZE (result) > 1)
7431 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7434 /* now we need to put the carry into the
7435 highest order byte of the result */
7436 if (AOP_SIZE (result) > 1)
7438 l = aopGet (result, 0, FALSE, FALSE);
7441 emitcode ("mov", "acc.0,c");
7443 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7444 freeAsmop (left, NULL, ic, TRUE);
7445 freeAsmop (result, NULL, ic, TRUE);
7448 /*-----------------------------------------------------------------*/
7449 /* genGetHbit - generates code get highest order bit */
7450 /*-----------------------------------------------------------------*/
7452 genGetHbit (iCode * ic)
7454 operand *left, *result;
7456 D(emitcode ("; genGetHbit",""));
7458 left = IC_LEFT (ic);
7459 result = IC_RESULT (ic);
7460 aopOp (left, ic, FALSE);
7461 aopOp (result, ic, FALSE);
7463 /* get the highest order byte into a */
7464 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7465 if (AOP_TYPE (result) == AOP_CRY)
7467 emitcode ("rlc", "a");
7472 emitcode ("rl", "a");
7473 emitcode ("anl", "a,#0x01");
7478 freeAsmop (left, NULL, ic, TRUE);
7479 freeAsmop (result, NULL, ic, TRUE);
7482 /*-----------------------------------------------------------------*/
7483 /* genGetAbit - generates code get a single bit */
7484 /*-----------------------------------------------------------------*/
7486 genGetAbit (iCode * ic)
7488 operand *left, *right, *result;
7491 D(emitcode ("; genGetAbit",""));
7493 left = IC_LEFT (ic);
7494 right = IC_RIGHT (ic);
7495 result = IC_RESULT (ic);
7496 aopOp (left, ic, FALSE);
7497 aopOp (right, ic, FALSE);
7498 aopOp (result, ic, FALSE);
7500 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7502 /* get the needed byte into a */
7503 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7505 if (AOP_TYPE (result) == AOP_CRY)
7508 emitcode ("rlc", "a");
7509 else if ((shCount) == 0)
7510 emitcode ("rrc", "a");
7512 emitcode ("mov", "c,acc[%d]", shCount);
7520 emitcode ("rr", "a");
7523 emitcode ("rr", "a");
7526 emitcode ("anl", "a,#0x01");
7530 emitcode ("mov", "c,acc[%d]", shCount);
7531 emitcode ("clr", "a");
7532 emitcode ("rlc", "a");
7535 emitcode ("swap", "a");
7536 emitcode ("anl", "a,#0x01");
7539 emitcode ("rl", "a");
7542 emitcode ("rl", "a");
7543 emitcode ("anl", "a,#0x01");
7549 freeAsmop (left, NULL, ic, TRUE);
7550 freeAsmop (right, NULL, ic, TRUE);
7551 freeAsmop (result, NULL, ic, TRUE);
7554 /*-----------------------------------------------------------------*/
7555 /* genGetByte - generates code get a single byte */
7556 /*-----------------------------------------------------------------*/
7558 genGetByte (iCode * ic)
7560 operand *left, *right, *result;
7563 D(emitcode ("; genGetByte",""));
7565 left = IC_LEFT (ic);
7566 right = IC_RIGHT (ic);
7567 result = IC_RESULT (ic);
7568 aopOp (left, ic, FALSE);
7569 aopOp (right, ic, FALSE);
7570 aopOp (result, ic, FALSE);
7572 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7574 aopGet (left, offset, FALSE, FALSE),
7576 isOperandVolatile (result, FALSE));
7578 freeAsmop (left, NULL, ic, TRUE);
7579 freeAsmop (right, NULL, ic, TRUE);
7580 freeAsmop (result, NULL, ic, TRUE);
7583 /*-----------------------------------------------------------------*/
7584 /* genGetWord - generates code get two bytes */
7585 /*-----------------------------------------------------------------*/
7587 genGetWord (iCode * ic)
7589 operand *left, *right, *result;
7592 D(emitcode ("; genGetWord",""));
7594 left = IC_LEFT (ic);
7595 right = IC_RIGHT (ic);
7596 result = IC_RESULT (ic);
7597 aopOp (left, ic, FALSE);
7598 aopOp (right, ic, FALSE);
7599 aopOp (result, ic, FALSE);
7601 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7603 aopGet (left, offset, FALSE, FALSE),
7605 isOperandVolatile (result, FALSE));
7607 aopGet (left, offset+1, FALSE, FALSE),
7609 isOperandVolatile (result, FALSE));
7611 freeAsmop (left, NULL, ic, TRUE);
7612 freeAsmop (right, NULL, ic, TRUE);
7613 freeAsmop (result, NULL, ic, TRUE);
7616 /*-----------------------------------------------------------------*/
7617 /* genSwap - generates code to swap nibbles or bytes */
7618 /*-----------------------------------------------------------------*/
7620 genSwap (iCode * ic)
7622 operand *left, *result;
7624 D(emitcode ("; genSwap",""));
7626 left = IC_LEFT (ic);
7627 result = IC_RESULT (ic);
7628 aopOp (left, ic, FALSE);
7629 aopOp (result, ic, FALSE);
7631 switch (AOP_SIZE (left))
7633 case 1: /* swap nibbles in byte */
7634 MOVA (aopGet (left, 0, FALSE, FALSE));
7635 emitcode ("swap", "a");
7636 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7638 case 2: /* swap bytes in word */
7639 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7641 MOVA (aopGet (left, 0, FALSE, FALSE));
7642 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7643 0, isOperandVolatile (result, FALSE));
7644 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7646 else if (operandsEqu (left, result))
7649 bool pushedB = FALSE, leftInB = FALSE;
7651 MOVA (aopGet (left, 0, FALSE, FALSE));
7652 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7655 emitcode ("mov", "b,a");
7659 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7660 0, isOperandVolatile (result, FALSE));
7661 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7668 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7669 0, isOperandVolatile (result, FALSE));
7670 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7671 1, isOperandVolatile (result, FALSE));
7675 wassertl(FALSE, "unsupported SWAP operand size");
7678 freeAsmop (left, NULL, ic, TRUE);
7679 freeAsmop (result, NULL, ic, TRUE);
7683 /*-----------------------------------------------------------------*/
7684 /* AccRol - rotate left accumulator by known count */
7685 /*-----------------------------------------------------------------*/
7687 AccRol (int shCount)
7689 shCount &= 0x0007; // shCount : 0..7
7696 emitcode ("rl", "a");
7699 emitcode ("rl", "a");
7700 emitcode ("rl", "a");
7703 emitcode ("swap", "a");
7704 emitcode ("rr", "a");
7707 emitcode ("swap", "a");
7710 emitcode ("swap", "a");
7711 emitcode ("rl", "a");
7714 emitcode ("rr", "a");
7715 emitcode ("rr", "a");
7718 emitcode ("rr", "a");
7723 /*-----------------------------------------------------------------*/
7724 /* AccLsh - left shift accumulator by known count */
7725 /*-----------------------------------------------------------------*/
7727 AccLsh (int shCount)
7732 emitcode ("add", "a,acc");
7733 else if (shCount == 2)
7735 emitcode ("add", "a,acc");
7736 emitcode ("add", "a,acc");
7740 /* rotate left accumulator */
7742 /* and kill the lower order bits */
7743 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7748 /*-----------------------------------------------------------------*/
7749 /* AccRsh - right shift accumulator by known count */
7750 /*-----------------------------------------------------------------*/
7752 AccRsh (int shCount)
7759 emitcode ("rrc", "a");
7763 /* rotate right accumulator */
7764 AccRol (8 - shCount);
7765 /* and kill the higher order bits */
7766 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7771 /*-----------------------------------------------------------------*/
7772 /* AccSRsh - signed right shift accumulator by known count */
7773 /*-----------------------------------------------------------------*/
7775 AccSRsh (int shCount)
7782 emitcode ("mov", "c,acc.7");
7783 emitcode ("rrc", "a");
7785 else if (shCount == 2)
7787 emitcode ("mov", "c,acc.7");
7788 emitcode ("rrc", "a");
7789 emitcode ("mov", "c,acc.7");
7790 emitcode ("rrc", "a");
7794 tlbl = newiTempLabel (NULL);
7795 /* rotate right accumulator */
7796 AccRol (8 - shCount);
7797 /* and kill the higher order bits */
7798 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7799 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7800 emitcode ("orl", "a,#0x%02x",
7801 (unsigned char) ~SRMask[shCount]);
7802 emitcode ("", "%05d$:", tlbl->key + 100);
7807 /*-----------------------------------------------------------------*/
7808 /* shiftR1Left2Result - shift right one byte from left to result */
7809 /*-----------------------------------------------------------------*/
7811 shiftR1Left2Result (operand * left, int offl,
7812 operand * result, int offr,
7813 int shCount, int sign)
7815 MOVA (aopGet (left, offl, FALSE, FALSE));
7816 /* shift right accumulator */
7821 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7824 /*-----------------------------------------------------------------*/
7825 /* shiftL1Left2Result - shift left one byte from left to result */
7826 /*-----------------------------------------------------------------*/
7828 shiftL1Left2Result (operand * left, int offl,
7829 operand * result, int offr, int shCount)
7832 l = aopGet (left, offl, FALSE, FALSE);
7834 /* shift left accumulator */
7836 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7839 /*-----------------------------------------------------------------*/
7840 /* movLeft2Result - move byte from left to result */
7841 /*-----------------------------------------------------------------*/
7843 movLeft2Result (operand * left, int offl,
7844 operand * result, int offr, int sign)
7847 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7849 l = aopGet (left, offl, FALSE, FALSE);
7851 if (*l == '@' && (IS_AOP_PREG (result)))
7853 emitcode ("mov", "a,%s", l);
7854 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7859 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7862 /* MSB sign in acc.7 ! */
7863 if (getDataSize (left) == offl + 1)
7866 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7873 /*-----------------------------------------------------------------*/
7874 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7875 /*-----------------------------------------------------------------*/
7879 emitcode ("rrc", "a");
7880 emitcode ("xch", "a,%s", x);
7881 emitcode ("rrc", "a");
7882 emitcode ("xch", "a,%s", x);
7885 /*-----------------------------------------------------------------*/
7886 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7887 /*-----------------------------------------------------------------*/
7891 emitcode ("xch", "a,%s", x);
7892 emitcode ("rlc", "a");
7893 emitcode ("xch", "a,%s", x);
7894 emitcode ("rlc", "a");
7897 /*-----------------------------------------------------------------*/
7898 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7899 /*-----------------------------------------------------------------*/
7903 emitcode ("xch", "a,%s", x);
7904 emitcode ("add", "a,acc");
7905 emitcode ("xch", "a,%s", x);
7906 emitcode ("rlc", "a");
7909 /*-----------------------------------------------------------------*/
7910 /* AccAXLsh - left shift a:x by known count (0..7) */
7911 /*-----------------------------------------------------------------*/
7913 AccAXLsh (char *x, int shCount)
7928 case 5: // AAAAABBB:CCCCCDDD
7930 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7932 emitcode ("anl", "a,#0x%02x",
7933 SLMask[shCount]); // BBB00000:CCCCCDDD
7935 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7937 AccRol (shCount); // DDDCCCCC:BBB00000
7939 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7941 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7943 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7945 emitcode ("anl", "a,#0x%02x",
7946 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7948 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7950 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7953 case 6: // AAAAAABB:CCCCCCDD
7954 emitcode ("anl", "a,#0x%02x",
7955 SRMask[shCount]); // 000000BB:CCCCCCDD
7956 emitcode ("mov", "c,acc.0"); // c = B
7957 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7959 AccAXRrl1 (x); // BCCCCCCD:D000000B
7960 AccAXRrl1 (x); // BBCCCCCC:DD000000
7962 emitcode("rrc","a");
7963 emitcode("xch","a,%s", x);
7964 emitcode("rrc","a");
7965 emitcode("mov","c,acc.0"); //<< get correct bit
7966 emitcode("xch","a,%s", x);
7968 emitcode("rrc","a");
7969 emitcode("xch","a,%s", x);
7970 emitcode("rrc","a");
7971 emitcode("xch","a,%s", x);
7974 case 7: // a:x <<= 7
7976 emitcode ("anl", "a,#0x%02x",
7977 SRMask[shCount]); // 0000000B:CCCCCCCD
7979 emitcode ("mov", "c,acc.0"); // c = B
7981 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7983 AccAXRrl1 (x); // BCCCCCCC:D0000000
7991 /*-----------------------------------------------------------------*/
7992 /* AccAXRsh - right shift a:x known count (0..7) */
7993 /*-----------------------------------------------------------------*/
7995 AccAXRsh (char *x, int shCount)
8003 AccAXRrl1 (x); // 0->a:x
8008 AccAXRrl1 (x); // 0->a:x
8011 AccAXRrl1 (x); // 0->a:x
8016 case 5: // AAAAABBB:CCCCCDDD = a:x
8018 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8020 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8022 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8024 emitcode ("anl", "a,#0x%02x",
8025 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8027 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8029 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8031 emitcode ("anl", "a,#0x%02x",
8032 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8034 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8036 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8038 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8041 case 6: // AABBBBBB:CCDDDDDD
8043 emitcode ("mov", "c,acc.7");
8044 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8046 emitcode ("mov", "c,acc.7");
8047 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8049 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8051 emitcode ("anl", "a,#0x%02x",
8052 SRMask[shCount]); // 000000AA:BBBBBBCC
8055 case 7: // ABBBBBBB:CDDDDDDD
8057 emitcode ("mov", "c,acc.7"); // c = A
8059 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8061 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8063 emitcode ("anl", "a,#0x%02x",
8064 SRMask[shCount]); // 0000000A:BBBBBBBC
8072 /*-----------------------------------------------------------------*/
8073 /* AccAXRshS - right shift signed a:x known count (0..7) */
8074 /*-----------------------------------------------------------------*/
8076 AccAXRshS (char *x, int shCount)
8084 emitcode ("mov", "c,acc.7");
8085 AccAXRrl1 (x); // s->a:x
8089 emitcode ("mov", "c,acc.7");
8090 AccAXRrl1 (x); // s->a:x
8092 emitcode ("mov", "c,acc.7");
8093 AccAXRrl1 (x); // s->a:x
8098 case 5: // AAAAABBB:CCCCCDDD = a:x
8100 tlbl = newiTempLabel (NULL);
8101 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8103 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8105 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8107 emitcode ("anl", "a,#0x%02x",
8108 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8110 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8112 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8114 emitcode ("anl", "a,#0x%02x",
8115 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8117 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8119 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8121 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8123 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8124 emitcode ("orl", "a,#0x%02x",
8125 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8127 emitcode ("", "%05d$:", tlbl->key + 100);
8128 break; // SSSSAAAA:BBBCCCCC
8130 case 6: // AABBBBBB:CCDDDDDD
8132 tlbl = newiTempLabel (NULL);
8133 emitcode ("mov", "c,acc.7");
8134 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8136 emitcode ("mov", "c,acc.7");
8137 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8139 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8141 emitcode ("anl", "a,#0x%02x",
8142 SRMask[shCount]); // 000000AA:BBBBBBCC
8144 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8145 emitcode ("orl", "a,#0x%02x",
8146 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8148 emitcode ("", "%05d$:", tlbl->key + 100);
8150 case 7: // ABBBBBBB:CDDDDDDD
8152 tlbl = newiTempLabel (NULL);
8153 emitcode ("mov", "c,acc.7"); // c = A
8155 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8157 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8159 emitcode ("anl", "a,#0x%02x",
8160 SRMask[shCount]); // 0000000A:BBBBBBBC
8162 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8163 emitcode ("orl", "a,#0x%02x",
8164 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8166 emitcode ("", "%05d$:", tlbl->key + 100);
8173 /*-----------------------------------------------------------------*/
8174 /* shiftL2Left2Result - shift left two bytes from left to result */
8175 /*-----------------------------------------------------------------*/
8177 shiftL2Left2Result (operand * left, int offl,
8178 operand * result, int offr, int shCount)
8181 bool pushedB = FALSE;
8184 if (sameRegs (AOP (result), AOP (left)) &&
8185 ((offl + MSB16) == offr))
8187 /* don't crash result[offr] */
8188 MOVA (aopGet (left, offl, FALSE, FALSE));
8189 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8190 x = aopGet (result, offr, FALSE, FALSE);
8192 else if (aopGetUsesAcc (result, offr))
8194 movLeft2Result (left, offl, result, offr, 0);
8197 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8198 MOVA (aopGet (result, offr, FALSE, FALSE));
8199 emitcode ("xch", "a,b");
8204 movLeft2Result (left, offl, result, offr, 0);
8205 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8206 x = aopGet (result, offr, FALSE, FALSE);
8208 /* ax << shCount (x = lsb(result)) */
8209 AccAXLsh (x, shCount);
8212 emitcode ("xch", "a,b");
8213 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8214 aopPut (result, "b", offr + MSB16, isOperandVolatile (result, FALSE));
8219 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8224 /*-----------------------------------------------------------------*/
8225 /* shiftR2Left2Result - shift right two bytes from left to result */
8226 /*-----------------------------------------------------------------*/
8228 shiftR2Left2Result (operand * left, int offl,
8229 operand * result, int offr,
8230 int shCount, int sign)
8233 bool pushedB = FALSE;
8236 if (sameRegs (AOP (result), AOP (left)) &&
8237 ((offl + MSB16) == offr))
8239 /* don't crash result[offr] */
8240 MOVA (aopGet (left, offl, FALSE, FALSE));
8241 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8242 x = aopGet (result, offr, FALSE, FALSE);
8244 else if (aopGetUsesAcc (result, offr))
8246 movLeft2Result (left, offl, result, offr, 0);
8249 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8250 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8255 movLeft2Result (left, offl, result, offr, 0);
8256 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8257 x = aopGet (result, offr, FALSE, FALSE);
8259 /* a:x >> shCount (x = lsb(result)) */
8261 AccAXRshS (x, shCount);
8263 AccAXRsh (x, shCount);
8266 emitcode ("xch", "a,b");
8267 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8268 emitcode ("xch", "a,b");
8271 if (getDataSize (result) > 1)
8272 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8275 /*-----------------------------------------------------------------*/
8276 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8277 /*-----------------------------------------------------------------*/
8279 shiftLLeftOrResult (operand * left, int offl,
8280 operand * result, int offr, int shCount)
8282 MOVA (aopGet (left, offl, FALSE, FALSE));
8283 /* shift left accumulator */
8285 /* or with result */
8286 if (aopGetUsesAcc (result, offr))
8288 emitcode ("xch", "a,b");
8289 MOVA (aopGet (result, offr, FALSE, FALSE));
8290 emitcode ("orl", "a,b");
8294 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8296 /* back to result */
8297 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8300 /*-----------------------------------------------------------------*/
8301 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8302 /*-----------------------------------------------------------------*/
8304 shiftRLeftOrResult (operand * left, int offl,
8305 operand * result, int offr, int shCount)
8307 MOVA (aopGet (left, offl, FALSE, FALSE));
8308 /* shift right accumulator */
8310 /* or with result */
8311 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8312 /* back to result */
8313 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8316 /*-----------------------------------------------------------------*/
8317 /* genlshOne - left shift a one byte quantity by known count */
8318 /*-----------------------------------------------------------------*/
8320 genlshOne (operand * result, operand * left, int shCount)
8322 D(emitcode ("; genlshOne",""));
8324 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8327 /*-----------------------------------------------------------------*/
8328 /* genlshTwo - left shift two bytes by known amount != 0 */
8329 /*-----------------------------------------------------------------*/
8331 genlshTwo (operand * result, operand * left, int shCount)
8335 D(emitcode ("; genlshTwo",""));
8337 size = getDataSize (result);
8339 /* if shCount >= 8 */
8347 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8349 movLeft2Result (left, LSB, result, MSB16, 0);
8351 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8354 /* 1 <= shCount <= 7 */
8358 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8360 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8364 /*-----------------------------------------------------------------*/
8365 /* shiftLLong - shift left one long from left to result */
8366 /* offl = LSB or MSB16 */
8367 /*-----------------------------------------------------------------*/
8369 shiftLLong (operand * left, operand * result, int offr)
8372 int size = AOP_SIZE (result);
8374 if (size >= LSB + offr)
8376 l = aopGet (left, LSB, FALSE, FALSE);
8378 emitcode ("add", "a,acc");
8379 if (sameRegs (AOP (left), AOP (result)) &&
8380 size >= MSB16 + offr && offr != LSB)
8381 emitcode ("xch", "a,%s",
8382 aopGet (left, LSB + offr, FALSE, FALSE));
8384 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8387 if (size >= MSB16 + offr)
8389 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8391 l = aopGet (left, MSB16, FALSE, FALSE);
8394 emitcode ("rlc", "a");
8395 if (sameRegs (AOP (left), AOP (result)) &&
8396 size >= MSB24 + offr && offr != LSB)
8397 emitcode ("xch", "a,%s",
8398 aopGet (left, MSB16 + offr, FALSE, FALSE));
8400 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8403 if (size >= MSB24 + offr)
8405 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8407 l = aopGet (left, MSB24, FALSE, FALSE);
8410 emitcode ("rlc", "a");
8411 if (sameRegs (AOP (left), AOP (result)) &&
8412 size >= MSB32 + offr && offr != LSB)
8413 emitcode ("xch", "a,%s",
8414 aopGet (left, MSB24 + offr, FALSE, FALSE));
8416 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8419 if (size > MSB32 + offr)
8421 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8423 l = aopGet (left, MSB32, FALSE, FALSE);
8426 emitcode ("rlc", "a");
8427 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8430 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8433 /*-----------------------------------------------------------------*/
8434 /* genlshFour - shift four byte by a known amount != 0 */
8435 /*-----------------------------------------------------------------*/
8437 genlshFour (operand * result, operand * left, int shCount)
8441 D(emitcode ("; genlshFour",""));
8443 size = AOP_SIZE (result);
8445 /* if shifting more that 3 bytes */
8450 /* lowest order of left goes to the highest
8451 order of the destination */
8452 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8454 movLeft2Result (left, LSB, result, MSB32, 0);
8455 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8456 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8457 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8461 /* more than two bytes */
8462 else if (shCount >= 16)
8464 /* lower order two bytes goes to higher order two bytes */
8466 /* if some more remaining */
8468 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8471 movLeft2Result (left, MSB16, result, MSB32, 0);
8472 movLeft2Result (left, LSB, result, MSB24, 0);
8474 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8475 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8479 /* if more than 1 byte */
8480 else if (shCount >= 8)
8482 /* lower order three bytes goes to higher order three bytes */
8487 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8489 movLeft2Result (left, LSB, result, MSB16, 0);
8495 movLeft2Result (left, MSB24, result, MSB32, 0);
8496 movLeft2Result (left, MSB16, result, MSB24, 0);
8497 movLeft2Result (left, LSB, result, MSB16, 0);
8498 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8500 else if (shCount == 1)
8501 shiftLLong (left, result, MSB16);
8504 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8505 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8506 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8507 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8512 /* 1 <= shCount <= 7 */
8513 else if (shCount <= 2)
8515 shiftLLong (left, result, LSB);
8517 shiftLLong (result, result, LSB);
8519 /* 3 <= shCount <= 7, optimize */
8522 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8523 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8524 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8528 /*-----------------------------------------------------------------*/
8529 /* genLeftShiftLiteral - left shifting by known count */
8530 /*-----------------------------------------------------------------*/
8532 genLeftShiftLiteral (operand * left,
8537 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8540 D(emitcode ("; genLeftShiftLiteral",""));
8542 freeAsmop (right, NULL, ic, TRUE);
8544 aopOp (left, ic, FALSE);
8545 aopOp (result, ic, FALSE);
8547 size = getSize (operandType (result));
8550 emitcode ("; shift left ", "result %d, left %d", size,
8554 /* I suppose that the left size >= result size */
8559 movLeft2Result (left, size, result, size, 0);
8563 else if (shCount >= (size * 8))
8565 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8571 genlshOne (result, left, shCount);
8575 genlshTwo (result, left, shCount);
8579 genlshFour (result, left, shCount);
8582 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8583 "*** ack! mystery literal shift!\n");
8587 freeAsmop (left, NULL, ic, TRUE);
8588 freeAsmop (result, NULL, ic, TRUE);
8591 /*-----------------------------------------------------------------*/
8592 /* genLeftShift - generates code for left shifting */
8593 /*-----------------------------------------------------------------*/
8595 genLeftShift (iCode * ic)
8597 operand *left, *right, *result;
8600 symbol *tlbl, *tlbl1;
8603 D(emitcode ("; genLeftShift",""));
8605 right = IC_RIGHT (ic);
8606 left = IC_LEFT (ic);
8607 result = IC_RESULT (ic);
8609 aopOp (right, ic, FALSE);
8611 /* if the shift count is known then do it
8612 as efficiently as possible */
8613 if (AOP_TYPE (right) == AOP_LIT)
8615 genLeftShiftLiteral (left, right, result, ic);
8619 /* shift count is unknown then we have to form
8620 a loop get the loop count in B : Note: we take
8621 only the lower order byte since shifting
8622 more that 32 bits make no sense anyway, ( the
8623 largest size of an object can be only 32 bits ) */
8626 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8627 emitcode ("inc", "b");
8628 freeAsmop (right, NULL, ic, TRUE);
8629 aopOp (left, ic, FALSE);
8630 aopOp (result, ic, FALSE);
8632 /* now move the left to the result if they are not the same */
8633 if (!sameRegs (AOP (left), AOP (result)) &&
8634 AOP_SIZE (result) > 1)
8637 size = AOP_SIZE (result);
8641 l = aopGet (left, offset, FALSE, TRUE);
8642 if (*l == '@' && (IS_AOP_PREG (result)))
8645 emitcode ("mov", "a,%s", l);
8646 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8649 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8654 tlbl = newiTempLabel (NULL);
8655 size = AOP_SIZE (result);
8657 tlbl1 = newiTempLabel (NULL);
8659 /* if it is only one byte then */
8662 symbol *tlbl1 = newiTempLabel (NULL);
8664 l = aopGet (left, 0, FALSE, FALSE);
8666 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8667 emitcode ("", "%05d$:", tlbl->key + 100);
8668 emitcode ("add", "a,acc");
8669 emitcode ("", "%05d$:", tlbl1->key + 100);
8670 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8672 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8676 reAdjustPreg (AOP (result));
8678 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8679 emitcode ("", "%05d$:", tlbl->key + 100);
8680 l = aopGet (result, offset, FALSE, FALSE);
8682 emitcode ("add", "a,acc");
8683 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8686 l = aopGet (result, offset, FALSE, FALSE);
8688 emitcode ("rlc", "a");
8689 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8691 reAdjustPreg (AOP (result));
8693 emitcode ("", "%05d$:", tlbl1->key + 100);
8694 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8697 freeAsmop (left, NULL, ic, TRUE);
8698 freeAsmop (result, NULL, ic, TRUE);
8701 /*-----------------------------------------------------------------*/
8702 /* genrshOne - right shift a one byte quantity by known count */
8703 /*-----------------------------------------------------------------*/
8705 genrshOne (operand * result, operand * left,
8706 int shCount, int sign)
8708 D(emitcode ("; genrshOne",""));
8710 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8713 /*-----------------------------------------------------------------*/
8714 /* genrshTwo - right shift two bytes by known amount != 0 */
8715 /*-----------------------------------------------------------------*/
8717 genrshTwo (operand * result, operand * left,
8718 int shCount, int sign)
8720 D(emitcode ("; genrshTwo",""));
8722 /* if shCount >= 8 */
8727 shiftR1Left2Result (left, MSB16, result, LSB,
8730 movLeft2Result (left, MSB16, result, LSB, sign);
8731 addSign (result, MSB16, sign);
8734 /* 1 <= shCount <= 7 */
8736 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8739 /*-----------------------------------------------------------------*/
8740 /* shiftRLong - shift right one long from left to result */
8741 /* offl = LSB or MSB16 */
8742 /*-----------------------------------------------------------------*/
8744 shiftRLong (operand * left, int offl,
8745 operand * result, int sign)
8747 int isSameRegs = sameRegs (AOP (left), AOP (result));
8749 if (isSameRegs && offl>1) {
8750 // we are in big trouble, but this shouldn't happen
8751 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8754 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8759 emitcode ("rlc", "a");
8760 emitcode ("subb", "a,acc");
8762 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8764 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8765 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8768 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8773 emitcode ("clr", "c");
8775 emitcode ("mov", "c,acc.7");
8778 emitcode ("rrc", "a");
8780 if (isSameRegs && offl==MSB16) {
8781 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8783 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8784 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8787 emitcode ("rrc", "a");
8788 if (isSameRegs && offl==1) {
8789 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8791 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8792 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8794 emitcode ("rrc", "a");
8795 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8799 MOVA (aopGet (left, LSB, FALSE, FALSE));
8800 emitcode ("rrc", "a");
8801 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8805 /*-----------------------------------------------------------------*/
8806 /* genrshFour - shift four byte by a known amount != 0 */
8807 /*-----------------------------------------------------------------*/
8809 genrshFour (operand * result, operand * left,
8810 int shCount, int sign)
8812 D(emitcode ("; genrshFour",""));
8814 /* if shifting more that 3 bytes */
8819 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8821 movLeft2Result (left, MSB32, result, LSB, sign);
8822 addSign (result, MSB16, sign);
8824 else if (shCount >= 16)
8828 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8831 movLeft2Result (left, MSB24, result, LSB, 0);
8832 movLeft2Result (left, MSB32, result, MSB16, sign);
8834 addSign (result, MSB24, sign);
8836 else if (shCount >= 8)
8840 shiftRLong (left, MSB16, result, sign);
8841 else if (shCount == 0)
8843 movLeft2Result (left, MSB16, result, LSB, 0);
8844 movLeft2Result (left, MSB24, result, MSB16, 0);
8845 movLeft2Result (left, MSB32, result, MSB24, sign);
8846 addSign (result, MSB32, sign);
8850 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8851 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8852 /* the last shift is signed */
8853 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8854 addSign (result, MSB32, sign);
8858 { /* 1 <= shCount <= 7 */
8861 shiftRLong (left, LSB, result, sign);
8863 shiftRLong (result, LSB, result, sign);
8867 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8868 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8869 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8874 /*-----------------------------------------------------------------*/
8875 /* genRightShiftLiteral - right shifting by known count */
8876 /*-----------------------------------------------------------------*/
8878 genRightShiftLiteral (operand * left,
8884 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8887 D(emitcode ("; genRightShiftLiteral",""));
8889 freeAsmop (right, NULL, ic, TRUE);
8891 aopOp (left, ic, FALSE);
8892 aopOp (result, ic, FALSE);
8895 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8899 size = getDataSize (left);
8900 /* test the LEFT size !!! */
8902 /* I suppose that the left size >= result size */
8905 size = getDataSize (result);
8907 movLeft2Result (left, size, result, size, 0);
8910 else if (shCount >= (size * 8))
8913 /* get sign in acc.7 */
8914 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8916 addSign (result, LSB, sign);
8923 genrshOne (result, left, shCount, sign);
8927 genrshTwo (result, left, shCount, sign);
8931 genrshFour (result, left, shCount, sign);
8937 freeAsmop (left, NULL, ic, TRUE);
8938 freeAsmop (result, NULL, ic, TRUE);
8941 /*-----------------------------------------------------------------*/
8942 /* genSignedRightShift - right shift of signed number */
8943 /*-----------------------------------------------------------------*/
8945 genSignedRightShift (iCode * ic)
8947 operand *right, *left, *result;
8950 symbol *tlbl, *tlbl1;
8953 D(emitcode ("; genSignedRightShift",""));
8955 /* we do it the hard way put the shift count in b
8956 and loop thru preserving the sign */
8958 right = IC_RIGHT (ic);
8959 left = IC_LEFT (ic);
8960 result = IC_RESULT (ic);
8962 aopOp (right, ic, FALSE);
8965 if (AOP_TYPE (right) == AOP_LIT)
8967 genRightShiftLiteral (left, right, result, ic, 1);
8970 /* shift count is unknown then we have to form
8971 a loop get the loop count in B : Note: we take
8972 only the lower order byte since shifting
8973 more that 32 bits make no sense anyway, ( the
8974 largest size of an object can be only 32 bits ) */
8977 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8978 emitcode ("inc", "b");
8979 freeAsmop (right, NULL, ic, TRUE);
8980 aopOp (left, ic, FALSE);
8981 aopOp (result, ic, FALSE);
8983 /* now move the left to the result if they are not the
8985 if (!sameRegs (AOP (left), AOP (result)) &&
8986 AOP_SIZE (result) > 1)
8989 size = AOP_SIZE (result);
8993 l = aopGet (left, offset, FALSE, TRUE);
8994 if (*l == '@' && IS_AOP_PREG (result))
8997 emitcode ("mov", "a,%s", l);
8998 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9001 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9006 /* mov the highest order bit to OVR */
9007 tlbl = newiTempLabel (NULL);
9008 tlbl1 = newiTempLabel (NULL);
9010 size = AOP_SIZE (result);
9012 MOVA (aopGet (left, offset, FALSE, FALSE));
9013 emitcode ("rlc", "a");
9014 emitcode ("mov", "ov,c");
9015 /* if it is only one byte then */
9018 l = aopGet (left, 0, FALSE, FALSE);
9020 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9021 emitcode ("", "%05d$:", tlbl->key + 100);
9022 emitcode ("mov", "c,ov");
9023 emitcode ("rrc", "a");
9024 emitcode ("", "%05d$:", tlbl1->key + 100);
9025 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9027 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9031 reAdjustPreg (AOP (result));
9032 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9033 emitcode ("", "%05d$:", tlbl->key + 100);
9034 emitcode ("mov", "c,ov");
9037 l = aopGet (result, offset, FALSE, FALSE);
9039 emitcode ("rrc", "a");
9040 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9042 reAdjustPreg (AOP (result));
9043 emitcode ("", "%05d$:", tlbl1->key + 100);
9044 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9048 freeAsmop (left, NULL, ic, TRUE);
9049 freeAsmop (result, NULL, ic, TRUE);
9052 /*-----------------------------------------------------------------*/
9053 /* genRightShift - generate code for right shifting */
9054 /*-----------------------------------------------------------------*/
9056 genRightShift (iCode * ic)
9058 operand *right, *left, *result;
9062 symbol *tlbl, *tlbl1;
9065 D(emitcode ("; genRightShift",""));
9067 /* if signed then we do it the hard way preserve the
9068 sign bit moving it inwards */
9069 letype = getSpec (operandType (IC_LEFT (ic)));
9071 if (!SPEC_USIGN (letype))
9073 genSignedRightShift (ic);
9077 /* signed & unsigned types are treated the same : i.e. the
9078 signed is NOT propagated inwards : quoting from the
9079 ANSI - standard : "for E1 >> E2, is equivalent to division
9080 by 2**E2 if unsigned or if it has a non-negative value,
9081 otherwise the result is implementation defined ", MY definition
9082 is that the sign does not get propagated */
9084 right = IC_RIGHT (ic);
9085 left = IC_LEFT (ic);
9086 result = IC_RESULT (ic);
9088 aopOp (right, ic, FALSE);
9090 /* if the shift count is known then do it
9091 as efficiently as possible */
9092 if (AOP_TYPE (right) == AOP_LIT)
9094 genRightShiftLiteral (left, right, result, ic, 0);
9098 /* shift count is unknown then we have to form
9099 a loop get the loop count in B : Note: we take
9100 only the lower order byte since shifting
9101 more that 32 bits make no sense anyway, ( the
9102 largest size of an object can be only 32 bits ) */
9105 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9106 emitcode ("inc", "b");
9107 freeAsmop (right, NULL, ic, TRUE);
9108 aopOp (left, ic, FALSE);
9109 aopOp (result, ic, FALSE);
9111 /* now move the left to the result if they are not the
9113 if (!sameRegs (AOP (left), AOP (result)) &&
9114 AOP_SIZE (result) > 1)
9117 size = AOP_SIZE (result);
9121 l = aopGet (left, offset, FALSE, TRUE);
9122 if (*l == '@' && IS_AOP_PREG (result))
9125 emitcode ("mov", "a,%s", l);
9126 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9129 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9134 tlbl = newiTempLabel (NULL);
9135 tlbl1 = newiTempLabel (NULL);
9136 size = AOP_SIZE (result);
9139 /* if it is only one byte then */
9142 l = aopGet (left, 0, FALSE, FALSE);
9144 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9145 emitcode ("", "%05d$:", tlbl->key + 100);
9147 emitcode ("rrc", "a");
9148 emitcode ("", "%05d$:", tlbl1->key + 100);
9149 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9151 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9155 reAdjustPreg (AOP (result));
9156 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9157 emitcode ("", "%05d$:", tlbl->key + 100);
9161 l = aopGet (result, offset, FALSE, FALSE);
9163 emitcode ("rrc", "a");
9164 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9166 reAdjustPreg (AOP (result));
9168 emitcode ("", "%05d$:", tlbl1->key + 100);
9169 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9173 freeAsmop (left, NULL, ic, TRUE);
9174 freeAsmop (result, NULL, ic, TRUE);
9177 /*-----------------------------------------------------------------*/
9178 /* emitPtrByteGet - emits code to get a byte into A through a */
9179 /* pointer register (R0, R1, or DPTR). The */
9180 /* original value of A can be preserved in B. */
9181 /*-----------------------------------------------------------------*/
9183 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9190 emitcode ("mov", "b,a");
9191 emitcode ("mov", "a,@%s", rname);
9196 emitcode ("mov", "b,a");
9197 emitcode ("movx", "a,@%s", rname);
9202 emitcode ("mov", "b,a");
9203 emitcode ("movx", "a,@dptr");
9208 emitcode ("mov", "b,a");
9209 emitcode ("clr", "a");
9210 emitcode ("movc", "a,@a+dptr");
9216 emitcode ("push", "b");
9217 emitcode ("push", "acc");
9219 emitcode ("lcall", "__gptrget");
9221 emitcode ("pop", "b");
9226 /*-----------------------------------------------------------------*/
9227 /* emitPtrByteSet - emits code to set a byte from src through a */
9228 /* pointer register (R0, R1, or DPTR). */
9229 /*-----------------------------------------------------------------*/
9231 emitPtrByteSet (char *rname, int p_type, char *src)
9240 emitcode ("mov", "@%s,a", rname);
9243 emitcode ("mov", "@%s,%s", rname, src);
9248 emitcode ("movx", "@%s,a", rname);
9253 emitcode ("movx", "@dptr,a");
9258 emitcode ("lcall", "__gptrput");
9263 /*-----------------------------------------------------------------*/
9264 /* genUnpackBits - generates code for unpacking bits */
9265 /*-----------------------------------------------------------------*/
9267 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9269 int offset = 0; /* result byte offset */
9270 int rsize; /* result size */
9271 int rlen = 0; /* remaining bitfield length */
9272 sym_link *etype; /* bitfield type information */
9273 int blen; /* bitfield length */
9274 int bstr; /* bitfield starting bit within byte */
9277 D(emitcode ("; genUnpackBits",""));
9279 etype = getSpec (operandType (result));
9280 rsize = getSize (operandType (result));
9281 blen = SPEC_BLEN (etype);
9282 bstr = SPEC_BSTR (etype);
9284 if (ifx && blen <= 8)
9286 emitPtrByteGet (rname, ptype, FALSE);
9289 SNPRINTF (buffer, sizeof(buffer),
9291 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9296 emitcode ("anl", "a,#0x%02x",
9297 (((unsigned char) -1) >> (8 - blen)) << bstr);
9298 genIfxJump (ifx, "a", NULL, NULL, NULL);
9304 /* If the bitfield length is less than a byte */
9307 emitPtrByteGet (rname, ptype, FALSE);
9309 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9310 if (!SPEC_USIGN (etype))
9312 /* signed bitfield */
9313 symbol *tlbl = newiTempLabel (NULL);
9315 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9316 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9317 emitcode ("", "%05d$:", tlbl->key + 100);
9319 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9323 /* Bit field did not fit in a byte. Copy all
9324 but the partial byte at the end. */
9325 for (rlen=blen;rlen>=8;rlen-=8)
9327 emitPtrByteGet (rname, ptype, FALSE);
9328 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9330 emitcode ("inc", "%s", rname);
9333 /* Handle the partial byte at the end */
9336 emitPtrByteGet (rname, ptype, FALSE);
9337 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9338 if (!SPEC_USIGN (etype))
9340 /* signed bitfield */
9341 symbol *tlbl = newiTempLabel (NULL);
9343 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9344 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9345 emitcode ("", "%05d$:", tlbl->key + 100);
9347 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9355 if (SPEC_USIGN (etype))
9359 /* signed bitfield: sign extension with 0x00 or 0xff */
9360 emitcode ("rlc", "a");
9361 emitcode ("subb", "a,acc");
9367 aopPut (result, source, offset++, isOperandVolatile (result, FALSE));
9372 /*-----------------------------------------------------------------*/
9373 /* genDataPointerGet - generates code when ptr offset is known */
9374 /*-----------------------------------------------------------------*/
9376 genDataPointerGet (operand * left,
9382 int size, offset = 0;
9384 D(emitcode ("; genDataPointerGet",""));
9386 aopOp (result, ic, TRUE);
9388 /* get the string representation of the name */
9389 l = aopGet (left, 0, FALSE, TRUE);
9390 size = AOP_SIZE (result);
9394 sprintf (buffer, "(%s + %d)", l + 1, offset);
9396 sprintf (buffer, "%s", l + 1);
9397 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9400 freeAsmop (left, NULL, ic, TRUE);
9401 freeAsmop (result, NULL, ic, TRUE);
9404 /*-----------------------------------------------------------------*/
9405 /* genNearPointerGet - emitcode for near pointer fetch */
9406 /*-----------------------------------------------------------------*/
9408 genNearPointerGet (operand * left,
9417 sym_link *rtype, *retype;
9418 sym_link *ltype = operandType (left);
9421 D(emitcode ("; genNearPointerGet",""));
9423 rtype = operandType (result);
9424 retype = getSpec (rtype);
9426 aopOp (left, ic, FALSE);
9428 /* if left is rematerialisable and
9429 result is not bitfield variable type and
9430 the left is pointer to data space i.e
9431 lower 128 bytes of space */
9432 if (AOP_TYPE (left) == AOP_IMMD &&
9433 !IS_BITFIELD (retype) &&
9434 DCL_TYPE (ltype) == POINTER)
9436 genDataPointerGet (left, result, ic);
9440 /* if the value is already in a pointer register
9441 then don't need anything more */
9442 if (!AOP_INPREG (AOP (left)))
9444 if (IS_AOP_PREG (left))
9446 // Aha, it is a pointer, just in disguise.
9447 rname = aopGet (left, 0, FALSE, FALSE);
9450 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9451 __FILE__, __LINE__);
9456 emitcode ("mov", "a%s,%s", rname + 1, rname);
9457 rname++; // skip the '@'.
9462 /* otherwise get a free pointer register */
9464 preg = getFreePtr (ic, &aop, FALSE);
9465 emitcode ("mov", "%s,%s",
9467 aopGet (left, 0, FALSE, TRUE));
9472 rname = aopGet (left, 0, FALSE, FALSE);
9474 //aopOp (result, ic, FALSE);
9475 aopOp (result, ic, result?TRUE:FALSE);
9477 /* if bitfield then unpack the bits */
9478 if (IS_BITFIELD (retype))
9479 genUnpackBits (result, rname, POINTER, ifx);
9482 /* we have can just get the values */
9483 int size = AOP_SIZE (result);
9488 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9491 emitcode ("mov", "a,@%s", rname);
9493 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9497 sprintf (buffer, "@%s", rname);
9498 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9502 emitcode ("inc", "%s", rname);
9506 /* now some housekeeping stuff */
9507 if (aop) /* we had to allocate for this iCode */
9509 if (pi) { /* post increment present */
9510 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9512 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9516 /* we did not allocate which means left
9517 already in a pointer register, then
9518 if size > 0 && this could be used again
9519 we have to point it back to where it
9521 if ((AOP_SIZE (result) > 1 &&
9522 !OP_SYMBOL (left)->remat &&
9523 (OP_SYMBOL (left)->liveTo > ic->seq ||
9527 int size = AOP_SIZE (result) - 1;
9529 emitcode ("dec", "%s", rname);
9533 if (ifx && !ifx->generated)
9535 genIfxJump (ifx, "a", left, NULL, result);
9539 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9540 freeAsmop (left, NULL, ic, TRUE);
9541 if (pi) pi->generated = 1;
9544 /*-----------------------------------------------------------------*/
9545 /* genPagedPointerGet - emitcode for paged pointer fetch */
9546 /*-----------------------------------------------------------------*/
9548 genPagedPointerGet (operand * left,
9557 sym_link *rtype, *retype;
9559 D(emitcode ("; genPagedPointerGet",""));
9561 rtype = operandType (result);
9562 retype = getSpec (rtype);
9564 aopOp (left, ic, FALSE);
9566 /* if the value is already in a pointer register
9567 then don't need anything more */
9568 if (!AOP_INPREG (AOP (left)))
9570 /* otherwise get a free pointer register */
9572 preg = getFreePtr (ic, &aop, FALSE);
9573 emitcode ("mov", "%s,%s",
9575 aopGet (left, 0, FALSE, TRUE));
9579 rname = aopGet (left, 0, FALSE, FALSE);
9581 aopOp (result, ic, FALSE);
9583 /* if bitfield then unpack the bits */
9584 if (IS_BITFIELD (retype))
9585 genUnpackBits (result, rname, PPOINTER, ifx);
9588 /* we have can just get the values */
9589 int size = AOP_SIZE (result);
9595 emitcode ("movx", "a,@%s", rname);
9597 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9602 emitcode ("inc", "%s", rname);
9606 /* now some housekeeping stuff */
9607 if (aop) /* we had to allocate for this iCode */
9609 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9610 freeAsmop (NULL, aop, ic, TRUE);
9614 /* we did not allocate which means left
9615 already in a pointer register, then
9616 if size > 0 && this could be used again
9617 we have to point it back to where it
9619 if ((AOP_SIZE (result) > 1 &&
9620 !OP_SYMBOL (left)->remat &&
9621 (OP_SYMBOL (left)->liveTo > ic->seq ||
9625 int size = AOP_SIZE (result) - 1;
9627 emitcode ("dec", "%s", rname);
9631 if (ifx && !ifx->generated)
9633 genIfxJump (ifx, "a", left, NULL, result);
9637 freeAsmop (left, NULL, ic, TRUE);
9638 freeAsmop (result, NULL, ic, TRUE);
9639 if (pi) pi->generated = 1;
9643 /*--------------------------------------------------------------------*/
9644 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9645 /*--------------------------------------------------------------------*/
9647 loadDptrFromOperand (operand *op, bool loadBToo)
9649 if (AOP_TYPE (op) != AOP_STR)
9651 /* if this is rematerializable */
9652 if (AOP_TYPE (op) == AOP_IMMD)
9654 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9657 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9658 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9661 wassertl(FALSE, "need pointerCode");
9662 emitcode ("", "; mov b,???");
9663 /* genPointerGet and genPointerSet originally did different
9664 ** things for this case. Both seem wrong.
9665 ** from genPointerGet:
9666 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9667 ** from genPointerSet:
9668 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9673 else if (AOP_TYPE (op) == AOP_DPTR)
9677 MOVA (aopGet (op, 0, FALSE, FALSE));
9678 emitcode ("push", "acc");
9679 MOVA (aopGet (op, 1, FALSE, FALSE));
9680 emitcode ("push", "acc");
9681 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9682 emitcode ("pop", "dph");
9683 emitcode ("pop", "dpl");
9687 MOVA (aopGet (op, 0, FALSE, FALSE));
9688 emitcode ("push", "acc");
9689 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9690 emitcode ("pop", "dpl");
9694 { /* we need to get it byte by byte */
9695 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9696 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9698 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9703 /*-----------------------------------------------------------------*/
9704 /* genFarPointerGet - gget value from far space */
9705 /*-----------------------------------------------------------------*/
9707 genFarPointerGet (operand * left,
9708 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9711 sym_link *retype = getSpec (operandType (result));
9713 D(emitcode ("; genFarPointerGet",""));
9715 aopOp (left, ic, FALSE);
9716 loadDptrFromOperand (left, FALSE);
9718 /* so dptr now contains the address */
9719 aopOp (result, ic, FALSE);
9721 /* if bit then unpack */
9722 if (IS_BITFIELD (retype))
9723 genUnpackBits (result, "dptr", FPOINTER, ifx);
9726 size = AOP_SIZE (result);
9731 emitcode ("movx", "a,@dptr");
9733 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9735 emitcode ("inc", "dptr");
9739 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9741 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9742 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9746 if (ifx && !ifx->generated)
9748 genIfxJump (ifx, "a", left, NULL, result);
9751 freeAsmop (left, NULL, ic, TRUE);
9752 freeAsmop (result, NULL, ic, TRUE);
9755 /*-----------------------------------------------------------------*/
9756 /* genCodePointerGet - gget value from code space */
9757 /*-----------------------------------------------------------------*/
9759 genCodePointerGet (operand * left,
9760 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9763 sym_link *retype = getSpec (operandType (result));
9765 D(emitcode ("; genCodePointerGet",""));
9767 aopOp (left, ic, FALSE);
9768 loadDptrFromOperand (left, FALSE);
9770 /* so dptr now contains the address */
9771 aopOp (result, ic, FALSE);
9773 /* if bit then unpack */
9774 if (IS_BITFIELD (retype))
9775 genUnpackBits (result, "dptr", CPOINTER, ifx);
9778 size = AOP_SIZE (result);
9785 emitcode ("clr", "a");
9786 emitcode ("movc", "a,@a+dptr");
9788 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9789 emitcode ("inc", "dptr");
9793 emitcode ("mov", "a,#0x%02x", offset);
9794 emitcode ("movc", "a,@a+dptr");
9796 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9801 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9803 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9804 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9808 if (ifx && !ifx->generated)
9810 genIfxJump (ifx, "a", left, NULL, result);
9813 freeAsmop (left, NULL, ic, TRUE);
9814 freeAsmop (result, NULL, ic, TRUE);
9817 /*-----------------------------------------------------------------*/
9818 /* genGenPointerGet - gget value from generic pointer space */
9819 /*-----------------------------------------------------------------*/
9821 genGenPointerGet (operand * left,
9822 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9825 sym_link *retype = getSpec (operandType (result));
9827 D(emitcode ("; genGenPointerGet",""));
9829 aopOp (left, ic, FALSE);
9830 loadDptrFromOperand (left, TRUE);
9832 /* so dptr know contains the address */
9833 aopOp (result, ic, FALSE);
9835 /* if bit then unpack */
9836 if (IS_BITFIELD (retype))
9837 genUnpackBits (result, "dptr", GPOINTER, ifx);
9840 size = AOP_SIZE (result);
9845 emitcode ("lcall", "__gptrget");
9847 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9849 emitcode ("inc", "dptr");
9853 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9855 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9856 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9860 if (ifx && !ifx->generated)
9862 genIfxJump (ifx, "a", left, NULL, result);
9866 freeAsmop (left, NULL, ic, TRUE);
9867 freeAsmop (result, NULL, ic, TRUE);
9870 /*-----------------------------------------------------------------*/
9871 /* genPointerGet - generate code for pointer get */
9872 /*-----------------------------------------------------------------*/
9874 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9876 operand *left, *result;
9877 sym_link *type, *etype;
9880 D(emitcode ("; genPointerGet",""));
9882 left = IC_LEFT (ic);
9883 result = IC_RESULT (ic);
9885 if (getSize (operandType (result))>1)
9888 /* depending on the type of pointer we need to
9889 move it to the correct pointer register */
9890 type = operandType (left);
9891 etype = getSpec (type);
9892 /* if left is of type of pointer then it is simple */
9893 if (IS_PTR (type) && !IS_FUNC (type->next))
9894 p_type = DCL_TYPE (type);
9897 /* we have to go by the storage class */
9898 p_type = PTR_TYPE (SPEC_OCLS (etype));
9901 /* special case when cast remat */
9902 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9903 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9904 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9905 type = operandType (left);
9906 p_type = DCL_TYPE (type);
9908 /* now that we have the pointer type we assign
9909 the pointer values */
9915 genNearPointerGet (left, result, ic, pi, ifx);
9919 genPagedPointerGet (left, result, ic, pi, ifx);
9923 genFarPointerGet (left, result, ic, pi, ifx);
9927 genCodePointerGet (left, result, ic, pi, ifx);
9931 genGenPointerGet (left, result, ic, pi, ifx);
9939 /*-----------------------------------------------------------------*/
9940 /* genPackBits - generates code for packed bit storage */
9941 /*-----------------------------------------------------------------*/
9943 genPackBits (sym_link * etype,
9945 char *rname, int p_type)
9947 int offset = 0; /* source byte offset */
9948 int rlen = 0; /* remaining bitfield length */
9949 int blen; /* bitfield length */
9950 int bstr; /* bitfield starting bit within byte */
9951 int litval; /* source literal value (if AOP_LIT) */
9952 unsigned char mask; /* bitmask within current byte */
9954 D(emitcode ("; genPackBits",""));
9956 blen = SPEC_BLEN (etype);
9957 bstr = SPEC_BSTR (etype);
9959 /* If the bitfield length is less than a byte */
9962 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9963 (unsigned char) (0xFF >> (8 - bstr)));
9965 if (AOP_TYPE (right) == AOP_LIT)
9967 /* Case with a bitfield length <8 and literal source
9969 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9971 litval &= (~mask) & 0xff;
9972 emitPtrByteGet (rname, p_type, FALSE);
9973 if ((mask|litval)!=0xff)
9974 emitcode ("anl","a,#0x%02x", mask);
9976 emitcode ("orl","a,#0x%02x", litval);
9980 if ((blen==1) && (p_type!=GPOINTER))
9982 /* Case with a bitfield length == 1 and no generic pointer
9984 if (AOP_TYPE (right) == AOP_CRY)
9985 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9988 MOVA (aopGet (right, 0, FALSE, FALSE));
9989 emitcode ("rrc","a");
9991 emitPtrByteGet (rname, p_type, FALSE);
9992 emitcode ("mov","acc.%d,c",bstr);
9997 /* Case with a bitfield length < 8 and arbitrary source
9999 MOVA (aopGet (right, 0, FALSE, FALSE));
10000 /* shift and mask source value */
10002 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10004 pushedB = pushB ();
10005 /* transfer A to B and get next byte */
10006 emitPtrByteGet (rname, p_type, TRUE);
10008 emitcode ("anl", "a,#0x%02x", mask);
10009 emitcode ("orl", "a,b");
10010 if (p_type == GPOINTER)
10011 emitcode ("pop", "b");
10017 emitPtrByteSet (rname, p_type, "a");
10021 /* Bit length is greater than 7 bits. In this case, copy */
10022 /* all except the partial byte at the end */
10023 for (rlen=blen;rlen>=8;rlen-=8)
10025 emitPtrByteSet (rname, p_type,
10026 aopGet (right, offset++, FALSE, TRUE) );
10028 emitcode ("inc", "%s", rname);
10031 /* If there was a partial byte at the end */
10034 mask = (((unsigned char) -1 << rlen) & 0xff);
10036 if (AOP_TYPE (right) == AOP_LIT)
10038 /* Case with partial byte and literal source
10040 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10041 litval >>= (blen-rlen);
10042 litval &= (~mask) & 0xff;
10043 emitPtrByteGet (rname, p_type, FALSE);
10044 if ((mask|litval)!=0xff)
10045 emitcode ("anl","a,#0x%02x", mask);
10047 emitcode ("orl","a,#0x%02x", litval);
10052 /* Case with partial byte and arbitrary source
10054 MOVA (aopGet (right, offset++, FALSE, FALSE));
10055 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10057 pushedB = pushB ();
10058 /* transfer A to B and get next byte */
10059 emitPtrByteGet (rname, p_type, TRUE);
10061 emitcode ("anl", "a,#0x%02x", mask);
10062 emitcode ("orl", "a,b");
10063 if (p_type == GPOINTER)
10064 emitcode ("pop", "b");
10068 emitPtrByteSet (rname, p_type, "a");
10074 /*-----------------------------------------------------------------*/
10075 /* genDataPointerSet - remat pointer to data space */
10076 /*-----------------------------------------------------------------*/
10078 genDataPointerSet (operand * right,
10082 int size, offset = 0;
10083 char *l, buffer[256];
10085 D(emitcode ("; genDataPointerSet",""));
10087 aopOp (right, ic, FALSE);
10089 l = aopGet (result, 0, FALSE, TRUE);
10090 size = AOP_SIZE (right);
10094 sprintf (buffer, "(%s + %d)", l + 1, offset);
10096 sprintf (buffer, "%s", l + 1);
10097 emitcode ("mov", "%s,%s", buffer,
10098 aopGet (right, offset++, FALSE, FALSE));
10101 freeAsmop (right, NULL, ic, TRUE);
10102 freeAsmop (result, NULL, ic, TRUE);
10105 /*-----------------------------------------------------------------*/
10106 /* genNearPointerSet - emitcode for near pointer put */
10107 /*-----------------------------------------------------------------*/
10109 genNearPointerSet (operand * right,
10117 sym_link *retype, *letype;
10118 sym_link *ptype = operandType (result);
10120 D(emitcode ("; genNearPointerSet",""));
10122 retype = getSpec (operandType (right));
10123 letype = getSpec (ptype);
10124 aopOp (result, ic, FALSE);
10126 /* if the result is rematerializable &
10127 in data space & not a bit variable */
10128 if (AOP_TYPE (result) == AOP_IMMD &&
10129 DCL_TYPE (ptype) == POINTER &&
10130 !IS_BITVAR (retype) &&
10131 !IS_BITVAR (letype))
10133 genDataPointerSet (right, result, ic);
10137 /* if the value is already in a pointer register
10138 then don't need anything more */
10139 if (!AOP_INPREG (AOP (result)))
10142 //AOP_TYPE (result) == AOP_STK
10143 IS_AOP_PREG(result)
10146 // Aha, it is a pointer, just in disguise.
10147 rname = aopGet (result, 0, FALSE, FALSE);
10150 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10151 __FILE__, __LINE__);
10156 emitcode ("mov", "a%s,%s", rname + 1, rname);
10157 rname++; // skip the '@'.
10162 /* otherwise get a free pointer register */
10163 aop = newAsmop (0);
10164 preg = getFreePtr (ic, &aop, FALSE);
10165 emitcode ("mov", "%s,%s",
10167 aopGet (result, 0, FALSE, TRUE));
10168 rname = preg->name;
10173 rname = aopGet (result, 0, FALSE, FALSE);
10176 aopOp (right, ic, FALSE);
10178 /* if bitfield then unpack the bits */
10179 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10180 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10183 /* we have can just get the values */
10184 int size = AOP_SIZE (right);
10189 l = aopGet (right, offset, FALSE, TRUE);
10193 emitcode ("mov", "@%s,a", rname);
10196 emitcode ("mov", "@%s,%s", rname, l);
10198 emitcode ("inc", "%s", rname);
10203 /* now some housekeeping stuff */
10204 if (aop) /* we had to allocate for this iCode */
10207 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10208 freeAsmop (NULL, aop, ic, TRUE);
10212 /* we did not allocate which means left
10213 already in a pointer register, then
10214 if size > 0 && this could be used again
10215 we have to point it back to where it
10217 if ((AOP_SIZE (right) > 1 &&
10218 !OP_SYMBOL (result)->remat &&
10219 (OP_SYMBOL (result)->liveTo > ic->seq ||
10223 int size = AOP_SIZE (right) - 1;
10225 emitcode ("dec", "%s", rname);
10230 if (pi) pi->generated = 1;
10231 freeAsmop (result, NULL, ic, TRUE);
10232 freeAsmop (right, NULL, ic, TRUE);
10235 /*-----------------------------------------------------------------*/
10236 /* genPagedPointerSet - emitcode for Paged pointer put */
10237 /*-----------------------------------------------------------------*/
10239 genPagedPointerSet (operand * right,
10247 sym_link *retype, *letype;
10249 D(emitcode ("; genPagedPointerSet",""));
10251 retype = getSpec (operandType (right));
10252 letype = getSpec (operandType (result));
10254 aopOp (result, ic, FALSE);
10256 /* if the value is already in a pointer register
10257 then don't need anything more */
10258 if (!AOP_INPREG (AOP (result)))
10260 /* otherwise get a free pointer register */
10261 aop = newAsmop (0);
10262 preg = getFreePtr (ic, &aop, FALSE);
10263 emitcode ("mov", "%s,%s",
10265 aopGet (result, 0, FALSE, TRUE));
10266 rname = preg->name;
10269 rname = aopGet (result, 0, FALSE, FALSE);
10271 aopOp (right, ic, FALSE);
10273 /* if bitfield then unpack the bits */
10274 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10275 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10278 /* we have can just get the values */
10279 int size = AOP_SIZE (right);
10284 l = aopGet (right, offset, FALSE, TRUE);
10287 emitcode ("movx", "@%s,a", rname);
10290 emitcode ("inc", "%s", rname);
10296 /* now some housekeeping stuff */
10297 if (aop) /* we had to allocate for this iCode */
10300 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10301 freeAsmop (NULL, aop, ic, TRUE);
10305 /* we did not allocate which means left
10306 already in a pointer register, then
10307 if size > 0 && this could be used again
10308 we have to point it back to where it
10310 if (AOP_SIZE (right) > 1 &&
10311 !OP_SYMBOL (result)->remat &&
10312 (OP_SYMBOL (result)->liveTo > ic->seq ||
10315 int size = AOP_SIZE (right) - 1;
10317 emitcode ("dec", "%s", rname);
10322 if (pi) pi->generated = 1;
10323 freeAsmop (result, NULL, ic, TRUE);
10324 freeAsmop (right, NULL, ic, TRUE);
10329 /*-----------------------------------------------------------------*/
10330 /* genFarPointerSet - set value from far space */
10331 /*-----------------------------------------------------------------*/
10333 genFarPointerSet (operand * right,
10334 operand * result, iCode * ic, iCode * pi)
10337 sym_link *retype = getSpec (operandType (right));
10338 sym_link *letype = getSpec (operandType (result));
10340 D(emitcode ("; genFarPointerSet",""));
10342 aopOp (result, ic, FALSE);
10343 loadDptrFromOperand (result, FALSE);
10345 /* so dptr know contains the address */
10346 aopOp (right, ic, FALSE);
10348 /* if bit then unpack */
10349 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10350 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10353 size = AOP_SIZE (right);
10358 char *l = aopGet (right, offset++, FALSE, FALSE);
10360 emitcode ("movx", "@dptr,a");
10362 emitcode ("inc", "dptr");
10365 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10366 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10367 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10370 freeAsmop (result, NULL, ic, TRUE);
10371 freeAsmop (right, NULL, ic, TRUE);
10374 /*-----------------------------------------------------------------*/
10375 /* genGenPointerSet - set value from generic pointer space */
10376 /*-----------------------------------------------------------------*/
10378 genGenPointerSet (operand * right,
10379 operand * result, iCode * ic, iCode * pi)
10382 sym_link *retype = getSpec (operandType (right));
10383 sym_link *letype = getSpec (operandType (result));
10385 D(emitcode ("; genGenPointerSet",""));
10387 aopOp (result, ic, FALSE);
10388 loadDptrFromOperand (result, TRUE);
10390 /* so dptr know contains the address */
10391 aopOp (right, ic, FALSE);
10393 /* if bit then unpack */
10394 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10395 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10398 size = AOP_SIZE (right);
10403 char *l = aopGet (right, offset++, FALSE, FALSE);
10405 emitcode ("lcall", "__gptrput");
10407 emitcode ("inc", "dptr");
10411 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10412 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10413 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10416 freeAsmop (result, NULL, ic, TRUE);
10417 freeAsmop (right, NULL, ic, TRUE);
10420 /*-----------------------------------------------------------------*/
10421 /* genPointerSet - stores the value into a pointer location */
10422 /*-----------------------------------------------------------------*/
10424 genPointerSet (iCode * ic, iCode *pi)
10426 operand *right, *result;
10427 sym_link *type, *etype;
10430 D(emitcode ("; genPointerSet",""));
10432 right = IC_RIGHT (ic);
10433 result = IC_RESULT (ic);
10435 /* depending on the type of pointer we need to
10436 move it to the correct pointer register */
10437 type = operandType (result);
10438 etype = getSpec (type);
10439 /* if left is of type of pointer then it is simple */
10440 if (IS_PTR (type) && !IS_FUNC (type->next))
10442 p_type = DCL_TYPE (type);
10446 /* we have to go by the storage class */
10447 p_type = PTR_TYPE (SPEC_OCLS (etype));
10450 /* special case when cast remat */
10451 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10452 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10453 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10454 type = operandType (result);
10455 p_type = DCL_TYPE (type);
10457 /* now that we have the pointer type we assign
10458 the pointer values */
10464 genNearPointerSet (right, result, ic, pi);
10468 genPagedPointerSet (right, result, ic, pi);
10472 genFarPointerSet (right, result, ic, pi);
10476 genGenPointerSet (right, result, ic, pi);
10480 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10481 "genPointerSet: illegal pointer type");
10486 /*-----------------------------------------------------------------*/
10487 /* genIfx - generate code for Ifx statement */
10488 /*-----------------------------------------------------------------*/
10490 genIfx (iCode * ic, iCode * popIc)
10492 operand *cond = IC_COND (ic);
10496 D(emitcode ("; genIfx",""));
10498 aopOp (cond, ic, FALSE);
10500 /* get the value into acc */
10501 if (AOP_TYPE (cond) != AOP_CRY)
10506 if (AOP(cond)->aopu.aop_dir)
10507 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10509 /* the result is now in the accumulator or a directly addressable bit */
10510 freeAsmop (cond, NULL, ic, TRUE);
10512 /* if there was something to be popped then do it */
10516 /* if the condition is a bit variable */
10518 genIfxJump(ic, dup, NULL, NULL, NULL);
10519 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10520 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10521 else if (isbit && !IS_ITEMP (cond))
10522 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10524 genIfxJump (ic, "a", NULL, NULL, NULL);
10529 /*-----------------------------------------------------------------*/
10530 /* genAddrOf - generates code for address of */
10531 /*-----------------------------------------------------------------*/
10533 genAddrOf (iCode * ic)
10535 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10538 D(emitcode ("; genAddrOf",""));
10540 aopOp (IC_RESULT (ic), ic, FALSE);
10542 /* if the operand is on the stack then we
10543 need to get the stack offset of this
10547 /* if it has an offset then we need to compute
10551 emitcode ("mov", "a,%s", SYM_BP (sym));
10552 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10553 ((char) (sym->stack - _G.nRegsSaved)) :
10554 ((char) sym->stack)) & 0xff);
10555 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10559 /* we can just move _bp */
10560 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10562 /* fill the result with zero */
10563 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10568 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10574 /* object not on stack then we need the name */
10575 size = AOP_SIZE (IC_RESULT (ic));
10580 char s[SDCC_NAME_MAX];
10582 sprintf (s, "#(%s >> %d)",
10586 sprintf (s, "#%s", sym->rname);
10587 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10591 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10595 /*-----------------------------------------------------------------*/
10596 /* genFarFarAssign - assignment when both are in far space */
10597 /*-----------------------------------------------------------------*/
10599 genFarFarAssign (operand * result, operand * right, iCode * ic)
10601 int size = AOP_SIZE (right);
10605 D(emitcode ("; genFarFarAssign",""));
10607 /* first push the right side on to the stack */
10610 l = aopGet (right, offset++, FALSE, FALSE);
10612 emitcode ("push", "acc");
10615 freeAsmop (right, NULL, ic, FALSE);
10616 /* now assign DPTR to result */
10617 aopOp (result, ic, FALSE);
10618 size = AOP_SIZE (result);
10621 emitcode ("pop", "acc");
10622 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10624 freeAsmop (result, NULL, ic, FALSE);
10628 /*-----------------------------------------------------------------*/
10629 /* genAssign - generate code for assignment */
10630 /*-----------------------------------------------------------------*/
10632 genAssign (iCode * ic)
10634 operand *result, *right;
10636 unsigned long lit = 0L;
10638 D(emitcode("; genAssign",""));
10640 result = IC_RESULT (ic);
10641 right = IC_RIGHT (ic);
10643 /* if they are the same */
10644 if (operandsEqu (result, right) &&
10645 !isOperandVolatile (result, FALSE) &&
10646 !isOperandVolatile (right, FALSE))
10649 aopOp (right, ic, FALSE);
10651 /* special case both in far space */
10652 if (AOP_TYPE (right) == AOP_DPTR &&
10653 IS_TRUE_SYMOP (result) &&
10654 isOperandInFarSpace (result))
10657 genFarFarAssign (result, right, ic);
10661 aopOp (result, ic, TRUE);
10663 /* if they are the same registers */
10664 if (sameRegs (AOP (right), AOP (result)) &&
10665 !isOperandVolatile (result, FALSE) &&
10666 !isOperandVolatile (right, FALSE))
10669 /* if the result is a bit */
10670 if (AOP_TYPE (result) == AOP_CRY)
10673 /* if the right size is a literal then
10674 we know what the value is */
10675 if (AOP_TYPE (right) == AOP_LIT)
10677 if (((int) operandLitValue (right)))
10678 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10680 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10684 /* the right is also a bit variable */
10685 if (AOP_TYPE (right) == AOP_CRY)
10687 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10688 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10692 /* we need to or */
10694 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10698 /* bit variables done */
10700 size = AOP_SIZE (result);
10702 if (AOP_TYPE (right) == AOP_LIT)
10703 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10705 (AOP_TYPE (result) != AOP_REG) &&
10706 (AOP_TYPE (right) == AOP_LIT) &&
10707 !IS_FLOAT (operandType (right)) &&
10710 while ((size) && (lit))
10713 aopGet (right, offset, FALSE, FALSE),
10715 isOperandVolatile (result, FALSE));
10720 emitcode ("clr", "a");
10723 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10732 aopGet (right, offset, FALSE, FALSE),
10734 isOperandVolatile (result, FALSE));
10740 freeAsmop (right, NULL, ic, TRUE);
10741 freeAsmop (result, NULL, ic, TRUE);
10744 /*-----------------------------------------------------------------*/
10745 /* genJumpTab - generates code for jump table */
10746 /*-----------------------------------------------------------------*/
10748 genJumpTab (iCode * ic)
10750 symbol *jtab,*jtablo,*jtabhi;
10752 unsigned int count;
10754 D(emitcode ("; genJumpTab",""));
10756 count = elementsInSet( IC_JTLABELS (ic) );
10760 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10761 if the switch argument is in a register.
10762 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10763 /* (MB) What if peephole converts ljmp to sjmp or ret ???
10764 How will multiply by three be updated ???*/
10765 aopOp (IC_JTCOND (ic), ic, FALSE);
10766 /* get the condition into accumulator */
10767 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10769 /* multiply by three */
10770 emitcode ("add", "a,acc");
10771 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10772 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10774 jtab = newiTempLabel (NULL);
10775 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10776 emitcode ("jmp", "@a+dptr");
10777 emitcode ("", "%05d$:", jtab->key + 100);
10778 /* now generate the jump labels */
10779 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10780 jtab = setNextItem (IC_JTLABELS (ic)))
10781 emitcode ("ljmp", "%05d$", jtab->key + 100);
10785 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10786 if the switch argument is in a register.
10787 For n>6 this algorithm may be more compact */
10788 jtablo = newiTempLabel (NULL);
10789 jtabhi = newiTempLabel (NULL);
10791 /* get the condition into accumulator.
10792 Using b as temporary storage, if register push/pop is needed */
10793 aopOp (IC_JTCOND (ic), ic, FALSE);
10794 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10795 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10796 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10798 // (MB) what if B is in use???
10799 wassertl(!BINUSE, "B was in use");
10800 emitcode ("mov", "b,%s", l);
10803 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10807 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10808 emitcode ("movc", "a,@a+pc");
10809 emitcode ("push", "acc");
10812 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10813 emitcode ("movc", "a,@a+pc");
10814 emitcode ("push", "acc");
10818 /* this scales up to n<=255, but needs two more bytes
10819 and changes dptr */
10820 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10821 emitcode ("movc", "a,@a+dptr");
10822 emitcode ("push", "acc");
10825 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10826 emitcode ("movc", "a,@a+dptr");
10827 emitcode ("push", "acc");
10830 emitcode ("ret", "");
10832 /* now generate jump table, LSB */
10833 emitcode ("", "%05d$:", jtablo->key + 100);
10834 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10835 jtab = setNextItem (IC_JTLABELS (ic)))
10836 emitcode (".db", "%05d$", jtab->key + 100);
10838 /* now generate jump table, MSB */
10839 emitcode ("", "%05d$:", jtabhi->key + 100);
10840 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10841 jtab = setNextItem (IC_JTLABELS (ic)))
10842 emitcode (".db", "%05d$>>8", jtab->key + 100);
10846 /*-----------------------------------------------------------------*/
10847 /* genCast - gen code for casting */
10848 /*-----------------------------------------------------------------*/
10850 genCast (iCode * ic)
10852 operand *result = IC_RESULT (ic);
10853 sym_link *ctype = operandType (IC_LEFT (ic));
10854 sym_link *rtype = operandType (IC_RIGHT (ic));
10855 operand *right = IC_RIGHT (ic);
10858 D(emitcode("; genCast",""));
10860 /* if they are equivalent then do nothing */
10861 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10864 aopOp (right, ic, FALSE);
10865 aopOp (result, ic, FALSE);
10867 /* if the result is a bit (and not a bitfield) */
10868 // if (AOP_TYPE (result) == AOP_CRY)
10869 if (IS_BIT (OP_SYMBOL (result)->type))
10870 /* not for bitfields */
10872 /* if the right size is a literal then
10873 we know what the value is */
10874 if (AOP_TYPE (right) == AOP_LIT)
10876 if (((int) operandLitValue (right)))
10877 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10879 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10884 /* the right is also a bit variable */
10885 if (AOP_TYPE (right) == AOP_CRY)
10887 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10888 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10892 /* we need to or */
10894 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10899 /* if they are the same size : or less */
10900 if (AOP_SIZE (result) <= AOP_SIZE (right))
10903 /* if they are in the same place */
10904 if (sameRegs (AOP (right), AOP (result)))
10907 /* if they in different places then copy */
10908 size = AOP_SIZE (result);
10913 aopGet (right, offset, FALSE, FALSE),
10915 isOperandVolatile (result, FALSE));
10922 /* if the result is of type pointer */
10923 if (IS_PTR (ctype))
10927 sym_link *type = operandType (right);
10928 sym_link *etype = getSpec (type);
10930 /* pointer to generic pointer */
10931 if (IS_GENPTR (ctype))
10934 p_type = DCL_TYPE (type);
10937 if (SPEC_SCLS(etype)==S_REGISTER) {
10938 // let's assume it is a generic pointer
10941 /* we have to go by the storage class */
10942 p_type = PTR_TYPE (SPEC_OCLS (etype));
10946 /* the first two bytes are known */
10947 size = GPTRSIZE - 1;
10952 aopGet (right, offset, FALSE, FALSE),
10954 isOperandVolatile (result, FALSE));
10957 /* the last byte depending on type */
10959 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10964 // pointerTypeToGPByte will have bitched.
10968 sprintf(gpValStr, "#0x%x", gpVal);
10969 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10974 /* just copy the pointers */
10975 size = AOP_SIZE (result);
10980 aopGet (right, offset, FALSE, FALSE),
10982 isOperandVolatile (result, FALSE));
10988 /* so we now know that the size of destination is greater
10989 than the size of the source */
10990 /* we move to result for the size of source */
10991 size = AOP_SIZE (right);
10996 aopGet (right, offset, FALSE, FALSE),
10998 isOperandVolatile (result, FALSE));
11002 /* now depending on the sign of the source && destination */
11003 size = AOP_SIZE (result) - AOP_SIZE (right);
11004 /* if unsigned or not an integral type */
11005 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11008 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
11012 /* we need to extend the sign :{ */
11013 char *l = aopGet (right, AOP_SIZE (right) - 1,
11016 emitcode ("rlc", "a");
11017 emitcode ("subb", "a,acc");
11019 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
11022 /* we are done hurray !!!! */
11025 freeAsmop (right, NULL, ic, TRUE);
11026 freeAsmop (result, NULL, ic, TRUE);
11030 /*-----------------------------------------------------------------*/
11031 /* genDjnz - generate decrement & jump if not zero instrucion */
11032 /*-----------------------------------------------------------------*/
11034 genDjnz (iCode * ic, iCode * ifx)
11036 symbol *lbl, *lbl1;
11040 D(emitcode ("; genDjnz",""));
11042 /* if the if condition has a false label
11043 then we cannot save */
11044 if (IC_FALSE (ifx))
11047 /* if the minus is not of the form
11049 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11050 !IS_OP_LITERAL (IC_RIGHT (ic)))
11053 if (operandLitValue (IC_RIGHT (ic)) != 1)
11056 /* if the size of this greater than one then no
11058 if (getSize (operandType (IC_RESULT (ic))) > 1)
11061 /* otherwise we can save BIG */
11062 lbl = newiTempLabel (NULL);
11063 lbl1 = newiTempLabel (NULL);
11065 aopOp (IC_RESULT (ic), ic, FALSE);
11067 if (AOP_NEEDSACC(IC_RESULT(ic)))
11069 /* If the result is accessed indirectly via
11070 * the accumulator, we must explicitly write
11071 * it back after the decrement.
11073 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11075 if (strcmp(rByte, "a"))
11077 /* Something is hopelessly wrong */
11078 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11079 __FILE__, __LINE__);
11080 /* We can just give up; the generated code will be inefficient,
11081 * but what the hey.
11083 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11086 emitcode ("dec", "%s", rByte);
11087 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
11088 emitcode ("jnz", "%05d$", lbl->key + 100);
11090 else if (IS_AOP_PREG (IC_RESULT (ic)))
11092 emitcode ("dec", "%s",
11093 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11094 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11095 emitcode ("jnz", "%05d$", lbl->key + 100);
11099 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11102 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11103 emitcode ("", "%05d$:", lbl->key + 100);
11104 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11105 emitcode ("", "%05d$:", lbl1->key + 100);
11107 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11108 ifx->generated = 1;
11112 /*-----------------------------------------------------------------*/
11113 /* genReceive - generate code for a receive iCode */
11114 /*-----------------------------------------------------------------*/
11116 genReceive (iCode * ic)
11118 int size = getSize (operandType (IC_RESULT (ic)));
11121 D(emitcode ("; genReceive",""));
11123 if (ic->argreg == 1)
11124 { /* first parameter */
11125 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11126 isOperandInPagedSpace (IC_RESULT (ic))) &&
11127 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11128 IS_TRUE_SYMOP (IC_RESULT (ic))))
11131 int receivingA = 0;
11134 for (offset = 0; offset<size; offset++)
11135 if (!strcmp (fReturn[offset], "a"))
11140 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11142 for (offset = size-1; offset>0; offset--)
11143 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11144 emitcode("mov","a,%s", fReturn[0]);
11146 aopOp (IC_RESULT (ic), ic, FALSE);
11148 aopPut (IC_RESULT (ic), "a", offset,
11149 isOperandVolatile (IC_RESULT (ic), FALSE));
11150 for (offset = 1; offset<size; offset++)
11151 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
11152 isOperandVolatile (IC_RESULT (ic), FALSE));
11158 if (getTempRegs(tempRegs, size, ic))
11160 for (offset = 0; offset<size; offset++)
11161 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11162 aopOp (IC_RESULT (ic), ic, FALSE);
11163 for (offset = 0; offset<size; offset++)
11164 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
11165 isOperandVolatile (IC_RESULT (ic), FALSE));
11170 offset = fReturnSizeMCS51 - size;
11173 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11174 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11177 aopOp (IC_RESULT (ic), ic, FALSE);
11178 size = AOP_SIZE (IC_RESULT (ic));
11182 emitcode ("pop", "acc");
11183 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11189 aopOp (IC_RESULT (ic), ic, FALSE);
11191 assignResultValue (IC_RESULT (ic), NULL);
11194 else if (ic->argreg > 12)
11195 { /* bit parameters */
11196 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11198 aopOp (IC_RESULT (ic), ic, FALSE);
11199 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11200 outBitC(IC_RESULT (ic));
11204 { /* other parameters */
11206 aopOp (IC_RESULT (ic), ic, FALSE);
11207 rb1off = ic->argreg;
11210 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11215 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11218 /*-----------------------------------------------------------------*/
11219 /* genDummyRead - generate code for dummy read of volatiles */
11220 /*-----------------------------------------------------------------*/
11222 genDummyRead (iCode * ic)
11227 D(emitcode("; genDummyRead",""));
11229 op = IC_RIGHT (ic);
11230 if (op && IS_SYMOP (op))
11232 aopOp (op, ic, FALSE);
11234 /* if the result is a bit */
11235 if (AOP_TYPE (op) == AOP_CRY)
11236 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11239 /* bit variables done */
11241 size = AOP_SIZE (op);
11245 MOVA (aopGet (op, offset, FALSE, FALSE));
11250 freeAsmop (op, NULL, ic, TRUE);
11254 if (op && IS_SYMOP (op))
11256 aopOp (op, ic, FALSE);
11258 /* if the result is a bit */
11259 if (AOP_TYPE (op) == AOP_CRY)
11260 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11263 /* bit variables done */
11265 size = AOP_SIZE (op);
11269 MOVA (aopGet (op, offset, FALSE, FALSE));
11274 freeAsmop (op, NULL, ic, TRUE);
11278 /*-----------------------------------------------------------------*/
11279 /* genCritical - generate code for start of a critical sequence */
11280 /*-----------------------------------------------------------------*/
11282 genCritical (iCode *ic)
11284 symbol *tlbl = newiTempLabel (NULL);
11286 D(emitcode("; genCritical",""));
11288 if (IC_RESULT (ic))
11290 aopOp (IC_RESULT (ic), ic, TRUE);
11291 aopPut (IC_RESULT (ic), one, 0, 0);
11292 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11293 aopPut (IC_RESULT (ic), zero, 0, 0);
11294 emitcode ("", "%05d$:", (tlbl->key + 100));
11295 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11299 emitcode ("setb", "c");
11300 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11301 emitcode ("clr", "c");
11302 emitcode ("", "%05d$:", (tlbl->key + 100));
11303 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11307 /*-----------------------------------------------------------------*/
11308 /* genEndCritical - generate code for end of a critical sequence */
11309 /*-----------------------------------------------------------------*/
11311 genEndCritical (iCode *ic)
11313 D(emitcode("; genEndCritical",""));
11317 aopOp (IC_RIGHT (ic), ic, FALSE);
11318 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11320 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11321 emitcode ("mov", "ea,c");
11325 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11326 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11327 emitcode ("rrc", "a");
11328 emitcode ("mov", "ea,c");
11330 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11334 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11335 emitcode ("mov", "ea,c");
11339 /*-----------------------------------------------------------------*/
11340 /* gen51Code - generate code for 8051 based controllers */
11341 /*-----------------------------------------------------------------*/
11343 gen51Code (iCode * lic)
11347 /* int cseq = 0; */
11349 _G.currentFunc = NULL;
11350 lineHead = lineCurr = NULL;
11352 /* print the allocation information */
11353 if (allocInfo && currFunc)
11354 printAllocInfo (currFunc, codeOutFile);
11355 /* if debug information required */
11356 if (options.debug && currFunc)
11358 debugFile->writeFunction (currFunc, lic);
11360 /* stack pointer name */
11361 if (options.useXstack)
11367 for (ic = lic; ic; ic = ic->next)
11369 _G.current_iCode = ic;
11371 if (ic->lineno && cln != ic->lineno)
11375 debugFile->writeCLine (ic);
11377 if (!options.noCcodeInAsm) {
11378 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11379 printCLine(ic->filename, ic->lineno));
11384 if (ic->seqPoint && ic->seqPoint != cseq)
11386 emitcode ("", "; sequence point %d", ic->seqPoint);
11387 cseq = ic->seqPoint;
11390 if (options.iCodeInAsm) {
11391 char regsInUse[80];
11395 for (i=0; i<8; i++) {
11396 sprintf (®sInUse[i],
11397 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11400 strcpy (regsInUse, "--------");
11401 for (i=0; i < 8; i++) {
11402 if (bitVectBitValue (ic->rMask, i))
11404 int offset = regs8051[i].offset;
11405 regsInUse[offset] = offset + '0'; /* show rMask */
11409 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11411 /* if the result is marked as
11412 spilt and rematerializable or code for
11413 this has already been generated then
11415 if (resultRemat (ic) || ic->generated)
11418 /* depending on the operation */
11438 /* IPOP happens only when trying to restore a
11439 spilt live range, if there is an ifx statement
11440 following this pop then the if statement might
11441 be using some of the registers being popped which
11442 would destory the contents of the register so
11443 we need to check for this condition and handle it */
11445 ic->next->op == IFX &&
11446 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11447 genIfx (ic->next, ic);
11465 genEndFunction (ic);
11485 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11502 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11506 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11513 /* note these two are xlated by algebraic equivalence
11514 during parsing SDCC.y */
11515 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11516 "got '>=' or '<=' shouldn't have come here");
11520 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11532 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11536 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11540 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11576 genRightShift (ic);
11579 case GET_VALUE_AT_ADDRESS:
11581 hasInc (IC_LEFT (ic), ic,
11582 getSize (operandType (IC_RESULT (ic)))),
11583 ifxForOp (IC_RESULT (ic), ic) );
11587 if (POINTER_SET (ic))
11588 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11614 addSet (&_G.sendSet, ic);
11617 case DUMMY_READ_VOLATILE:
11626 genEndCritical (ic);
11638 _G.current_iCode = NULL;
11640 /* now we are ready to call the
11641 peep hole optimizer */
11642 if (!options.nopeep)
11643 peepHole (&lineHead);
11645 /* now do the actual printing */
11646 printLine (lineHead, codeOutFile);