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