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_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4389 freeAsmop (IC_LEFT (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_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4705 freeAsmop (IC_LEFT (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 (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4973 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4974 freeAsmop (result, NULL, ic, 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");
7477 freeAsmop (left, NULL, ic, TRUE);
7478 freeAsmop (result, NULL, ic, TRUE);
7481 /*-----------------------------------------------------------------*/
7482 /* genGetAbit - generates code get a single bit */
7483 /*-----------------------------------------------------------------*/
7485 genGetAbit (iCode * ic)
7487 operand *left, *right, *result;
7490 D(emitcode ("; genGetAbit",""));
7492 left = IC_LEFT (ic);
7493 right = IC_RIGHT (ic);
7494 result = IC_RESULT (ic);
7495 aopOp (left, ic, FALSE);
7496 aopOp (right, ic, FALSE);
7497 aopOp (result, ic, FALSE);
7499 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7501 /* get the needed byte into a */
7502 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7504 if (AOP_TYPE (result) == AOP_CRY)
7507 emitcode ("rlc", "a");
7508 else if ((shCount) == 0)
7509 emitcode ("rrc", "a");
7511 emitcode ("mov", "c,acc[%d]", shCount);
7519 emitcode ("rr", "a");
7522 emitcode ("rr", "a");
7525 emitcode ("anl", "a,#0x01");
7529 emitcode ("mov", "c,acc[%d]", shCount);
7530 emitcode ("clr", "a");
7531 emitcode ("rlc", "a");
7534 emitcode ("swap", "a");
7535 emitcode ("anl", "a,#0x01");
7538 emitcode ("rl", "a");
7541 emitcode ("rl", "a");
7542 emitcode ("anl", "a,#0x01");
7548 freeAsmop (right, NULL, ic, TRUE);
7549 freeAsmop (left, NULL, ic, TRUE);
7550 freeAsmop (result, NULL, ic, TRUE);
7553 /*-----------------------------------------------------------------*/
7554 /* genGetByte - generates code get a single byte */
7555 /*-----------------------------------------------------------------*/
7557 genGetByte (iCode * ic)
7559 operand *left, *right, *result;
7562 D(emitcode ("; genGetByte",""));
7564 left = IC_LEFT (ic);
7565 right = IC_RIGHT (ic);
7566 result = IC_RESULT (ic);
7567 aopOp (left, ic, FALSE);
7568 aopOp (right, ic, FALSE);
7569 aopOp (result, ic, FALSE);
7571 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7573 aopGet (left, offset, FALSE, FALSE),
7575 isOperandVolatile (result, FALSE));
7577 freeAsmop (right, NULL, ic, TRUE);
7578 freeAsmop (left, NULL, ic, TRUE);
7579 freeAsmop (result, NULL, ic, TRUE);
7582 /*-----------------------------------------------------------------*/
7583 /* genGetWord - generates code get two bytes */
7584 /*-----------------------------------------------------------------*/
7586 genGetWord (iCode * ic)
7588 operand *left, *right, *result;
7591 D(emitcode ("; genGetWord",""));
7593 left = IC_LEFT (ic);
7594 right = IC_RIGHT (ic);
7595 result = IC_RESULT (ic);
7596 aopOp (left, ic, FALSE);
7597 aopOp (right, ic, FALSE);
7598 aopOp (result, ic, FALSE);
7600 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7602 aopGet (left, offset, FALSE, FALSE),
7604 isOperandVolatile (result, FALSE));
7606 aopGet (left, offset+1, FALSE, FALSE),
7608 isOperandVolatile (result, FALSE));
7610 freeAsmop (right, NULL, ic, TRUE);
7611 freeAsmop (left, NULL, ic, TRUE);
7612 freeAsmop (result, NULL, ic, TRUE);
7615 /*-----------------------------------------------------------------*/
7616 /* genSwap - generates code to swap nibbles or bytes */
7617 /*-----------------------------------------------------------------*/
7619 genSwap (iCode * ic)
7621 operand *left, *result;
7623 D(emitcode ("; genSwap",""));
7625 left = IC_LEFT (ic);
7626 result = IC_RESULT (ic);
7627 aopOp (left, ic, FALSE);
7628 aopOp (result, ic, FALSE);
7630 switch (AOP_SIZE (left))
7632 case 1: /* swap nibbles in byte */
7633 MOVA (aopGet (left, 0, FALSE, FALSE));
7634 emitcode ("swap", "a");
7635 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7637 case 2: /* swap bytes in word */
7638 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7640 MOVA (aopGet (left, 0, FALSE, FALSE));
7641 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7642 0, isOperandVolatile (result, FALSE));
7643 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7645 else if (operandsEqu (left, result))
7648 bool pushedB = FALSE, leftInB = FALSE;
7650 MOVA (aopGet (left, 0, FALSE, FALSE));
7651 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7654 emitcode ("mov", "b,a");
7658 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7659 0, isOperandVolatile (result, FALSE));
7660 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7667 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7668 0, isOperandVolatile (result, FALSE));
7669 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7670 1, isOperandVolatile (result, FALSE));
7674 wassertl(FALSE, "unsupported SWAP operand size");
7677 freeAsmop (left, NULL, ic, TRUE);
7678 freeAsmop (result, NULL, ic, TRUE);
7682 /*-----------------------------------------------------------------*/
7683 /* AccRol - rotate left accumulator by known count */
7684 /*-----------------------------------------------------------------*/
7686 AccRol (int shCount)
7688 shCount &= 0x0007; // shCount : 0..7
7695 emitcode ("rl", "a");
7698 emitcode ("rl", "a");
7699 emitcode ("rl", "a");
7702 emitcode ("swap", "a");
7703 emitcode ("rr", "a");
7706 emitcode ("swap", "a");
7709 emitcode ("swap", "a");
7710 emitcode ("rl", "a");
7713 emitcode ("rr", "a");
7714 emitcode ("rr", "a");
7717 emitcode ("rr", "a");
7722 /*-----------------------------------------------------------------*/
7723 /* AccLsh - left shift accumulator by known count */
7724 /*-----------------------------------------------------------------*/
7726 AccLsh (int shCount)
7731 emitcode ("add", "a,acc");
7732 else if (shCount == 2)
7734 emitcode ("add", "a,acc");
7735 emitcode ("add", "a,acc");
7739 /* rotate left accumulator */
7741 /* and kill the lower order bits */
7742 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7747 /*-----------------------------------------------------------------*/
7748 /* AccRsh - right shift accumulator by known count */
7749 /*-----------------------------------------------------------------*/
7751 AccRsh (int shCount)
7758 emitcode ("rrc", "a");
7762 /* rotate right accumulator */
7763 AccRol (8 - shCount);
7764 /* and kill the higher order bits */
7765 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7770 /*-----------------------------------------------------------------*/
7771 /* AccSRsh - signed right shift accumulator by known count */
7772 /*-----------------------------------------------------------------*/
7774 AccSRsh (int shCount)
7781 emitcode ("mov", "c,acc.7");
7782 emitcode ("rrc", "a");
7784 else if (shCount == 2)
7786 emitcode ("mov", "c,acc.7");
7787 emitcode ("rrc", "a");
7788 emitcode ("mov", "c,acc.7");
7789 emitcode ("rrc", "a");
7793 tlbl = newiTempLabel (NULL);
7794 /* rotate right accumulator */
7795 AccRol (8 - shCount);
7796 /* and kill the higher order bits */
7797 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7798 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7799 emitcode ("orl", "a,#0x%02x",
7800 (unsigned char) ~SRMask[shCount]);
7801 emitcode ("", "%05d$:", tlbl->key + 100);
7806 /*-----------------------------------------------------------------*/
7807 /* shiftR1Left2Result - shift right one byte from left to result */
7808 /*-----------------------------------------------------------------*/
7810 shiftR1Left2Result (operand * left, int offl,
7811 operand * result, int offr,
7812 int shCount, int sign)
7814 MOVA (aopGet (left, offl, FALSE, FALSE));
7815 /* shift right accumulator */
7820 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7823 /*-----------------------------------------------------------------*/
7824 /* shiftL1Left2Result - shift left one byte from left to result */
7825 /*-----------------------------------------------------------------*/
7827 shiftL1Left2Result (operand * left, int offl,
7828 operand * result, int offr, int shCount)
7831 l = aopGet (left, offl, FALSE, FALSE);
7833 /* shift left accumulator */
7835 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7838 /*-----------------------------------------------------------------*/
7839 /* movLeft2Result - move byte from left to result */
7840 /*-----------------------------------------------------------------*/
7842 movLeft2Result (operand * left, int offl,
7843 operand * result, int offr, int sign)
7846 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7848 l = aopGet (left, offl, FALSE, FALSE);
7850 if (*l == '@' && (IS_AOP_PREG (result)))
7852 emitcode ("mov", "a,%s", l);
7853 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7858 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7861 /* MSB sign in acc.7 ! */
7862 if (getDataSize (left) == offl + 1)
7865 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7872 /*-----------------------------------------------------------------*/
7873 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7874 /*-----------------------------------------------------------------*/
7878 emitcode ("rrc", "a");
7879 emitcode ("xch", "a,%s", x);
7880 emitcode ("rrc", "a");
7881 emitcode ("xch", "a,%s", x);
7884 /*-----------------------------------------------------------------*/
7885 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7886 /*-----------------------------------------------------------------*/
7890 emitcode ("xch", "a,%s", x);
7891 emitcode ("rlc", "a");
7892 emitcode ("xch", "a,%s", x);
7893 emitcode ("rlc", "a");
7896 /*-----------------------------------------------------------------*/
7897 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7898 /*-----------------------------------------------------------------*/
7902 emitcode ("xch", "a,%s", x);
7903 emitcode ("add", "a,acc");
7904 emitcode ("xch", "a,%s", x);
7905 emitcode ("rlc", "a");
7908 /*-----------------------------------------------------------------*/
7909 /* AccAXLsh - left shift a:x by known count (0..7) */
7910 /*-----------------------------------------------------------------*/
7912 AccAXLsh (char *x, int shCount)
7927 case 5: // AAAAABBB:CCCCCDDD
7929 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7931 emitcode ("anl", "a,#0x%02x",
7932 SLMask[shCount]); // BBB00000:CCCCCDDD
7934 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7936 AccRol (shCount); // DDDCCCCC:BBB00000
7938 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7940 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7942 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7944 emitcode ("anl", "a,#0x%02x",
7945 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7947 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7949 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7952 case 6: // AAAAAABB:CCCCCCDD
7953 emitcode ("anl", "a,#0x%02x",
7954 SRMask[shCount]); // 000000BB:CCCCCCDD
7955 emitcode ("mov", "c,acc.0"); // c = B
7956 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7958 AccAXRrl1 (x); // BCCCCCCD:D000000B
7959 AccAXRrl1 (x); // BBCCCCCC:DD000000
7961 emitcode("rrc","a");
7962 emitcode("xch","a,%s", x);
7963 emitcode("rrc","a");
7964 emitcode("mov","c,acc.0"); //<< get correct bit
7965 emitcode("xch","a,%s", x);
7967 emitcode("rrc","a");
7968 emitcode("xch","a,%s", x);
7969 emitcode("rrc","a");
7970 emitcode("xch","a,%s", x);
7973 case 7: // a:x <<= 7
7975 emitcode ("anl", "a,#0x%02x",
7976 SRMask[shCount]); // 0000000B:CCCCCCCD
7978 emitcode ("mov", "c,acc.0"); // c = B
7980 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7982 AccAXRrl1 (x); // BCCCCCCC:D0000000
7990 /*-----------------------------------------------------------------*/
7991 /* AccAXRsh - right shift a:x known count (0..7) */
7992 /*-----------------------------------------------------------------*/
7994 AccAXRsh (char *x, int shCount)
8002 AccAXRrl1 (x); // 0->a:x
8007 AccAXRrl1 (x); // 0->a:x
8010 AccAXRrl1 (x); // 0->a:x
8015 case 5: // AAAAABBB:CCCCCDDD = a:x
8017 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
8019 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8021 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8023 emitcode ("anl", "a,#0x%02x",
8024 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8026 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8028 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8030 emitcode ("anl", "a,#0x%02x",
8031 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8033 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8035 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8037 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8040 case 6: // AABBBBBB:CCDDDDDD
8042 emitcode ("mov", "c,acc.7");
8043 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8045 emitcode ("mov", "c,acc.7");
8046 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8048 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8050 emitcode ("anl", "a,#0x%02x",
8051 SRMask[shCount]); // 000000AA:BBBBBBCC
8054 case 7: // ABBBBBBB:CDDDDDDD
8056 emitcode ("mov", "c,acc.7"); // c = A
8058 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8060 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8062 emitcode ("anl", "a,#0x%02x",
8063 SRMask[shCount]); // 0000000A:BBBBBBBC
8071 /*-----------------------------------------------------------------*/
8072 /* AccAXRshS - right shift signed a:x known count (0..7) */
8073 /*-----------------------------------------------------------------*/
8075 AccAXRshS (char *x, int shCount)
8083 emitcode ("mov", "c,acc.7");
8084 AccAXRrl1 (x); // s->a:x
8088 emitcode ("mov", "c,acc.7");
8089 AccAXRrl1 (x); // s->a:x
8091 emitcode ("mov", "c,acc.7");
8092 AccAXRrl1 (x); // s->a:x
8097 case 5: // AAAAABBB:CCCCCDDD = a:x
8099 tlbl = newiTempLabel (NULL);
8100 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8102 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8104 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8106 emitcode ("anl", "a,#0x%02x",
8107 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8109 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8111 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8113 emitcode ("anl", "a,#0x%02x",
8114 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8116 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8118 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8120 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8122 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8123 emitcode ("orl", "a,#0x%02x",
8124 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8126 emitcode ("", "%05d$:", tlbl->key + 100);
8127 break; // SSSSAAAA:BBBCCCCC
8129 case 6: // AABBBBBB:CCDDDDDD
8131 tlbl = newiTempLabel (NULL);
8132 emitcode ("mov", "c,acc.7");
8133 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8135 emitcode ("mov", "c,acc.7");
8136 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8138 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8140 emitcode ("anl", "a,#0x%02x",
8141 SRMask[shCount]); // 000000AA:BBBBBBCC
8143 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8144 emitcode ("orl", "a,#0x%02x",
8145 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8147 emitcode ("", "%05d$:", tlbl->key + 100);
8149 case 7: // ABBBBBBB:CDDDDDDD
8151 tlbl = newiTempLabel (NULL);
8152 emitcode ("mov", "c,acc.7"); // c = A
8154 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8156 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8158 emitcode ("anl", "a,#0x%02x",
8159 SRMask[shCount]); // 0000000A:BBBBBBBC
8161 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8162 emitcode ("orl", "a,#0x%02x",
8163 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8165 emitcode ("", "%05d$:", tlbl->key + 100);
8172 /*-----------------------------------------------------------------*/
8173 /* shiftL2Left2Result - shift left two bytes from left to result */
8174 /*-----------------------------------------------------------------*/
8176 shiftL2Left2Result (operand * left, int offl,
8177 operand * result, int offr, int shCount)
8180 bool pushedB = FALSE;
8183 if (sameRegs (AOP (result), AOP (left)) &&
8184 ((offl + MSB16) == offr))
8186 /* don't crash result[offr] */
8187 MOVA (aopGet (left, offl, FALSE, FALSE));
8188 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8189 x = aopGet (result, offr, FALSE, FALSE);
8191 else if (aopGetUsesAcc (result, offr))
8193 movLeft2Result (left, offl, result, offr, 0);
8196 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8197 MOVA (aopGet (result, offr, FALSE, FALSE));
8198 emitcode ("xch", "a,b");
8203 movLeft2Result (left, offl, result, offr, 0);
8204 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8205 x = aopGet (result, offr, FALSE, FALSE);
8207 /* ax << shCount (x = lsb(result)) */
8208 AccAXLsh (x, shCount);
8211 emitcode ("xch", "a,b");
8212 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8213 aopPut (result, "b", offr + MSB16, isOperandVolatile (result, FALSE));
8218 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8223 /*-----------------------------------------------------------------*/
8224 /* shiftR2Left2Result - shift right two bytes from left to result */
8225 /*-----------------------------------------------------------------*/
8227 shiftR2Left2Result (operand * left, int offl,
8228 operand * result, int offr,
8229 int shCount, int sign)
8232 bool pushedB = FALSE;
8235 if (sameRegs (AOP (result), AOP (left)) &&
8236 ((offl + MSB16) == offr))
8238 /* don't crash result[offr] */
8239 MOVA (aopGet (left, offl, FALSE, FALSE));
8240 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8241 x = aopGet (result, offr, FALSE, FALSE);
8243 else if (aopGetUsesAcc (result, offr))
8245 movLeft2Result (left, offl, result, offr, 0);
8248 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8249 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8254 movLeft2Result (left, offl, result, offr, 0);
8255 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8256 x = aopGet (result, offr, FALSE, FALSE);
8258 /* a:x >> shCount (x = lsb(result)) */
8260 AccAXRshS (x, shCount);
8262 AccAXRsh (x, shCount);
8265 emitcode ("xch", "a,b");
8266 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8267 emitcode ("xch", "a,b");
8270 if (getDataSize (result) > 1)
8271 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8274 /*-----------------------------------------------------------------*/
8275 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8276 /*-----------------------------------------------------------------*/
8278 shiftLLeftOrResult (operand * left, int offl,
8279 operand * result, int offr, int shCount)
8281 MOVA (aopGet (left, offl, FALSE, FALSE));
8282 /* shift left accumulator */
8284 /* or with result */
8285 if (aopGetUsesAcc (result, offr))
8287 emitcode ("xch", "a,b");
8288 MOVA (aopGet (result, offr, FALSE, FALSE));
8289 emitcode ("orl", "a,b");
8293 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8295 /* back to result */
8296 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8299 /*-----------------------------------------------------------------*/
8300 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8301 /*-----------------------------------------------------------------*/
8303 shiftRLeftOrResult (operand * left, int offl,
8304 operand * result, int offr, int shCount)
8306 MOVA (aopGet (left, offl, FALSE, FALSE));
8307 /* shift right accumulator */
8309 /* or with result */
8310 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8311 /* back to result */
8312 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8315 /*-----------------------------------------------------------------*/
8316 /* genlshOne - left shift a one byte quantity by known count */
8317 /*-----------------------------------------------------------------*/
8319 genlshOne (operand * result, operand * left, int shCount)
8321 D(emitcode ("; genlshOne",""));
8323 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8326 /*-----------------------------------------------------------------*/
8327 /* genlshTwo - left shift two bytes by known amount != 0 */
8328 /*-----------------------------------------------------------------*/
8330 genlshTwo (operand * result, operand * left, int shCount)
8334 D(emitcode ("; genlshTwo",""));
8336 size = getDataSize (result);
8338 /* if shCount >= 8 */
8346 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8348 movLeft2Result (left, LSB, result, MSB16, 0);
8350 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8353 /* 1 <= shCount <= 7 */
8357 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8359 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8363 /*-----------------------------------------------------------------*/
8364 /* shiftLLong - shift left one long from left to result */
8365 /* offl = LSB or MSB16 */
8366 /*-----------------------------------------------------------------*/
8368 shiftLLong (operand * left, operand * result, int offr)
8371 int size = AOP_SIZE (result);
8373 if (size >= LSB + offr)
8375 l = aopGet (left, LSB, FALSE, FALSE);
8377 emitcode ("add", "a,acc");
8378 if (sameRegs (AOP (left), AOP (result)) &&
8379 size >= MSB16 + offr && offr != LSB)
8380 emitcode ("xch", "a,%s",
8381 aopGet (left, LSB + offr, FALSE, FALSE));
8383 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8386 if (size >= MSB16 + offr)
8388 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8390 l = aopGet (left, MSB16, FALSE, FALSE);
8393 emitcode ("rlc", "a");
8394 if (sameRegs (AOP (left), AOP (result)) &&
8395 size >= MSB24 + offr && offr != LSB)
8396 emitcode ("xch", "a,%s",
8397 aopGet (left, MSB16 + offr, FALSE, FALSE));
8399 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8402 if (size >= MSB24 + offr)
8404 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8406 l = aopGet (left, MSB24, FALSE, FALSE);
8409 emitcode ("rlc", "a");
8410 if (sameRegs (AOP (left), AOP (result)) &&
8411 size >= MSB32 + offr && offr != LSB)
8412 emitcode ("xch", "a,%s",
8413 aopGet (left, MSB24 + offr, FALSE, FALSE));
8415 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8418 if (size > MSB32 + offr)
8420 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8422 l = aopGet (left, MSB32, FALSE, FALSE);
8425 emitcode ("rlc", "a");
8426 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8429 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8432 /*-----------------------------------------------------------------*/
8433 /* genlshFour - shift four byte by a known amount != 0 */
8434 /*-----------------------------------------------------------------*/
8436 genlshFour (operand * result, operand * left, int shCount)
8440 D(emitcode ("; genlshFour",""));
8442 size = AOP_SIZE (result);
8444 /* if shifting more that 3 bytes */
8449 /* lowest order of left goes to the highest
8450 order of the destination */
8451 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8453 movLeft2Result (left, LSB, result, MSB32, 0);
8454 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8455 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8456 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8460 /* more than two bytes */
8461 else if (shCount >= 16)
8463 /* lower order two bytes goes to higher order two bytes */
8465 /* if some more remaining */
8467 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8470 movLeft2Result (left, MSB16, result, MSB32, 0);
8471 movLeft2Result (left, LSB, result, MSB24, 0);
8473 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8474 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8478 /* if more than 1 byte */
8479 else if (shCount >= 8)
8481 /* lower order three bytes goes to higher order three bytes */
8486 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8488 movLeft2Result (left, LSB, result, MSB16, 0);
8494 movLeft2Result (left, MSB24, result, MSB32, 0);
8495 movLeft2Result (left, MSB16, result, MSB24, 0);
8496 movLeft2Result (left, LSB, result, MSB16, 0);
8497 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8499 else if (shCount == 1)
8500 shiftLLong (left, result, MSB16);
8503 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8504 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8505 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8506 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8511 /* 1 <= shCount <= 7 */
8512 else if (shCount <= 2)
8514 shiftLLong (left, result, LSB);
8516 shiftLLong (result, result, LSB);
8518 /* 3 <= shCount <= 7, optimize */
8521 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8522 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8523 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8527 /*-----------------------------------------------------------------*/
8528 /* genLeftShiftLiteral - left shifting by known count */
8529 /*-----------------------------------------------------------------*/
8531 genLeftShiftLiteral (operand * left,
8536 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8539 D(emitcode ("; genLeftShiftLiteral",""));
8541 freeAsmop (right, NULL, ic, TRUE);
8543 aopOp (left, ic, FALSE);
8544 aopOp (result, ic, FALSE);
8546 size = getSize (operandType (result));
8549 emitcode ("; shift left ", "result %d, left %d", size,
8553 /* I suppose that the left size >= result size */
8558 movLeft2Result (left, size, result, size, 0);
8562 else if (shCount >= (size * 8))
8564 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8570 genlshOne (result, left, shCount);
8574 genlshTwo (result, left, shCount);
8578 genlshFour (result, left, shCount);
8581 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8582 "*** ack! mystery literal shift!\n");
8586 freeAsmop (left, NULL, ic, TRUE);
8587 freeAsmop (result, NULL, ic, TRUE);
8590 /*-----------------------------------------------------------------*/
8591 /* genLeftShift - generates code for left shifting */
8592 /*-----------------------------------------------------------------*/
8594 genLeftShift (iCode * ic)
8596 operand *left, *right, *result;
8599 symbol *tlbl, *tlbl1;
8602 D(emitcode ("; genLeftShift",""));
8604 right = IC_RIGHT (ic);
8605 left = IC_LEFT (ic);
8606 result = IC_RESULT (ic);
8608 aopOp (right, ic, FALSE);
8610 /* if the shift count is known then do it
8611 as efficiently as possible */
8612 if (AOP_TYPE (right) == AOP_LIT)
8614 genLeftShiftLiteral (left, right, result, ic);
8618 /* shift count is unknown then we have to form
8619 a loop get the loop count in B : Note: we take
8620 only the lower order byte since shifting
8621 more that 32 bits make no sense anyway, ( the
8622 largest size of an object can be only 32 bits ) */
8625 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8626 emitcode ("inc", "b");
8627 freeAsmop (right, NULL, ic, TRUE);
8628 aopOp (left, ic, FALSE);
8629 aopOp (result, ic, FALSE);
8631 /* now move the left to the result if they are not the same */
8632 if (!sameRegs (AOP (left), AOP (result)) &&
8633 AOP_SIZE (result) > 1)
8636 size = AOP_SIZE (result);
8640 l = aopGet (left, offset, FALSE, TRUE);
8641 if (*l == '@' && (IS_AOP_PREG (result)))
8644 emitcode ("mov", "a,%s", l);
8645 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8648 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8653 tlbl = newiTempLabel (NULL);
8654 size = AOP_SIZE (result);
8656 tlbl1 = newiTempLabel (NULL);
8658 /* if it is only one byte then */
8661 symbol *tlbl1 = newiTempLabel (NULL);
8663 l = aopGet (left, 0, FALSE, FALSE);
8665 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8666 emitcode ("", "%05d$:", tlbl->key + 100);
8667 emitcode ("add", "a,acc");
8668 emitcode ("", "%05d$:", tlbl1->key + 100);
8669 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8671 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8675 reAdjustPreg (AOP (result));
8677 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8678 emitcode ("", "%05d$:", tlbl->key + 100);
8679 l = aopGet (result, offset, FALSE, FALSE);
8681 emitcode ("add", "a,acc");
8682 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8685 l = aopGet (result, offset, FALSE, FALSE);
8687 emitcode ("rlc", "a");
8688 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8690 reAdjustPreg (AOP (result));
8692 emitcode ("", "%05d$:", tlbl1->key + 100);
8693 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8696 freeAsmop (left, NULL, ic, TRUE);
8697 freeAsmop (result, NULL, ic, TRUE);
8700 /*-----------------------------------------------------------------*/
8701 /* genrshOne - right shift a one byte quantity by known count */
8702 /*-----------------------------------------------------------------*/
8704 genrshOne (operand * result, operand * left,
8705 int shCount, int sign)
8707 D(emitcode ("; genrshOne",""));
8709 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8712 /*-----------------------------------------------------------------*/
8713 /* genrshTwo - right shift two bytes by known amount != 0 */
8714 /*-----------------------------------------------------------------*/
8716 genrshTwo (operand * result, operand * left,
8717 int shCount, int sign)
8719 D(emitcode ("; genrshTwo",""));
8721 /* if shCount >= 8 */
8726 shiftR1Left2Result (left, MSB16, result, LSB,
8729 movLeft2Result (left, MSB16, result, LSB, sign);
8730 addSign (result, MSB16, sign);
8733 /* 1 <= shCount <= 7 */
8735 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8738 /*-----------------------------------------------------------------*/
8739 /* shiftRLong - shift right one long from left to result */
8740 /* offl = LSB or MSB16 */
8741 /*-----------------------------------------------------------------*/
8743 shiftRLong (operand * left, int offl,
8744 operand * result, int sign)
8746 int isSameRegs = sameRegs (AOP (left), AOP (result));
8748 if (isSameRegs && offl>1) {
8749 // we are in big trouble, but this shouldn't happen
8750 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8753 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8758 emitcode ("rlc", "a");
8759 emitcode ("subb", "a,acc");
8761 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8763 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8764 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8767 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8772 emitcode ("clr", "c");
8774 emitcode ("mov", "c,acc.7");
8777 emitcode ("rrc", "a");
8779 if (isSameRegs && offl==MSB16) {
8780 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8782 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8783 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8786 emitcode ("rrc", "a");
8787 if (isSameRegs && offl==1) {
8788 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8790 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8791 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8793 emitcode ("rrc", "a");
8794 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8798 MOVA (aopGet (left, LSB, FALSE, FALSE));
8799 emitcode ("rrc", "a");
8800 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8804 /*-----------------------------------------------------------------*/
8805 /* genrshFour - shift four byte by a known amount != 0 */
8806 /*-----------------------------------------------------------------*/
8808 genrshFour (operand * result, operand * left,
8809 int shCount, int sign)
8811 D(emitcode ("; genrshFour",""));
8813 /* if shifting more that 3 bytes */
8818 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8820 movLeft2Result (left, MSB32, result, LSB, sign);
8821 addSign (result, MSB16, sign);
8823 else if (shCount >= 16)
8827 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8830 movLeft2Result (left, MSB24, result, LSB, 0);
8831 movLeft2Result (left, MSB32, result, MSB16, sign);
8833 addSign (result, MSB24, sign);
8835 else if (shCount >= 8)
8839 shiftRLong (left, MSB16, result, sign);
8840 else if (shCount == 0)
8842 movLeft2Result (left, MSB16, result, LSB, 0);
8843 movLeft2Result (left, MSB24, result, MSB16, 0);
8844 movLeft2Result (left, MSB32, result, MSB24, sign);
8845 addSign (result, MSB32, sign);
8849 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8850 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8851 /* the last shift is signed */
8852 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8853 addSign (result, MSB32, sign);
8857 { /* 1 <= shCount <= 7 */
8860 shiftRLong (left, LSB, result, sign);
8862 shiftRLong (result, LSB, result, sign);
8866 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8867 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8868 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8873 /*-----------------------------------------------------------------*/
8874 /* genRightShiftLiteral - right shifting by known count */
8875 /*-----------------------------------------------------------------*/
8877 genRightShiftLiteral (operand * left,
8883 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8886 D(emitcode ("; genRightShiftLiteral",""));
8888 freeAsmop (right, NULL, ic, TRUE);
8890 aopOp (left, ic, FALSE);
8891 aopOp (result, ic, FALSE);
8894 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8898 size = getDataSize (left);
8899 /* test the LEFT size !!! */
8901 /* I suppose that the left size >= result size */
8904 size = getDataSize (result);
8906 movLeft2Result (left, size, result, size, 0);
8909 else if (shCount >= (size * 8))
8912 /* get sign in acc.7 */
8913 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8915 addSign (result, LSB, sign);
8922 genrshOne (result, left, shCount, sign);
8926 genrshTwo (result, left, shCount, sign);
8930 genrshFour (result, left, shCount, sign);
8936 freeAsmop (left, NULL, ic, TRUE);
8937 freeAsmop (result, NULL, ic, TRUE);
8940 /*-----------------------------------------------------------------*/
8941 /* genSignedRightShift - right shift of signed number */
8942 /*-----------------------------------------------------------------*/
8944 genSignedRightShift (iCode * ic)
8946 operand *right, *left, *result;
8949 symbol *tlbl, *tlbl1;
8952 D(emitcode ("; genSignedRightShift",""));
8954 /* we do it the hard way put the shift count in b
8955 and loop thru preserving the sign */
8957 right = IC_RIGHT (ic);
8958 left = IC_LEFT (ic);
8959 result = IC_RESULT (ic);
8961 aopOp (right, ic, FALSE);
8964 if (AOP_TYPE (right) == AOP_LIT)
8966 genRightShiftLiteral (left, right, result, ic, 1);
8969 /* shift count is unknown then we have to form
8970 a loop get the loop count in B : Note: we take
8971 only the lower order byte since shifting
8972 more that 32 bits make no sense anyway, ( the
8973 largest size of an object can be only 32 bits ) */
8976 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8977 emitcode ("inc", "b");
8978 freeAsmop (right, NULL, ic, TRUE);
8979 aopOp (left, ic, FALSE);
8980 aopOp (result, ic, FALSE);
8982 /* now move the left to the result if they are not the
8984 if (!sameRegs (AOP (left), AOP (result)) &&
8985 AOP_SIZE (result) > 1)
8988 size = AOP_SIZE (result);
8992 l = aopGet (left, offset, FALSE, TRUE);
8993 if (*l == '@' && IS_AOP_PREG (result))
8996 emitcode ("mov", "a,%s", l);
8997 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9000 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9005 /* mov the highest order bit to OVR */
9006 tlbl = newiTempLabel (NULL);
9007 tlbl1 = newiTempLabel (NULL);
9009 size = AOP_SIZE (result);
9011 MOVA (aopGet (left, offset, FALSE, FALSE));
9012 emitcode ("rlc", "a");
9013 emitcode ("mov", "ov,c");
9014 /* if it is only one byte then */
9017 l = aopGet (left, 0, FALSE, FALSE);
9019 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9020 emitcode ("", "%05d$:", tlbl->key + 100);
9021 emitcode ("mov", "c,ov");
9022 emitcode ("rrc", "a");
9023 emitcode ("", "%05d$:", tlbl1->key + 100);
9024 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9026 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9030 reAdjustPreg (AOP (result));
9031 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9032 emitcode ("", "%05d$:", tlbl->key + 100);
9033 emitcode ("mov", "c,ov");
9036 l = aopGet (result, offset, FALSE, FALSE);
9038 emitcode ("rrc", "a");
9039 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9041 reAdjustPreg (AOP (result));
9042 emitcode ("", "%05d$:", tlbl1->key + 100);
9043 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9047 freeAsmop (left, NULL, ic, TRUE);
9048 freeAsmop (result, NULL, ic, TRUE);
9051 /*-----------------------------------------------------------------*/
9052 /* genRightShift - generate code for right shifting */
9053 /*-----------------------------------------------------------------*/
9055 genRightShift (iCode * ic)
9057 operand *right, *left, *result;
9061 symbol *tlbl, *tlbl1;
9064 D(emitcode ("; genRightShift",""));
9066 /* if signed then we do it the hard way preserve the
9067 sign bit moving it inwards */
9068 letype = getSpec (operandType (IC_LEFT (ic)));
9070 if (!SPEC_USIGN (letype))
9072 genSignedRightShift (ic);
9076 /* signed & unsigned types are treated the same : i.e. the
9077 signed is NOT propagated inwards : quoting from the
9078 ANSI - standard : "for E1 >> E2, is equivalent to division
9079 by 2**E2 if unsigned or if it has a non-negative value,
9080 otherwise the result is implementation defined ", MY definition
9081 is that the sign does not get propagated */
9083 right = IC_RIGHT (ic);
9084 left = IC_LEFT (ic);
9085 result = IC_RESULT (ic);
9087 aopOp (right, ic, FALSE);
9089 /* if the shift count is known then do it
9090 as efficiently as possible */
9091 if (AOP_TYPE (right) == AOP_LIT)
9093 genRightShiftLiteral (left, right, result, ic, 0);
9097 /* shift count is unknown then we have to form
9098 a loop get the loop count in B : Note: we take
9099 only the lower order byte since shifting
9100 more that 32 bits make no sense anyway, ( the
9101 largest size of an object can be only 32 bits ) */
9104 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9105 emitcode ("inc", "b");
9106 freeAsmop (right, NULL, ic, TRUE);
9107 aopOp (left, ic, FALSE);
9108 aopOp (result, ic, FALSE);
9110 /* now move the left to the result if they are not the
9112 if (!sameRegs (AOP (left), AOP (result)) &&
9113 AOP_SIZE (result) > 1)
9116 size = AOP_SIZE (result);
9120 l = aopGet (left, offset, FALSE, TRUE);
9121 if (*l == '@' && IS_AOP_PREG (result))
9124 emitcode ("mov", "a,%s", l);
9125 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9128 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9133 tlbl = newiTempLabel (NULL);
9134 tlbl1 = newiTempLabel (NULL);
9135 size = AOP_SIZE (result);
9138 /* if it is only one byte then */
9141 l = aopGet (left, 0, FALSE, FALSE);
9143 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9144 emitcode ("", "%05d$:", tlbl->key + 100);
9146 emitcode ("rrc", "a");
9147 emitcode ("", "%05d$:", tlbl1->key + 100);
9148 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9150 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9154 reAdjustPreg (AOP (result));
9155 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9156 emitcode ("", "%05d$:", tlbl->key + 100);
9160 l = aopGet (result, offset, FALSE, FALSE);
9162 emitcode ("rrc", "a");
9163 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9165 reAdjustPreg (AOP (result));
9167 emitcode ("", "%05d$:", tlbl1->key + 100);
9168 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9172 freeAsmop (left, NULL, ic, TRUE);
9173 freeAsmop (result, NULL, ic, TRUE);
9176 /*-----------------------------------------------------------------*/
9177 /* emitPtrByteGet - emits code to get a byte into A through a */
9178 /* pointer register (R0, R1, or DPTR). The */
9179 /* original value of A can be preserved in B. */
9180 /*-----------------------------------------------------------------*/
9182 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9189 emitcode ("mov", "b,a");
9190 emitcode ("mov", "a,@%s", rname);
9195 emitcode ("mov", "b,a");
9196 emitcode ("movx", "a,@%s", rname);
9201 emitcode ("mov", "b,a");
9202 emitcode ("movx", "a,@dptr");
9207 emitcode ("mov", "b,a");
9208 emitcode ("clr", "a");
9209 emitcode ("movc", "a,@a+dptr");
9215 emitcode ("push", "b");
9216 emitcode ("push", "acc");
9218 emitcode ("lcall", "__gptrget");
9220 emitcode ("pop", "b");
9225 /*-----------------------------------------------------------------*/
9226 /* emitPtrByteSet - emits code to set a byte from src through a */
9227 /* pointer register (R0, R1, or DPTR). */
9228 /*-----------------------------------------------------------------*/
9230 emitPtrByteSet (char *rname, int p_type, char *src)
9239 emitcode ("mov", "@%s,a", rname);
9242 emitcode ("mov", "@%s,%s", rname, src);
9247 emitcode ("movx", "@%s,a", rname);
9252 emitcode ("movx", "@dptr,a");
9257 emitcode ("lcall", "__gptrput");
9262 /*-----------------------------------------------------------------*/
9263 /* genUnpackBits - generates code for unpacking bits */
9264 /*-----------------------------------------------------------------*/
9266 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9268 int offset = 0; /* result byte offset */
9269 int rsize; /* result size */
9270 int rlen = 0; /* remaining bitfield length */
9271 sym_link *etype; /* bitfield type information */
9272 int blen; /* bitfield length */
9273 int bstr; /* bitfield starting bit within byte */
9276 D(emitcode ("; genUnpackBits",""));
9278 etype = getSpec (operandType (result));
9279 rsize = getSize (operandType (result));
9280 blen = SPEC_BLEN (etype);
9281 bstr = SPEC_BSTR (etype);
9283 if (ifx && blen <= 8)
9285 emitPtrByteGet (rname, ptype, FALSE);
9288 SNPRINTF (buffer, sizeof(buffer),
9290 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9295 emitcode ("anl", "a,#0x%02x",
9296 (((unsigned char) -1) >> (8 - blen)) << bstr);
9297 genIfxJump (ifx, "a", NULL, NULL, NULL);
9303 /* If the bitfield length is less than a byte */
9306 emitPtrByteGet (rname, ptype, FALSE);
9308 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9309 if (!SPEC_USIGN (etype))
9311 /* signed bitfield */
9312 symbol *tlbl = newiTempLabel (NULL);
9314 emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
9315 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
9316 emitcode ("", "%05d$:", tlbl->key + 100);
9318 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9322 /* Bit field did not fit in a byte. Copy all
9323 but the partial byte at the end. */
9324 for (rlen=blen;rlen>=8;rlen-=8)
9326 emitPtrByteGet (rname, ptype, FALSE);
9327 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9329 emitcode ("inc", "%s", rname);
9332 /* Handle the partial byte at the end */
9335 emitPtrByteGet (rname, ptype, FALSE);
9336 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9337 if (!SPEC_USIGN (etype))
9339 /* signed bitfield */
9340 symbol *tlbl = newiTempLabel (NULL);
9342 emitcode ("jnb", "acc.%d,%05d$", rlen - 1, tlbl->key + 100);
9343 emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
9344 emitcode ("", "%05d$:", tlbl->key + 100);
9346 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9354 if (SPEC_USIGN (etype))
9358 /* signed bitfield: sign extension with 0x00 or 0xff */
9359 emitcode ("rlc", "a");
9360 emitcode ("subb", "a,acc");
9366 aopPut (result, source, offset++, isOperandVolatile (result, FALSE));
9371 /*-----------------------------------------------------------------*/
9372 /* genDataPointerGet - generates code when ptr offset is known */
9373 /*-----------------------------------------------------------------*/
9375 genDataPointerGet (operand * left,
9381 int size, offset = 0;
9383 D(emitcode ("; genDataPointerGet",""));
9385 aopOp (result, ic, TRUE);
9387 /* get the string representation of the name */
9388 l = aopGet (left, 0, FALSE, TRUE);
9389 size = AOP_SIZE (result);
9393 sprintf (buffer, "(%s + %d)", l + 1, offset);
9395 sprintf (buffer, "%s", l + 1);
9396 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9399 freeAsmop (left, NULL, ic, TRUE);
9400 freeAsmop (result, NULL, ic, TRUE);
9403 /*-----------------------------------------------------------------*/
9404 /* genNearPointerGet - emitcode for near pointer fetch */
9405 /*-----------------------------------------------------------------*/
9407 genNearPointerGet (operand * left,
9416 sym_link *rtype, *retype;
9417 sym_link *ltype = operandType (left);
9420 D(emitcode ("; genNearPointerGet",""));
9422 rtype = operandType (result);
9423 retype = getSpec (rtype);
9425 aopOp (left, ic, FALSE);
9427 /* if left is rematerialisable and
9428 result is not bitfield variable type and
9429 the left is pointer to data space i.e
9430 lower 128 bytes of space */
9431 if (AOP_TYPE (left) == AOP_IMMD &&
9432 !IS_BITFIELD (retype) &&
9433 DCL_TYPE (ltype) == POINTER)
9435 genDataPointerGet (left, result, ic);
9439 /* if the value is already in a pointer register
9440 then don't need anything more */
9441 if (!AOP_INPREG (AOP (left)))
9443 if (IS_AOP_PREG (left))
9445 // Aha, it is a pointer, just in disguise.
9446 rname = aopGet (left, 0, FALSE, FALSE);
9449 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9450 __FILE__, __LINE__);
9455 emitcode ("mov", "a%s,%s", rname + 1, rname);
9456 rname++; // skip the '@'.
9461 /* otherwise get a free pointer register */
9463 preg = getFreePtr (ic, &aop, FALSE);
9464 emitcode ("mov", "%s,%s",
9466 aopGet (left, 0, FALSE, TRUE));
9471 rname = aopGet (left, 0, FALSE, FALSE);
9473 //aopOp (result, ic, FALSE);
9474 aopOp (result, ic, result?TRUE:FALSE);
9476 /* if bitfield then unpack the bits */
9477 if (IS_BITFIELD (retype))
9478 genUnpackBits (result, rname, POINTER, ifx);
9481 /* we have can just get the values */
9482 int size = AOP_SIZE (result);
9487 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9490 emitcode ("mov", "a,@%s", rname);
9492 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9496 sprintf (buffer, "@%s", rname);
9497 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9501 emitcode ("inc", "%s", rname);
9505 /* now some housekeeping stuff */
9506 if (aop) /* we had to allocate for this iCode */
9508 if (pi) { /* post increment present */
9509 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9511 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9515 /* we did not allocate which means left
9516 already in a pointer register, then
9517 if size > 0 && this could be used again
9518 we have to point it back to where it
9520 if ((AOP_SIZE (result) > 1 &&
9521 !OP_SYMBOL (left)->remat &&
9522 (OP_SYMBOL (left)->liveTo > ic->seq ||
9526 int size = AOP_SIZE (result) - 1;
9528 emitcode ("dec", "%s", rname);
9532 if (ifx && !ifx->generated)
9534 genIfxJump (ifx, "a", left, NULL, result);
9538 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9539 freeAsmop (left, NULL, ic, TRUE);
9540 if (pi) pi->generated = 1;
9543 /*-----------------------------------------------------------------*/
9544 /* genPagedPointerGet - emitcode for paged pointer fetch */
9545 /*-----------------------------------------------------------------*/
9547 genPagedPointerGet (operand * left,
9556 sym_link *rtype, *retype;
9558 D(emitcode ("; genPagedPointerGet",""));
9560 rtype = operandType (result);
9561 retype = getSpec (rtype);
9563 aopOp (left, ic, FALSE);
9565 /* if the value is already in a pointer register
9566 then don't need anything more */
9567 if (!AOP_INPREG (AOP (left)))
9569 /* otherwise get a free pointer register */
9571 preg = getFreePtr (ic, &aop, FALSE);
9572 emitcode ("mov", "%s,%s",
9574 aopGet (left, 0, FALSE, TRUE));
9578 rname = aopGet (left, 0, FALSE, FALSE);
9580 aopOp (result, ic, FALSE);
9582 /* if bitfield then unpack the bits */
9583 if (IS_BITFIELD (retype))
9584 genUnpackBits (result, rname, PPOINTER, ifx);
9587 /* we have can just get the values */
9588 int size = AOP_SIZE (result);
9594 emitcode ("movx", "a,@%s", rname);
9596 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9601 emitcode ("inc", "%s", rname);
9605 /* now some housekeeping stuff */
9606 if (aop) /* we had to allocate for this iCode */
9608 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9609 freeAsmop (NULL, aop, ic, TRUE);
9613 /* we did not allocate which means left
9614 already in a pointer register, then
9615 if size > 0 && this could be used again
9616 we have to point it back to where it
9618 if ((AOP_SIZE (result) > 1 &&
9619 !OP_SYMBOL (left)->remat &&
9620 (OP_SYMBOL (left)->liveTo > ic->seq ||
9624 int size = AOP_SIZE (result) - 1;
9626 emitcode ("dec", "%s", rname);
9630 if (ifx && !ifx->generated)
9632 genIfxJump (ifx, "a", left, NULL, result);
9636 freeAsmop (left, NULL, ic, TRUE);
9637 freeAsmop (result, NULL, ic, TRUE);
9638 if (pi) pi->generated = 1;
9642 /*--------------------------------------------------------------------*/
9643 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9644 /*--------------------------------------------------------------------*/
9646 loadDptrFromOperand (operand *op, bool loadBToo)
9648 if (AOP_TYPE (op) != AOP_STR)
9650 /* if this is rematerializable */
9651 if (AOP_TYPE (op) == AOP_IMMD)
9653 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9656 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9657 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9660 wassertl(FALSE, "need pointerCode");
9661 emitcode ("", "; mov b,???");
9662 /* genPointerGet and genPointerSet originally did different
9663 ** things for this case. Both seem wrong.
9664 ** from genPointerGet:
9665 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9666 ** from genPointerSet:
9667 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9672 else if (AOP_TYPE (op) == AOP_DPTR)
9676 MOVA (aopGet (op, 0, FALSE, FALSE));
9677 emitcode ("push", "acc");
9678 MOVA (aopGet (op, 1, FALSE, FALSE));
9679 emitcode ("push", "acc");
9680 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9681 emitcode ("pop", "dph");
9682 emitcode ("pop", "dpl");
9686 MOVA (aopGet (op, 0, FALSE, FALSE));
9687 emitcode ("push", "acc");
9688 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9689 emitcode ("pop", "dpl");
9693 { /* we need to get it byte by byte */
9694 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9695 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9697 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9702 /*-----------------------------------------------------------------*/
9703 /* genFarPointerGet - gget value from far space */
9704 /*-----------------------------------------------------------------*/
9706 genFarPointerGet (operand * left,
9707 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9710 sym_link *retype = getSpec (operandType (result));
9712 D(emitcode ("; genFarPointerGet",""));
9714 aopOp (left, ic, FALSE);
9715 loadDptrFromOperand (left, FALSE);
9717 /* so dptr now contains the address */
9718 aopOp (result, ic, FALSE);
9720 /* if bit then unpack */
9721 if (IS_BITFIELD (retype))
9722 genUnpackBits (result, "dptr", FPOINTER, ifx);
9725 size = AOP_SIZE (result);
9730 emitcode ("movx", "a,@dptr");
9732 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9734 emitcode ("inc", "dptr");
9738 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9740 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9741 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9745 if (ifx && !ifx->generated)
9747 genIfxJump (ifx, "a", left, NULL, result);
9750 freeAsmop (left, NULL, ic, TRUE);
9751 freeAsmop (result, NULL, ic, TRUE);
9754 /*-----------------------------------------------------------------*/
9755 /* genCodePointerGet - gget value from code space */
9756 /*-----------------------------------------------------------------*/
9758 genCodePointerGet (operand * left,
9759 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9762 sym_link *retype = getSpec (operandType (result));
9764 D(emitcode ("; genCodePointerGet",""));
9766 aopOp (left, ic, FALSE);
9767 loadDptrFromOperand (left, FALSE);
9769 /* so dptr now contains the address */
9770 aopOp (result, ic, FALSE);
9772 /* if bit then unpack */
9773 if (IS_BITFIELD (retype))
9774 genUnpackBits (result, "dptr", CPOINTER, ifx);
9777 size = AOP_SIZE (result);
9784 emitcode ("clr", "a");
9785 emitcode ("movc", "a,@a+dptr");
9787 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9788 emitcode ("inc", "dptr");
9792 emitcode ("mov", "a,#0x%02x", offset);
9793 emitcode ("movc", "a,@a+dptr");
9795 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9800 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9802 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9803 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9807 if (ifx && !ifx->generated)
9809 genIfxJump (ifx, "a", left, NULL, result);
9812 freeAsmop (left, NULL, ic, TRUE);
9813 freeAsmop (result, NULL, ic, TRUE);
9816 /*-----------------------------------------------------------------*/
9817 /* genGenPointerGet - gget value from generic pointer space */
9818 /*-----------------------------------------------------------------*/
9820 genGenPointerGet (operand * left,
9821 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9824 sym_link *retype = getSpec (operandType (result));
9826 D(emitcode ("; genGenPointerGet",""));
9828 aopOp (left, ic, FALSE);
9829 loadDptrFromOperand (left, TRUE);
9831 /* so dptr know contains the address */
9832 aopOp (result, ic, FALSE);
9834 /* if bit then unpack */
9835 if (IS_BITFIELD (retype))
9836 genUnpackBits (result, "dptr", GPOINTER, ifx);
9839 size = AOP_SIZE (result);
9844 emitcode ("lcall", "__gptrget");
9846 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9848 emitcode ("inc", "dptr");
9852 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9854 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9855 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9859 if (ifx && !ifx->generated)
9861 genIfxJump (ifx, "a", left, NULL, result);
9865 freeAsmop (left, NULL, ic, TRUE);
9866 freeAsmop (result, NULL, ic, TRUE);
9869 /*-----------------------------------------------------------------*/
9870 /* genPointerGet - generate code for pointer get */
9871 /*-----------------------------------------------------------------*/
9873 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9875 operand *left, *result;
9876 sym_link *type, *etype;
9879 D(emitcode ("; genPointerGet",""));
9881 left = IC_LEFT (ic);
9882 result = IC_RESULT (ic);
9884 if (getSize (operandType (result))>1)
9887 /* depending on the type of pointer we need to
9888 move it to the correct pointer register */
9889 type = operandType (left);
9890 etype = getSpec (type);
9891 /* if left is of type of pointer then it is simple */
9892 if (IS_PTR (type) && !IS_FUNC (type->next))
9893 p_type = DCL_TYPE (type);
9896 /* we have to go by the storage class */
9897 p_type = PTR_TYPE (SPEC_OCLS (etype));
9900 /* special case when cast remat */
9901 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9902 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9903 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9904 type = operandType (left);
9905 p_type = DCL_TYPE (type);
9907 /* now that we have the pointer type we assign
9908 the pointer values */
9914 genNearPointerGet (left, result, ic, pi, ifx);
9918 genPagedPointerGet (left, result, ic, pi, ifx);
9922 genFarPointerGet (left, result, ic, pi, ifx);
9926 genCodePointerGet (left, result, ic, pi, ifx);
9930 genGenPointerGet (left, result, ic, pi, ifx);
9938 /*-----------------------------------------------------------------*/
9939 /* genPackBits - generates code for packed bit storage */
9940 /*-----------------------------------------------------------------*/
9942 genPackBits (sym_link * etype,
9944 char *rname, int p_type)
9946 int offset = 0; /* source byte offset */
9947 int rlen = 0; /* remaining bitfield length */
9948 int blen; /* bitfield length */
9949 int bstr; /* bitfield starting bit within byte */
9950 int litval; /* source literal value (if AOP_LIT) */
9951 unsigned char mask; /* bitmask within current byte */
9953 D(emitcode ("; genPackBits",""));
9955 blen = SPEC_BLEN (etype);
9956 bstr = SPEC_BSTR (etype);
9958 /* If the bitfield length is less than a byte */
9961 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9962 (unsigned char) (0xFF >> (8 - bstr)));
9964 if (AOP_TYPE (right) == AOP_LIT)
9966 /* Case with a bitfield length <8 and literal source
9968 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9970 litval &= (~mask) & 0xff;
9971 emitPtrByteGet (rname, p_type, FALSE);
9972 if ((mask|litval)!=0xff)
9973 emitcode ("anl","a,#0x%02x", mask);
9975 emitcode ("orl","a,#0x%02x", litval);
9979 if ((blen==1) && (p_type!=GPOINTER))
9981 /* Case with a bitfield length == 1 and no generic pointer
9983 if (AOP_TYPE (right) == AOP_CRY)
9984 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9987 MOVA (aopGet (right, 0, FALSE, FALSE));
9988 emitcode ("rrc","a");
9990 emitPtrByteGet (rname, p_type, FALSE);
9991 emitcode ("mov","acc.%d,c",bstr);
9996 /* Case with a bitfield length < 8 and arbitrary source
9998 MOVA (aopGet (right, 0, FALSE, FALSE));
9999 /* shift and mask source value */
10001 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10003 pushedB = pushB ();
10004 /* transfer A to B and get next byte */
10005 emitPtrByteGet (rname, p_type, TRUE);
10007 emitcode ("anl", "a,#0x%02x", mask);
10008 emitcode ("orl", "a,b");
10009 if (p_type == GPOINTER)
10010 emitcode ("pop", "b");
10016 emitPtrByteSet (rname, p_type, "a");
10020 /* Bit length is greater than 7 bits. In this case, copy */
10021 /* all except the partial byte at the end */
10022 for (rlen=blen;rlen>=8;rlen-=8)
10024 emitPtrByteSet (rname, p_type,
10025 aopGet (right, offset++, FALSE, TRUE) );
10027 emitcode ("inc", "%s", rname);
10030 /* If there was a partial byte at the end */
10033 mask = (((unsigned char) -1 << rlen) & 0xff);
10035 if (AOP_TYPE (right) == AOP_LIT)
10037 /* Case with partial byte and literal source
10039 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
10040 litval >>= (blen-rlen);
10041 litval &= (~mask) & 0xff;
10042 emitPtrByteGet (rname, p_type, FALSE);
10043 if ((mask|litval)!=0xff)
10044 emitcode ("anl","a,#0x%02x", mask);
10046 emitcode ("orl","a,#0x%02x", litval);
10051 /* Case with partial byte and arbitrary source
10053 MOVA (aopGet (right, offset++, FALSE, FALSE));
10054 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
10056 pushedB = pushB ();
10057 /* transfer A to B and get next byte */
10058 emitPtrByteGet (rname, p_type, TRUE);
10060 emitcode ("anl", "a,#0x%02x", mask);
10061 emitcode ("orl", "a,b");
10062 if (p_type == GPOINTER)
10063 emitcode ("pop", "b");
10067 emitPtrByteSet (rname, p_type, "a");
10073 /*-----------------------------------------------------------------*/
10074 /* genDataPointerSet - remat pointer to data space */
10075 /*-----------------------------------------------------------------*/
10077 genDataPointerSet (operand * right,
10081 int size, offset = 0;
10082 char *l, buffer[256];
10084 D(emitcode ("; genDataPointerSet",""));
10086 aopOp (right, ic, FALSE);
10088 l = aopGet (result, 0, FALSE, TRUE);
10089 size = AOP_SIZE (right);
10093 sprintf (buffer, "(%s + %d)", l + 1, offset);
10095 sprintf (buffer, "%s", l + 1);
10096 emitcode ("mov", "%s,%s", buffer,
10097 aopGet (right, offset++, FALSE, FALSE));
10100 freeAsmop (right, NULL, ic, TRUE);
10101 freeAsmop (result, NULL, ic, TRUE);
10104 /*-----------------------------------------------------------------*/
10105 /* genNearPointerSet - emitcode for near pointer put */
10106 /*-----------------------------------------------------------------*/
10108 genNearPointerSet (operand * right,
10116 sym_link *retype, *letype;
10117 sym_link *ptype = operandType (result);
10119 D(emitcode ("; genNearPointerSet",""));
10121 retype = getSpec (operandType (right));
10122 letype = getSpec (ptype);
10123 aopOp (result, ic, FALSE);
10125 /* if the result is rematerializable &
10126 in data space & not a bit variable */
10127 if (AOP_TYPE (result) == AOP_IMMD &&
10128 DCL_TYPE (ptype) == POINTER &&
10129 !IS_BITVAR (retype) &&
10130 !IS_BITVAR (letype))
10132 genDataPointerSet (right, result, ic);
10136 /* if the value is already in a pointer register
10137 then don't need anything more */
10138 if (!AOP_INPREG (AOP (result)))
10141 //AOP_TYPE (result) == AOP_STK
10142 IS_AOP_PREG(result)
10145 // Aha, it is a pointer, just in disguise.
10146 rname = aopGet (result, 0, FALSE, FALSE);
10149 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10150 __FILE__, __LINE__);
10155 emitcode ("mov", "a%s,%s", rname + 1, rname);
10156 rname++; // skip the '@'.
10161 /* otherwise get a free pointer register */
10162 aop = newAsmop (0);
10163 preg = getFreePtr (ic, &aop, FALSE);
10164 emitcode ("mov", "%s,%s",
10166 aopGet (result, 0, FALSE, TRUE));
10167 rname = preg->name;
10172 rname = aopGet (result, 0, FALSE, FALSE);
10175 aopOp (right, ic, FALSE);
10177 /* if bitfield then unpack the bits */
10178 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10179 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10182 /* we have can just get the values */
10183 int size = AOP_SIZE (right);
10188 l = aopGet (right, offset, FALSE, TRUE);
10192 emitcode ("mov", "@%s,a", rname);
10195 emitcode ("mov", "@%s,%s", rname, l);
10197 emitcode ("inc", "%s", rname);
10202 /* now some housekeeping stuff */
10203 if (aop) /* we had to allocate for this iCode */
10206 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10207 freeAsmop (NULL, aop, ic, TRUE);
10211 /* we did not allocate which means left
10212 already in a pointer register, then
10213 if size > 0 && this could be used again
10214 we have to point it back to where it
10216 if ((AOP_SIZE (right) > 1 &&
10217 !OP_SYMBOL (result)->remat &&
10218 (OP_SYMBOL (result)->liveTo > ic->seq ||
10222 int size = AOP_SIZE (right) - 1;
10224 emitcode ("dec", "%s", rname);
10229 if (pi) pi->generated = 1;
10230 freeAsmop (result, NULL, ic, TRUE);
10231 freeAsmop (right, NULL, ic, TRUE);
10234 /*-----------------------------------------------------------------*/
10235 /* genPagedPointerSet - emitcode for Paged pointer put */
10236 /*-----------------------------------------------------------------*/
10238 genPagedPointerSet (operand * right,
10246 sym_link *retype, *letype;
10248 D(emitcode ("; genPagedPointerSet",""));
10250 retype = getSpec (operandType (right));
10251 letype = getSpec (operandType (result));
10253 aopOp (result, ic, FALSE);
10255 /* if the value is already in a pointer register
10256 then don't need anything more */
10257 if (!AOP_INPREG (AOP (result)))
10259 /* otherwise get a free pointer register */
10260 aop = newAsmop (0);
10261 preg = getFreePtr (ic, &aop, FALSE);
10262 emitcode ("mov", "%s,%s",
10264 aopGet (result, 0, FALSE, TRUE));
10265 rname = preg->name;
10268 rname = aopGet (result, 0, FALSE, FALSE);
10270 aopOp (right, ic, FALSE);
10272 /* if bitfield then unpack the bits */
10273 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10274 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10277 /* we have can just get the values */
10278 int size = AOP_SIZE (right);
10283 l = aopGet (right, offset, FALSE, TRUE);
10286 emitcode ("movx", "@%s,a", rname);
10289 emitcode ("inc", "%s", rname);
10295 /* now some housekeeping stuff */
10296 if (aop) /* we had to allocate for this iCode */
10299 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10300 freeAsmop (NULL, aop, ic, TRUE);
10304 /* we did not allocate which means left
10305 already in a pointer register, then
10306 if size > 0 && this could be used again
10307 we have to point it back to where it
10309 if (AOP_SIZE (right) > 1 &&
10310 !OP_SYMBOL (result)->remat &&
10311 (OP_SYMBOL (result)->liveTo > ic->seq ||
10314 int size = AOP_SIZE (right) - 1;
10316 emitcode ("dec", "%s", rname);
10321 if (pi) pi->generated = 1;
10322 freeAsmop (result, NULL, ic, TRUE);
10323 freeAsmop (right, NULL, ic, TRUE);
10328 /*-----------------------------------------------------------------*/
10329 /* genFarPointerSet - set value from far space */
10330 /*-----------------------------------------------------------------*/
10332 genFarPointerSet (operand * right,
10333 operand * result, iCode * ic, iCode * pi)
10336 sym_link *retype = getSpec (operandType (right));
10337 sym_link *letype = getSpec (operandType (result));
10339 D(emitcode ("; genFarPointerSet",""));
10341 aopOp (result, ic, FALSE);
10342 loadDptrFromOperand (result, FALSE);
10344 /* so dptr know contains the address */
10345 aopOp (right, ic, FALSE);
10347 /* if bit then unpack */
10348 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10349 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10352 size = AOP_SIZE (right);
10357 char *l = aopGet (right, offset++, FALSE, FALSE);
10359 emitcode ("movx", "@dptr,a");
10361 emitcode ("inc", "dptr");
10364 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10365 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10366 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10369 freeAsmop (result, NULL, ic, TRUE);
10370 freeAsmop (right, NULL, ic, TRUE);
10373 /*-----------------------------------------------------------------*/
10374 /* genGenPointerSet - set value from generic pointer space */
10375 /*-----------------------------------------------------------------*/
10377 genGenPointerSet (operand * right,
10378 operand * result, iCode * ic, iCode * pi)
10381 sym_link *retype = getSpec (operandType (right));
10382 sym_link *letype = getSpec (operandType (result));
10384 D(emitcode ("; genGenPointerSet",""));
10386 aopOp (result, ic, FALSE);
10387 loadDptrFromOperand (result, TRUE);
10389 /* so dptr know contains the address */
10390 aopOp (right, ic, FALSE);
10392 /* if bit then unpack */
10393 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10394 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10397 size = AOP_SIZE (right);
10402 char *l = aopGet (right, offset++, FALSE, FALSE);
10404 emitcode ("lcall", "__gptrput");
10406 emitcode ("inc", "dptr");
10410 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10411 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10412 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10415 freeAsmop (result, NULL, ic, TRUE);
10416 freeAsmop (right, NULL, ic, TRUE);
10419 /*-----------------------------------------------------------------*/
10420 /* genPointerSet - stores the value into a pointer location */
10421 /*-----------------------------------------------------------------*/
10423 genPointerSet (iCode * ic, iCode *pi)
10425 operand *right, *result;
10426 sym_link *type, *etype;
10429 D(emitcode ("; genPointerSet",""));
10431 right = IC_RIGHT (ic);
10432 result = IC_RESULT (ic);
10434 /* depending on the type of pointer we need to
10435 move it to the correct pointer register */
10436 type = operandType (result);
10437 etype = getSpec (type);
10438 /* if left is of type of pointer then it is simple */
10439 if (IS_PTR (type) && !IS_FUNC (type->next))
10441 p_type = DCL_TYPE (type);
10445 /* we have to go by the storage class */
10446 p_type = PTR_TYPE (SPEC_OCLS (etype));
10449 /* special case when cast remat */
10450 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10451 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10452 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10453 type = operandType (result);
10454 p_type = DCL_TYPE (type);
10456 /* now that we have the pointer type we assign
10457 the pointer values */
10463 genNearPointerSet (right, result, ic, pi);
10467 genPagedPointerSet (right, result, ic, pi);
10471 genFarPointerSet (right, result, ic, pi);
10475 genGenPointerSet (right, result, ic, pi);
10479 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10480 "genPointerSet: illegal pointer type");
10485 /*-----------------------------------------------------------------*/
10486 /* genIfx - generate code for Ifx statement */
10487 /*-----------------------------------------------------------------*/
10489 genIfx (iCode * ic, iCode * popIc)
10491 operand *cond = IC_COND (ic);
10495 D(emitcode ("; genIfx",""));
10497 aopOp (cond, ic, FALSE);
10499 /* get the value into acc */
10500 if (AOP_TYPE (cond) != AOP_CRY)
10505 if (AOP(cond)->aopu.aop_dir)
10506 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10508 /* the result is now in the accumulator or a directly addressable bit */
10509 freeAsmop (cond, NULL, ic, TRUE);
10511 /* if there was something to be popped then do it */
10515 /* if the condition is a bit variable */
10517 genIfxJump(ic, dup, NULL, NULL, NULL);
10518 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10519 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10520 else if (isbit && !IS_ITEMP (cond))
10521 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10523 genIfxJump (ic, "a", NULL, NULL, NULL);
10528 /*-----------------------------------------------------------------*/
10529 /* genAddrOf - generates code for address of */
10530 /*-----------------------------------------------------------------*/
10532 genAddrOf (iCode * ic)
10534 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10537 D(emitcode ("; genAddrOf",""));
10539 aopOp (IC_RESULT (ic), ic, FALSE);
10541 /* if the operand is on the stack then we
10542 need to get the stack offset of this
10546 /* if it has an offset then we need to compute
10550 emitcode ("mov", "a,%s", SYM_BP (sym));
10551 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10552 ((char) (sym->stack - _G.nRegsSaved)) :
10553 ((char) sym->stack)) & 0xff);
10554 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10558 /* we can just move _bp */
10559 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10561 /* fill the result with zero */
10562 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10567 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10573 /* object not on stack then we need the name */
10574 size = AOP_SIZE (IC_RESULT (ic));
10579 char s[SDCC_NAME_MAX];
10581 sprintf (s, "#(%s >> %d)",
10585 sprintf (s, "#%s", sym->rname);
10586 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10590 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10594 /*-----------------------------------------------------------------*/
10595 /* genFarFarAssign - assignment when both are in far space */
10596 /*-----------------------------------------------------------------*/
10598 genFarFarAssign (operand * result, operand * right, iCode * ic)
10600 int size = AOP_SIZE (right);
10604 D(emitcode ("; genFarFarAssign",""));
10606 /* first push the right side on to the stack */
10609 l = aopGet (right, offset++, FALSE, FALSE);
10611 emitcode ("push", "acc");
10614 freeAsmop (right, NULL, ic, FALSE);
10615 /* now assign DPTR to result */
10616 aopOp (result, ic, FALSE);
10617 size = AOP_SIZE (result);
10620 emitcode ("pop", "acc");
10621 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10623 freeAsmop (result, NULL, ic, FALSE);
10627 /*-----------------------------------------------------------------*/
10628 /* genAssign - generate code for assignment */
10629 /*-----------------------------------------------------------------*/
10631 genAssign (iCode * ic)
10633 operand *result, *right;
10635 unsigned long lit = 0L;
10637 D(emitcode("; genAssign",""));
10639 result = IC_RESULT (ic);
10640 right = IC_RIGHT (ic);
10642 /* if they are the same */
10643 if (operandsEqu (result, right) &&
10644 !isOperandVolatile (result, FALSE) &&
10645 !isOperandVolatile (right, FALSE))
10648 aopOp (right, ic, FALSE);
10650 /* special case both in far space */
10651 if (AOP_TYPE (right) == AOP_DPTR &&
10652 IS_TRUE_SYMOP (result) &&
10653 isOperandInFarSpace (result))
10656 genFarFarAssign (result, right, ic);
10660 aopOp (result, ic, TRUE);
10662 /* if they are the same registers */
10663 if (sameRegs (AOP (right), AOP (result)) &&
10664 !isOperandVolatile (result, FALSE) &&
10665 !isOperandVolatile (right, FALSE))
10668 /* if the result is a bit */
10669 if (AOP_TYPE (result) == AOP_CRY)
10672 /* if the right size is a literal then
10673 we know what the value is */
10674 if (AOP_TYPE (right) == AOP_LIT)
10676 if (((int) operandLitValue (right)))
10677 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10679 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10683 /* the right is also a bit variable */
10684 if (AOP_TYPE (right) == AOP_CRY)
10686 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10687 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10691 /* we need to or */
10693 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10697 /* bit variables done */
10699 size = AOP_SIZE (result);
10701 if (AOP_TYPE (right) == AOP_LIT)
10702 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10704 (AOP_TYPE (result) != AOP_REG) &&
10705 (AOP_TYPE (right) == AOP_LIT) &&
10706 !IS_FLOAT (operandType (right)) &&
10709 while ((size) && (lit))
10712 aopGet (right, offset, FALSE, FALSE),
10714 isOperandVolatile (result, FALSE));
10719 emitcode ("clr", "a");
10722 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10731 aopGet (right, offset, FALSE, FALSE),
10733 isOperandVolatile (result, FALSE));
10739 freeAsmop (right, NULL, ic, TRUE);
10740 freeAsmop (result, NULL, ic, TRUE);
10743 /*-----------------------------------------------------------------*/
10744 /* genJumpTab - generates code for jump table */
10745 /*-----------------------------------------------------------------*/
10747 genJumpTab (iCode * ic)
10749 symbol *jtab,*jtablo,*jtabhi;
10751 unsigned int count;
10753 D(emitcode ("; genJumpTab",""));
10755 count = elementsInSet( IC_JTLABELS (ic) );
10759 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10760 if the switch argument is in a register.
10761 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10762 /* (MB) What if peephole converts ljmp to sjmp or ret ???
10763 How will multiply by three be updated ???*/
10764 aopOp (IC_JTCOND (ic), ic, FALSE);
10765 /* get the condition into accumulator */
10766 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10768 /* multiply by three */
10769 emitcode ("add", "a,acc");
10770 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10771 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10773 jtab = newiTempLabel (NULL);
10774 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10775 emitcode ("jmp", "@a+dptr");
10776 emitcode ("", "%05d$:", jtab->key + 100);
10777 /* now generate the jump labels */
10778 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10779 jtab = setNextItem (IC_JTLABELS (ic)))
10780 emitcode ("ljmp", "%05d$", jtab->key + 100);
10784 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10785 if the switch argument is in a register.
10786 For n>6 this algorithm may be more compact */
10787 jtablo = newiTempLabel (NULL);
10788 jtabhi = newiTempLabel (NULL);
10790 /* get the condition into accumulator.
10791 Using b as temporary storage, if register push/pop is needed */
10792 aopOp (IC_JTCOND (ic), ic, FALSE);
10793 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10794 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10795 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10797 // (MB) what if B is in use???
10798 wassertl(!BINUSE, "B was in use");
10799 emitcode ("mov", "b,%s", l);
10802 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10806 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10807 emitcode ("movc", "a,@a+pc");
10808 emitcode ("push", "acc");
10811 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10812 emitcode ("movc", "a,@a+pc");
10813 emitcode ("push", "acc");
10817 /* this scales up to n<=255, but needs two more bytes
10818 and changes dptr */
10819 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10820 emitcode ("movc", "a,@a+dptr");
10821 emitcode ("push", "acc");
10824 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10825 emitcode ("movc", "a,@a+dptr");
10826 emitcode ("push", "acc");
10829 emitcode ("ret", "");
10831 /* now generate jump table, LSB */
10832 emitcode ("", "%05d$:", jtablo->key + 100);
10833 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10834 jtab = setNextItem (IC_JTLABELS (ic)))
10835 emitcode (".db", "%05d$", jtab->key + 100);
10837 /* now generate jump table, MSB */
10838 emitcode ("", "%05d$:", jtabhi->key + 100);
10839 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10840 jtab = setNextItem (IC_JTLABELS (ic)))
10841 emitcode (".db", "%05d$>>8", jtab->key + 100);
10845 /*-----------------------------------------------------------------*/
10846 /* genCast - gen code for casting */
10847 /*-----------------------------------------------------------------*/
10849 genCast (iCode * ic)
10851 operand *result = IC_RESULT (ic);
10852 sym_link *ctype = operandType (IC_LEFT (ic));
10853 sym_link *rtype = operandType (IC_RIGHT (ic));
10854 operand *right = IC_RIGHT (ic);
10857 D(emitcode("; genCast",""));
10859 /* if they are equivalent then do nothing */
10860 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10863 aopOp (right, ic, FALSE);
10864 aopOp (result, ic, FALSE);
10866 /* if the result is a bit (and not a bitfield) */
10867 // if (AOP_TYPE (result) == AOP_CRY)
10868 if (IS_BIT (OP_SYMBOL (result)->type))
10869 /* not for bitfields */
10871 /* if the right size is a literal then
10872 we know what the value is */
10873 if (AOP_TYPE (right) == AOP_LIT)
10875 if (((int) operandLitValue (right)))
10876 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10878 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10883 /* the right is also a bit variable */
10884 if (AOP_TYPE (right) == AOP_CRY)
10886 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10887 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10891 /* we need to or */
10893 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10898 /* if they are the same size : or less */
10899 if (AOP_SIZE (result) <= AOP_SIZE (right))
10902 /* if they are in the same place */
10903 if (sameRegs (AOP (right), AOP (result)))
10906 /* if they in different places then copy */
10907 size = AOP_SIZE (result);
10912 aopGet (right, offset, FALSE, FALSE),
10914 isOperandVolatile (result, FALSE));
10921 /* if the result is of type pointer */
10922 if (IS_PTR (ctype))
10926 sym_link *type = operandType (right);
10927 sym_link *etype = getSpec (type);
10929 /* pointer to generic pointer */
10930 if (IS_GENPTR (ctype))
10933 p_type = DCL_TYPE (type);
10936 if (SPEC_SCLS(etype)==S_REGISTER) {
10937 // let's assume it is a generic pointer
10940 /* we have to go by the storage class */
10941 p_type = PTR_TYPE (SPEC_OCLS (etype));
10945 /* the first two bytes are known */
10946 size = GPTRSIZE - 1;
10951 aopGet (right, offset, FALSE, FALSE),
10953 isOperandVolatile (result, FALSE));
10956 /* the last byte depending on type */
10958 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10963 // pointerTypeToGPByte will have bitched.
10967 sprintf(gpValStr, "#0x%x", gpVal);
10968 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10973 /* just copy the pointers */
10974 size = AOP_SIZE (result);
10979 aopGet (right, offset, FALSE, FALSE),
10981 isOperandVolatile (result, FALSE));
10987 /* so we now know that the size of destination is greater
10988 than the size of the source */
10989 /* we move to result for the size of source */
10990 size = AOP_SIZE (right);
10995 aopGet (right, offset, FALSE, FALSE),
10997 isOperandVolatile (result, FALSE));
11001 /* now depending on the sign of the source && destination */
11002 size = AOP_SIZE (result) - AOP_SIZE (right);
11003 /* if unsigned or not an integral type */
11004 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
11007 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
11011 /* we need to extend the sign :{ */
11012 char *l = aopGet (right, AOP_SIZE (right) - 1,
11015 emitcode ("rlc", "a");
11016 emitcode ("subb", "a,acc");
11018 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
11021 /* we are done hurray !!!! */
11024 freeAsmop (right, NULL, ic, TRUE);
11025 freeAsmop (result, NULL, ic, TRUE);
11029 /*-----------------------------------------------------------------*/
11030 /* genDjnz - generate decrement & jump if not zero instrucion */
11031 /*-----------------------------------------------------------------*/
11033 genDjnz (iCode * ic, iCode * ifx)
11035 symbol *lbl, *lbl1;
11039 D(emitcode ("; genDjnz",""));
11041 /* if the if condition has a false label
11042 then we cannot save */
11043 if (IC_FALSE (ifx))
11046 /* if the minus is not of the form
11048 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11049 !IS_OP_LITERAL (IC_RIGHT (ic)))
11052 if (operandLitValue (IC_RIGHT (ic)) != 1)
11055 /* if the size of this greater than one then no
11057 if (getSize (operandType (IC_RESULT (ic))) > 1)
11060 /* otherwise we can save BIG */
11061 lbl = newiTempLabel (NULL);
11062 lbl1 = newiTempLabel (NULL);
11064 aopOp (IC_RESULT (ic), ic, FALSE);
11066 if (AOP_NEEDSACC(IC_RESULT(ic)))
11068 /* If the result is accessed indirectly via
11069 * the accumulator, we must explicitly write
11070 * it back after the decrement.
11072 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11074 if (strcmp(rByte, "a"))
11076 /* Something is hopelessly wrong */
11077 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11078 __FILE__, __LINE__);
11079 /* We can just give up; the generated code will be inefficient,
11080 * but what the hey.
11082 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11085 emitcode ("dec", "%s", rByte);
11086 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
11087 emitcode ("jnz", "%05d$", lbl->key + 100);
11089 else if (IS_AOP_PREG (IC_RESULT (ic)))
11091 emitcode ("dec", "%s",
11092 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11093 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11094 emitcode ("jnz", "%05d$", lbl->key + 100);
11098 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11101 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11102 emitcode ("", "%05d$:", lbl->key + 100);
11103 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11104 emitcode ("", "%05d$:", lbl1->key + 100);
11106 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11107 ifx->generated = 1;
11111 /*-----------------------------------------------------------------*/
11112 /* genReceive - generate code for a receive iCode */
11113 /*-----------------------------------------------------------------*/
11115 genReceive (iCode * ic)
11117 int size = getSize (operandType (IC_RESULT (ic)));
11120 D(emitcode ("; genReceive",""));
11122 if (ic->argreg == 1)
11123 { /* first parameter */
11124 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11125 isOperandInPagedSpace (IC_RESULT (ic))) &&
11126 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11127 IS_TRUE_SYMOP (IC_RESULT (ic))))
11130 int receivingA = 0;
11133 for (offset = 0; offset<size; offset++)
11134 if (!strcmp (fReturn[offset], "a"))
11139 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11141 for (offset = size-1; offset>0; offset--)
11142 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11143 emitcode("mov","a,%s", fReturn[0]);
11145 aopOp (IC_RESULT (ic), ic, FALSE);
11147 aopPut (IC_RESULT (ic), "a", offset,
11148 isOperandVolatile (IC_RESULT (ic), FALSE));
11149 for (offset = 1; offset<size; offset++)
11150 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
11151 isOperandVolatile (IC_RESULT (ic), FALSE));
11157 if (getTempRegs(tempRegs, size, ic))
11159 for (offset = 0; offset<size; offset++)
11160 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11161 aopOp (IC_RESULT (ic), ic, FALSE);
11162 for (offset = 0; offset<size; offset++)
11163 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
11164 isOperandVolatile (IC_RESULT (ic), FALSE));
11169 offset = fReturnSizeMCS51 - size;
11172 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11173 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11176 aopOp (IC_RESULT (ic), ic, FALSE);
11177 size = AOP_SIZE (IC_RESULT (ic));
11181 emitcode ("pop", "acc");
11182 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11188 aopOp (IC_RESULT (ic), ic, FALSE);
11190 assignResultValue (IC_RESULT (ic), NULL);
11193 else if (ic->argreg > 12)
11194 { /* bit parameters */
11195 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11197 aopOp (IC_RESULT (ic), ic, FALSE);
11198 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11199 outBitC(IC_RESULT (ic));
11203 { /* other parameters */
11205 aopOp (IC_RESULT (ic), ic, FALSE);
11206 rb1off = ic->argreg;
11209 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11214 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11217 /*-----------------------------------------------------------------*/
11218 /* genDummyRead - generate code for dummy read of volatiles */
11219 /*-----------------------------------------------------------------*/
11221 genDummyRead (iCode * ic)
11226 D(emitcode("; genDummyRead",""));
11228 op = IC_RIGHT (ic);
11229 if (op && IS_SYMOP (op))
11231 aopOp (op, ic, FALSE);
11233 /* if the result is a bit */
11234 if (AOP_TYPE (op) == AOP_CRY)
11235 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11238 /* bit variables done */
11240 size = AOP_SIZE (op);
11244 MOVA (aopGet (op, offset, FALSE, FALSE));
11249 freeAsmop (op, NULL, ic, TRUE);
11253 if (op && IS_SYMOP (op))
11255 aopOp (op, ic, FALSE);
11257 /* if the result is a bit */
11258 if (AOP_TYPE (op) == AOP_CRY)
11259 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11262 /* bit variables done */
11264 size = AOP_SIZE (op);
11268 MOVA (aopGet (op, offset, FALSE, FALSE));
11273 freeAsmop (op, NULL, ic, TRUE);
11277 /*-----------------------------------------------------------------*/
11278 /* genCritical - generate code for start of a critical sequence */
11279 /*-----------------------------------------------------------------*/
11281 genCritical (iCode *ic)
11283 symbol *tlbl = newiTempLabel (NULL);
11285 D(emitcode("; genCritical",""));
11287 if (IC_RESULT (ic))
11289 aopOp (IC_RESULT (ic), ic, TRUE);
11290 aopPut (IC_RESULT (ic), one, 0, 0);
11291 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11292 aopPut (IC_RESULT (ic), zero, 0, 0);
11293 emitcode ("", "%05d$:", (tlbl->key + 100));
11294 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11298 emitcode ("setb", "c");
11299 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11300 emitcode ("clr", "c");
11301 emitcode ("", "%05d$:", (tlbl->key + 100));
11302 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11306 /*-----------------------------------------------------------------*/
11307 /* genEndCritical - generate code for end of a critical sequence */
11308 /*-----------------------------------------------------------------*/
11310 genEndCritical (iCode *ic)
11312 D(emitcode("; genEndCritical",""));
11316 aopOp (IC_RIGHT (ic), ic, FALSE);
11317 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11319 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11320 emitcode ("mov", "ea,c");
11324 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11325 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11326 emitcode ("rrc", "a");
11327 emitcode ("mov", "ea,c");
11329 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11333 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11334 emitcode ("mov", "ea,c");
11338 /*-----------------------------------------------------------------*/
11339 /* gen51Code - generate code for 8051 based controllers */
11340 /*-----------------------------------------------------------------*/
11342 gen51Code (iCode * lic)
11346 /* int cseq = 0; */
11348 _G.currentFunc = NULL;
11349 lineHead = lineCurr = NULL;
11351 /* print the allocation information */
11352 if (allocInfo && currFunc)
11353 printAllocInfo (currFunc, codeOutFile);
11354 /* if debug information required */
11355 if (options.debug && currFunc)
11357 debugFile->writeFunction (currFunc, lic);
11359 /* stack pointer name */
11360 if (options.useXstack)
11366 for (ic = lic; ic; ic = ic->next)
11368 _G.current_iCode = ic;
11370 if (ic->lineno && cln != ic->lineno)
11374 debugFile->writeCLine (ic);
11376 if (!options.noCcodeInAsm) {
11377 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11378 printCLine(ic->filename, ic->lineno));
11383 if (ic->seqPoint && ic->seqPoint != cseq)
11385 emitcode ("", "; sequence point %d", ic->seqPoint);
11386 cseq = ic->seqPoint;
11389 if (options.iCodeInAsm) {
11390 char regsInUse[80];
11394 for (i=0; i<8; i++) {
11395 sprintf (®sInUse[i],
11396 "%c", ic->riu & (1<<i) ? i+'0' : '-'); /* show riu */
11399 strcpy (regsInUse, "--------");
11400 for (i=0; i < 8; i++) {
11401 if (bitVectBitValue (ic->rMask, i))
11403 int offset = regs8051[i].offset;
11404 regsInUse[offset] = offset + '0'; /* show rMask */
11408 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11410 /* if the result is marked as
11411 spilt and rematerializable or code for
11412 this has already been generated then
11414 if (resultRemat (ic) || ic->generated)
11417 /* depending on the operation */
11437 /* IPOP happens only when trying to restore a
11438 spilt live range, if there is an ifx statement
11439 following this pop then the if statement might
11440 be using some of the registers being popped which
11441 would destory the contents of the register so
11442 we need to check for this condition and handle it */
11444 ic->next->op == IFX &&
11445 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11446 genIfx (ic->next, ic);
11464 genEndFunction (ic);
11484 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11501 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11505 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11512 /* note these two are xlated by algebraic equivalence
11513 during parsing SDCC.y */
11514 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11515 "got '>=' or '<=' shouldn't have come here");
11519 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11531 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11535 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11539 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11575 genRightShift (ic);
11578 case GET_VALUE_AT_ADDRESS:
11580 hasInc (IC_LEFT (ic), ic,
11581 getSize (operandType (IC_RESULT (ic)))),
11582 ifxForOp (IC_RESULT (ic), ic) );
11586 if (POINTER_SET (ic))
11587 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11613 addSet (&_G.sendSet, ic);
11616 case DUMMY_READ_VOLATILE:
11625 genEndCritical (ic);
11637 _G.current_iCode = NULL;
11639 /* now we are ready to call the
11640 peep hole optimizer */
11641 if (!options.nopeep)
11642 peepHole (&lineHead);
11644 /* now do the actual printing */
11645 printLine (lineHead, codeOutFile);