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 = mcs51_nRegs + (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 < mcs51_nRegs; 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);
2455 if (options.useXstack)
2457 emitcode ("mov", "a,psw");
2458 emitcode ("movx", "@%s,a", r->name);
2463 emitcode ("push", "psw");
2466 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2471 freeAsmop (NULL, aop, ic, TRUE);
2480 /*-----------------------------------------------------------------*/
2481 /* unsaveRBank - restores the register bank from stack */
2482 /*-----------------------------------------------------------------*/
2484 unsaveRBank (int bank, iCode * ic, bool popPsw)
2490 if (options.useXstack)
2494 /* Assume r0 is available for use. */
2495 r = mcs51_regWithIdx (R0_IDX);;
2500 r = getFreePtr (ic, &aop, FALSE);
2502 emitcode ("mov", "%s,%s", r->name, spname);
2507 if (options.useXstack)
2509 emitcode ("dec", "%s", r->name);
2510 emitcode ("movx", "a,@%s", r->name);
2511 emitcode ("mov", "psw,a");
2515 emitcode ("pop", "psw");
2519 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2521 if (options.useXstack)
2523 emitcode ("dec", "%s", r->name);
2524 emitcode ("movx", "a,@%s", r->name);
2525 emitcode ("mov", "(%s+%d),a",
2526 regs8051[i].base, 8 * bank + regs8051[i].offset);
2530 emitcode ("pop", "(%s+%d)",
2531 regs8051[i].base, 8 * bank + regs8051[i].offset);
2535 if (options.useXstack)
2537 emitcode ("mov", "%s,%s", spname, r->name);
2542 freeAsmop (NULL, aop, ic, TRUE);
2546 /*-----------------------------------------------------------------*/
2547 /* genSend - gen code for SEND */
2548 /*-----------------------------------------------------------------*/
2549 static void genSend(set *sendSet)
2554 /* first we do all bit parameters */
2555 for (sic = setFirstItem (sendSet); sic;
2556 sic = setNextItem (sendSet))
2558 aopOp (IC_LEFT (sic), sic, FALSE);
2560 if (sic->argreg > 12)
2562 int bit = sic->argreg-13;
2564 /* if left is a literal then
2565 we know what the value is */
2566 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2568 if (((int) operandLitValue (IC_LEFT (sic))))
2569 emitcode ("setb", "b[%d]", bit);
2571 emitcode ("clr", "b[%d]", bit);
2573 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2575 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2576 if (strcmp (l, "c"))
2577 emitcode ("mov", "c,%s", l);
2578 emitcode ("mov", "b[%d],c", bit);
2583 toBoolean (IC_LEFT (sic));
2584 /* set C, if a >= 1 */
2585 emitcode ("add", "a,#0xff");
2586 emitcode ("mov", "b[%d],c", bit);
2591 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2596 saveRegisters (setFirstItem (sendSet));
2597 emitcode ("mov", "bits,b");
2600 /* then we do all other parameters */
2601 for (sic = setFirstItem (sendSet); sic;
2602 sic = setNextItem (sendSet))
2604 int size, offset = 0;
2605 aopOp (IC_LEFT (sic), sic, FALSE);
2606 size = AOP_SIZE (IC_LEFT (sic));
2608 if (sic->argreg == 1)
2612 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2613 if (strcmp (l, fReturn[offset]))
2614 emitcode ("mov", "%s,%s", fReturn[offset], l);
2618 else if (sic->argreg <= 12)
2622 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2623 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2627 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2631 /*-----------------------------------------------------------------*/
2632 /* selectRegBank - emit code to select the register bank */
2633 /*-----------------------------------------------------------------*/
2635 selectRegBank (short bank, bool keepFlags)
2637 /* if f.e. result is in carry */
2640 emitcode ("anl", "psw,#0xE7");
2642 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2646 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2650 /*-----------------------------------------------------------------*/
2651 /* genCall - generates a call statement */
2652 /*-----------------------------------------------------------------*/
2654 genCall (iCode * ic)
2658 // bool restoreBank = FALSE;
2659 bool swapBanks = FALSE;
2660 bool accuse = FALSE;
2661 bool accPushed = FALSE;
2662 bool resultInF0 = FALSE;
2664 D(emitcode("; genCall",""));
2666 dtype = operandType (IC_LEFT (ic));
2667 etype = getSpec(dtype);
2668 /* if send set is not empty then assign */
2671 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2672 genSend(reverseSet(_G.sendSet));
2674 genSend(_G.sendSet);
2680 /* if we are calling a not _naked function that is not using
2681 the same register bank then we need to save the
2682 destination registers on the stack */
2683 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2684 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2685 !IFFUNC_ISISR (dtype))
2690 /* if caller saves & we have not saved then */
2696 emitcode ("mov", "psw,#0x%02x",
2697 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2701 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2703 if (IFFUNC_CALLEESAVES(dtype))
2705 werror (E_BANKED_WITH_CALLEESAVES);
2709 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2710 OP_SYMBOL (IC_LEFT (ic))->rname :
2711 OP_SYMBOL (IC_LEFT (ic))->name);
2713 emitcode ("mov", "r0,#%s", l);
2714 emitcode ("mov", "r1,#(%s >> 8)", l);
2715 emitcode ("mov", "r2,#(%s >> 16)", l);
2716 emitcode ("lcall", "__sdcc_banked_call");
2721 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2722 OP_SYMBOL (IC_LEFT (ic))->rname :
2723 OP_SYMBOL (IC_LEFT (ic))->name));
2728 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2731 /* if we need assign a result value */
2732 if ((IS_ITEMP (IC_RESULT (ic)) &&
2733 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2734 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2735 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2736 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2737 IS_TRUE_SYMOP (IC_RESULT (ic)))
2741 aopOp (IC_RESULT (ic), ic, FALSE);
2744 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2746 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2749 /* adjust the stack for parameters if required */
2753 if (ic->parmBytes > 3)
2757 emitcode ("push", "acc");
2760 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2761 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2763 emitcode ("mov", "F0,c");
2767 emitcode ("mov", "a,%s", spname);
2768 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2769 emitcode ("mov", "%s,a", spname);
2771 /* unsaveRegisters from xstack needs acc, but */
2772 /* unsaveRegisters from stack needs this popped */
2773 if (accPushed && !options.useXstack)
2775 emitcode ("pop", "acc");
2780 for (i = 0; i < ic->parmBytes; i++)
2781 emitcode ("dec", "%s", spname);
2784 /* if we had saved some registers then unsave them */
2785 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2787 if (accuse && !accPushed && options.useXstack)
2789 /* xstack needs acc, but doesn't touch normal stack */
2790 emitcode ("push", "acc");
2793 unsaveRegisters (ic);
2796 // /* if register bank was saved then pop them */
2798 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2800 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2803 emitcode ("mov", "c,F0");
2805 aopOp (IC_RESULT (ic), ic, FALSE);
2806 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2807 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2811 emitcode ("pop", "acc");
2814 /*-----------------------------------------------------------------*/
2815 /* -10l - generates a call by pointer statement */
2816 /*-----------------------------------------------------------------*/
2818 genPcall (iCode * ic)
2822 symbol *rlbl = newiTempLabel (NULL);
2823 // bool restoreBank=FALSE;
2824 bool swapBanks = FALSE;
2825 bool resultInF0 = FALSE;
2827 D(emitcode("; genPCall",""));
2829 dtype = operandType (IC_LEFT (ic))->next;
2830 etype = getSpec(dtype);
2831 /* if caller saves & we have not saved then */
2835 /* if we are calling a not _naked function that is not using
2836 the same register bank then we need to save the
2837 destination registers on the stack */
2838 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2839 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2840 !IFFUNC_ISISR (dtype))
2842 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2843 // restoreBank=TRUE;
2845 // need caution message to user here
2848 if (IS_LITERAL(etype))
2850 /* if send set is not empty then assign */
2853 genSend(reverseSet(_G.sendSet));
2859 emitcode ("mov", "psw,#0x%02x",
2860 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2863 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2865 if (IFFUNC_CALLEESAVES(dtype))
2867 werror (E_BANKED_WITH_CALLEESAVES);
2871 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2873 emitcode ("mov", "r0,#%s", l);
2874 emitcode ("mov", "r1,#(%s >> 8)", l);
2875 emitcode ("mov", "r2,#(%s >> 16)", l);
2876 emitcode ("lcall", "__sdcc_banked_call");
2881 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2886 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2888 if (IFFUNC_CALLEESAVES(dtype))
2890 werror (E_BANKED_WITH_CALLEESAVES);
2894 aopOp (IC_LEFT (ic), ic, FALSE);
2898 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2899 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2900 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2904 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2905 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2906 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2907 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2910 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2912 /* if send set is not empty then assign */
2915 genSend(reverseSet(_G.sendSet));
2921 emitcode ("mov", "psw,#0x%02x",
2922 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2926 emitcode ("lcall", "__sdcc_banked_call");
2931 /* push the return address on to the stack */
2932 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2933 emitcode ("push", "acc");
2934 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2935 emitcode ("push", "acc");
2937 /* now push the calling address */
2938 aopOp (IC_LEFT (ic), ic, FALSE);
2940 pushSide (IC_LEFT (ic), FPTRSIZE);
2942 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2944 /* if send set is not empty the assign */
2947 genSend(reverseSet(_G.sendSet));
2953 emitcode ("mov", "psw,#0x%02x",
2954 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2958 emitcode ("ret", "");
2959 emitcode ("", "%05d$:", (rlbl->key + 100));
2964 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2967 /* if we need assign a result value */
2968 if ((IS_ITEMP (IC_RESULT (ic)) &&
2969 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2970 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2971 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2972 IS_TRUE_SYMOP (IC_RESULT (ic)))
2976 aopOp (IC_RESULT (ic), ic, FALSE);
2979 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2981 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2984 /* adjust the stack for parameters if required */
2988 if (ic->parmBytes > 3)
2990 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2991 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2993 emitcode ("mov", "F0,c");
2997 emitcode ("mov", "a,%s", spname);
2998 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2999 emitcode ("mov", "%s,a", spname);
3002 for (i = 0; i < ic->parmBytes; i++)
3003 emitcode ("dec", "%s", spname);
3007 // /* if register bank was saved then unsave them */
3009 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
3011 /* if we had saved some registers then unsave them */
3012 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3013 unsaveRegisters (ic);
3015 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
3018 emitcode ("mov", "c,F0");
3020 aopOp (IC_RESULT (ic), ic, FALSE);
3021 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
3022 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3026 /*-----------------------------------------------------------------*/
3027 /* resultRemat - result is rematerializable */
3028 /*-----------------------------------------------------------------*/
3030 resultRemat (iCode * ic)
3032 if (SKIP_IC (ic) || ic->op == IFX)
3035 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
3037 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
3038 if (sym->remat && !POINTER_SET (ic))
3045 #if defined(__BORLANDC__) || defined(_MSC_VER)
3046 #define STRCASECMP stricmp
3048 #define STRCASECMP strcasecmp
3051 /*-----------------------------------------------------------------*/
3052 /* inExcludeList - return 1 if the string is in exclude Reg list */
3053 /*-----------------------------------------------------------------*/
3055 regsCmp(void *p1, void *p2)
3057 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3061 inExcludeList (char *s)
3063 const char *p = setFirstItem(options.excludeRegsSet);
3065 if (p == NULL || STRCASECMP(p, "none") == 0)
3069 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3072 /*-----------------------------------------------------------------*/
3073 /* genFunction - generated code for function entry */
3074 /*-----------------------------------------------------------------*/
3076 genFunction (iCode * ic)
3078 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3080 bool switchedPSW = FALSE;
3081 int calleesaves_saved_register = -1;
3082 int stackAdjust = sym->stack;
3083 int accIsFree = sym->recvSize < 4;
3084 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3085 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3088 /* create the function header */
3089 emitcode (";", "-----------------------------------------");
3090 emitcode (";", " function %s", sym->name);
3091 emitcode (";", "-----------------------------------------");
3093 emitcode ("", "%s:", sym->rname);
3094 ftype = operandType (IC_LEFT (ic));
3095 _G.currentFunc = sym;
3097 if (IFFUNC_ISNAKED(ftype))
3099 emitcode(";", "naked function: no prologue.");
3103 /* here we need to generate the equates for the
3104 register bank if required */
3105 if (FUNC_REGBANK (ftype) != rbank)
3109 rbank = FUNC_REGBANK (ftype);
3110 for (i = 0; i < mcs51_nRegs; i++)
3112 if (regs8051[i].type != REG_BIT)
3114 if (strcmp (regs8051[i].base, "0") == 0)
3115 emitcode ("", "%s = 0x%02x",
3117 8 * rbank + regs8051[i].offset);
3119 emitcode ("", "%s = %s + 0x%02x",
3122 8 * rbank + regs8051[i].offset);
3127 /* if this is an interrupt service routine then
3128 save acc, b, dpl, dph */
3129 if (IFFUNC_ISISR (sym->type))
3132 if (!inExcludeList ("acc"))
3133 emitcode ("push", "acc");
3134 if (!inExcludeList ("b"))
3135 emitcode ("push", "b");
3136 if (!inExcludeList ("dpl"))
3137 emitcode ("push", "dpl");
3138 if (!inExcludeList ("dph"))
3139 emitcode ("push", "dph");
3140 /* if this isr has no bank i.e. is going to
3141 run with bank 0 , then we need to save more
3143 if (!FUNC_REGBANK (sym->type))
3146 /* if this function does not call any other
3147 function then we can be economical and
3148 save only those registers that are used */
3149 if (!IFFUNC_HASFCALL(sym->type))
3153 /* if any registers used */
3156 bool bits_pushed = FALSE;
3157 /* save the registers used */
3158 for (i = 0; i < sym->regsUsed->size; i++)
3160 if (bitVectBitValue (sym->regsUsed, i))
3161 bits_pushed = pushReg (i, bits_pushed);
3168 /* this function has a function call. We cannot
3169 determines register usage so we will have to push the
3171 saveRBank (0, ic, FALSE);
3172 if (options.parms_in_bank1) {
3174 for (i=0; i < 8 ; i++ ) {
3175 emitcode ("push","%s",rb1regs[i]);
3182 /* This ISR uses a non-zero bank.
3184 * We assume that the bank is available for our
3187 * However, if this ISR calls a function which uses some
3188 * other bank, we must save that bank entirely.
3190 unsigned long banksToSave = 0;
3192 if (IFFUNC_HASFCALL(sym->type))
3195 #define MAX_REGISTER_BANKS 4
3200 for (i = ic; i; i = i->next)
3202 if (i->op == ENDFUNCTION)
3204 /* we got to the end OK. */
3212 dtype = operandType (IC_LEFT(i));
3214 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3216 /* Mark this bank for saving. */
3217 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3219 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3223 banksToSave |= (1 << FUNC_REGBANK(dtype));
3226 /* And note that we don't need to do it in
3234 /* This is a mess; we have no idea what
3235 * register bank the called function might
3238 * The only thing I can think of to do is
3239 * throw a warning and hope.
3241 werror(W_FUNCPTR_IN_USING_ISR);
3245 if (banksToSave && options.useXstack)
3247 /* Since we aren't passing it an ic,
3248 * saveRBank will assume r0 is available to abuse.
3250 * So switch to our (trashable) bank now, so
3251 * the caller's R0 isn't trashed.
3253 emitcode ("push", "psw");
3254 emitcode ("mov", "psw,#0x%02x",
3255 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3259 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3261 if (banksToSave & (1 << ix))
3263 saveRBank(ix, NULL, FALSE);
3267 // TODO: this needs a closer look
3268 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3271 /* Set the register bank to the desired value if nothing else */
3272 /* has done so yet. */
3275 emitcode ("push", "psw");
3276 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3281 /* This is a non-ISR function. The caller has already switched register */
3282 /* banks, if necessary, so just handle the callee-saves option. */
3284 /* if callee-save to be used for this function
3285 then save the registers being used in this function */
3286 if (IFFUNC_CALLEESAVES(sym->type))
3290 /* if any registers used */
3293 bool bits_pushed = FALSE;
3294 /* save the registers used */
3295 for (i = 0; i < sym->regsUsed->size; i++)
3297 if (bitVectBitValue (sym->regsUsed, i))
3299 /* remember one saved register for later usage */
3300 if (calleesaves_saved_register < 0)
3301 calleesaves_saved_register = i;
3302 bits_pushed = pushReg (i, bits_pushed);
3313 if (options.useXstack)
3315 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3317 emitcode ("mov", "r0,%s", spname);
3318 emitcode ("inc", "%s", spname);
3319 emitcode ("xch", "a,_bpx");
3320 emitcode ("movx", "@r0,a");
3321 emitcode ("inc", "r0");
3322 emitcode ("mov", "a,r0");
3323 emitcode ("xch", "a,_bpx");
3327 emitcode ("push", "_bp"); /* save the callers stack */
3328 emitcode ("mov", "_bp,sp");
3333 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3335 /* set up the stack */
3336 emitcode ("push", "_bp"); /* save the callers stack */
3337 emitcode ("mov", "_bp,sp");
3342 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3343 /* before setting up the stack frame completely. */
3344 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3346 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3350 if (rsym && rsym->regType == REG_CND)
3352 if (rsym && (rsym->accuse || rsym->ruonly))
3354 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3355 rsym = rsym->usl.spillLoc;
3358 /* If the RECEIVE operand immediately spills to the first entry on the */
3359 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3360 /* rather than the usual @r0/r1 machinations. */
3361 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3365 _G.current_iCode = ric;
3366 D(emitcode ("; genReceive",""));
3367 for (ofs=0; ofs < sym->recvSize; ofs++)
3369 if (!strcmp (fReturn[ofs], "a"))
3370 emitcode ("push", "acc");
3372 emitcode ("push", fReturn[ofs]);
3374 stackAdjust -= sym->recvSize;
3377 assert (stackAdjust>=0);
3380 _G.current_iCode = ic;
3384 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3385 /* to free up the accumulator. */
3386 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3390 _G.current_iCode = ric;
3391 D(emitcode ("; genReceive",""));
3392 for (ofs=0; ofs < sym->recvSize; ofs++)
3394 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3396 _G.current_iCode = ic;
3402 /* adjust the stack for the function */
3405 int i = stackAdjust;
3407 werror (W_STACK_OVERFLOW, sym->name);
3409 if (i > 3 && accIsFree)
3411 emitcode ("mov", "a,sp");
3412 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3413 emitcode ("mov", "sp,a");
3417 /* The accumulator is not free, so we will need another register */
3418 /* to clobber. No need to worry about a possible conflict with */
3419 /* the above early RECEIVE optimizations since they would have */
3420 /* freed the accumulator if they were generated. */
3422 if (IFFUNC_CALLEESAVES(sym->type))
3424 /* if it's a callee-saves function we need a saved register */
3425 if (calleesaves_saved_register >= 0)
3427 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3428 emitcode ("mov", "a,sp");
3429 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3430 emitcode ("mov", "sp,a");
3431 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3434 /* do it the hard way */
3436 emitcode ("inc", "sp");
3440 /* not callee-saves, we can clobber r0 */
3441 emitcode ("mov", "r0,a");
3442 emitcode ("mov", "a,sp");
3443 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3444 emitcode ("mov", "sp,a");
3445 emitcode ("mov", "a,r0");
3450 emitcode ("inc", "sp");
3455 char i = ((char) sym->xstack & 0xff);
3457 if (i > 3 && accIsFree)
3459 emitcode ("mov", "a,_spx");
3460 emitcode ("add", "a,#0x%02x", i);
3461 emitcode ("mov", "_spx,a");
3465 emitcode ("push", "acc");
3466 emitcode ("mov", "a,_spx");
3467 emitcode ("add", "a,#0x%02x", i);
3468 emitcode ("mov", "_spx,a");
3469 emitcode ("pop", "acc");
3474 emitcode ("inc", "_spx");
3478 /* if critical function then turn interrupts off */
3479 if (IFFUNC_ISCRITICAL (ftype))
3481 symbol *tlbl = newiTempLabel (NULL);
3482 emitcode ("setb", "c");
3483 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3484 emitcode ("clr", "c");
3485 emitcode ("", "%05d$:", (tlbl->key + 100));
3486 emitcode ("push", "psw"); /* save old ea via c in psw */
3490 /*-----------------------------------------------------------------*/
3491 /* genEndFunction - generates epilogue for functions */
3492 /*-----------------------------------------------------------------*/
3494 genEndFunction (iCode * ic)
3496 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3497 lineNode *lnp = lineCurr;
3499 bitVect *regsUsedPrologue;
3500 bitVect *regsUnneeded;
3503 _G.currentFunc = NULL;
3504 if (IFFUNC_ISNAKED(sym->type))
3506 emitcode(";", "naked function: no epilogue.");
3507 if (options.debug && currFunc)
3508 debugFile->writeEndFunction (currFunc, ic, 0);
3512 if (IFFUNC_ISCRITICAL (sym->type))
3514 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3516 emitcode ("rlc", "a"); /* save c in a */
3517 emitcode ("pop", "psw"); /* restore ea via c in psw */
3518 emitcode ("mov", "ea,c");
3519 emitcode ("rrc", "a"); /* restore c from a */
3523 emitcode ("pop", "psw"); /* restore ea via c in psw */
3524 emitcode ("mov", "ea,c");
3528 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3530 if (options.useXstack)
3534 emitcode ("mov", "sp,_bp");
3535 emitcode ("pop", "_bp");
3537 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3539 emitcode ("xch", "a,_bpx");
3540 emitcode ("mov", "r0,a");
3541 emitcode ("dec", "r0");
3542 emitcode ("movx", "a,@r0");
3543 emitcode ("xch", "a,_bpx");
3544 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3547 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3549 emitcode ("mov", "sp,_bp");
3550 emitcode ("pop", "_bp");
3554 /* restore the register bank */
3555 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3557 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3558 || !options.useXstack)
3560 /* Special case of ISR using non-zero bank with useXstack
3563 emitcode ("pop", "psw");
3567 if (IFFUNC_ISISR (sym->type))
3570 /* now we need to restore the registers */
3571 /* if this isr has no bank i.e. is going to
3572 run with bank 0 , then we need to save more
3574 if (!FUNC_REGBANK (sym->type))
3576 /* if this function does not call any other
3577 function then we can be economical and
3578 save only those registers that are used */
3579 if (!IFFUNC_HASFCALL(sym->type))
3583 /* if any registers used */
3586 bool bits_popped = FALSE;
3587 /* save the registers used */
3588 for (i = sym->regsUsed->size; i >= 0; i--)
3590 if (bitVectBitValue (sym->regsUsed, i))
3591 bits_popped = popReg (i, bits_popped);
3597 if (options.parms_in_bank1) {
3599 for (i = 7 ; i >= 0 ; i-- ) {
3600 emitcode ("pop","%s",rb1regs[i]);
3603 /* this function has a function call cannot
3604 determines register usage so we will have to pop the
3606 unsaveRBank (0, ic, FALSE);
3611 /* This ISR uses a non-zero bank.
3613 * Restore any register banks saved by genFunction
3616 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3619 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3621 if (savedBanks & (1 << ix))
3623 unsaveRBank(ix, NULL, FALSE);
3627 if (options.useXstack)
3629 /* Restore bank AFTER calling unsaveRBank,
3630 * since it can trash r0.
3632 emitcode ("pop", "psw");
3636 if (!inExcludeList ("dph"))
3637 emitcode ("pop", "dph");
3638 if (!inExcludeList ("dpl"))
3639 emitcode ("pop", "dpl");
3640 if (!inExcludeList ("b"))
3641 emitcode ("pop", "b");
3642 if (!inExcludeList ("acc"))
3643 emitcode ("pop", "acc");
3645 /* if debug then send end of function */
3646 if (options.debug && currFunc)
3648 debugFile->writeEndFunction (currFunc, ic, 1);
3651 emitcode ("reti", "");
3655 if (IFFUNC_CALLEESAVES(sym->type))
3659 /* if any registers used */
3662 /* save the registers used */
3663 for (i = sym->regsUsed->size; i >= 0; i--)
3665 if (bitVectBitValue (sym->regsUsed, i) ||
3666 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3667 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3670 else if (mcs51_ptrRegReq)
3672 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3673 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3678 /* if debug then send end of function */
3679 if (options.debug && currFunc)
3681 debugFile->writeEndFunction (currFunc, ic, 1);
3684 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3686 emitcode ("ljmp", "__sdcc_banked_ret");
3690 emitcode ("ret", "");
3694 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3697 /* If this was an interrupt handler using bank 0 that called another */
3698 /* function, then all registers must be saved; nothing to optimized. */
3699 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3700 && !FUNC_REGBANK(sym->type))
3703 /* There are no push/pops to optimize if not callee-saves or ISR */
3704 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3707 /* If there were stack parameters, we cannot optimize without also */
3708 /* fixing all of the stack offsets; this is too dificult to consider. */
3709 if (FUNC_HASSTACKPARM(sym->type))
3712 /* Compute the registers actually used */
3713 regsUsed = newBitVect (mcs51_nRegs);
3714 regsUsedPrologue = newBitVect (mcs51_nRegs);
3717 if (lnp->ic && lnp->ic->op == FUNCTION)
3718 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3720 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3722 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3723 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3730 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3731 && !bitVectBitValue (regsUsed, CND_IDX))
3733 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3734 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3735 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3736 bitVectUnSetBit (regsUsed, CND_IDX);
3739 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3741 /* If this was an interrupt handler that called another function */
3742 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3743 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3745 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3746 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3747 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3748 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3749 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3752 /* Remove the unneeded push/pops */
3753 regsUnneeded = newBitVect (mcs51_nRegs);
3756 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3758 if (!strncmp(lnp->line, "push", 4))
3760 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3761 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3763 connectLine (lnp->prev, lnp->next);
3764 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3767 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3769 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3770 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3772 connectLine (lnp->prev, lnp->next);
3773 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3780 for (idx = 0; idx < regsUnneeded->size; idx++)
3781 if (bitVectBitValue (regsUnneeded, idx))
3782 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3784 freeBitVect (regsUnneeded);
3785 freeBitVect (regsUsed);
3786 freeBitVect (regsUsedPrologue);
3789 /*-----------------------------------------------------------------*/
3790 /* genRet - generate code for return statement */
3791 /*-----------------------------------------------------------------*/
3795 int size, offset = 0, pushed = 0;
3797 D(emitcode ("; genRet",""));
3799 /* if we have no return value then
3800 just generate the "ret" */
3804 /* we have something to return then
3805 move the return value into place */
3806 aopOp (IC_LEFT (ic), ic, FALSE);
3807 size = AOP_SIZE (IC_LEFT (ic));
3810 if (IS_BIT(_G.currentFunc->etype))
3812 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3819 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3822 l = aopGet (IC_LEFT (ic), offset++,
3824 emitcode ("push", "%s", l);
3829 l = aopGet (IC_LEFT (ic), offset,
3831 if (strcmp (fReturn[offset], l))
3832 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3839 if (strcmp (fReturn[pushed], "a"))
3840 emitcode ("pop", fReturn[pushed]);
3842 emitcode ("pop", "acc");
3844 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3847 /* generate a jump to the return label
3848 if the next is not the return statement */
3849 if (!(ic->next && ic->next->op == LABEL &&
3850 IC_LABEL (ic->next) == returnLabel))
3852 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3856 /*-----------------------------------------------------------------*/
3857 /* genLabel - generates a label */
3858 /*-----------------------------------------------------------------*/
3860 genLabel (iCode * ic)
3862 /* special case never generate */
3863 if (IC_LABEL (ic) == entryLabel)
3866 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3869 /*-----------------------------------------------------------------*/
3870 /* genGoto - generates a ljmp */
3871 /*-----------------------------------------------------------------*/
3873 genGoto (iCode * ic)
3875 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3878 /*-----------------------------------------------------------------*/
3879 /* findLabelBackwards: walks back through the iCode chain looking */
3880 /* for the given label. Returns number of iCode instructions */
3881 /* between that label and given ic. */
3882 /* Returns zero if label not found. */
3883 /*-----------------------------------------------------------------*/
3885 findLabelBackwards (iCode * ic, int key)
3894 /* If we have any pushes or pops, we cannot predict the distance.
3895 I don't like this at all, this should be dealt with in the
3897 if (ic->op == IPUSH || ic->op == IPOP) {
3901 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3910 /*-----------------------------------------------------------------*/
3911 /* genPlusIncr :- does addition with increment if possible */
3912 /*-----------------------------------------------------------------*/
3914 genPlusIncr (iCode * ic)
3916 unsigned int icount;
3917 unsigned int size = getDataSize (IC_RESULT (ic));
3919 /* will try to generate an increment */
3920 /* if the right side is not a literal
3922 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3925 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3927 D(emitcode ("; genPlusIncr",""));
3929 /* if increment >=16 bits in register or direct space */
3930 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3931 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3932 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3940 /* If the next instruction is a goto and the goto target
3941 * is < 10 instructions previous to this, we can generate
3942 * jumps straight to that target.
3944 if (ic->next && ic->next->op == GOTO
3945 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3946 && labelRange <= 10)
3948 emitcode (";", "tail increment optimized");
3949 tlbl = IC_LABEL (ic->next);
3954 tlbl = newiTempLabel (NULL);
3957 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3958 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3959 IS_AOP_PREG (IC_RESULT (ic)))
3960 emitcode ("cjne", "%s,#0x00,%05d$",
3961 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3965 emitcode ("clr", "a");
3966 emitcode ("cjne", "a,%s,%05d$",
3967 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3971 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3974 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3975 IS_AOP_PREG (IC_RESULT (ic)))
3976 emitcode ("cjne", "%s,#0x00,%05d$",
3977 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3980 emitcode ("cjne", "a,%s,%05d$",
3981 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3984 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, 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), MSB24, FALSE, FALSE),
3995 emitcode ("cjne", "a,%s,%05d$",
3996 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3999 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4004 emitcode ("", "%05d$:", tlbl->key + 100);
4009 /* if result is dptr */
4010 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
4011 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
4012 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
4013 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
4015 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4021 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
4024 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
4025 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
4027 emitcode ("inc", "dptr");
4032 /* if the literal value of the right hand side
4033 is greater than 4 then it is not worth it */
4037 /* if the sizes are greater than 1 then we cannot */
4038 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4039 AOP_SIZE (IC_LEFT (ic)) > 1)
4042 /* we can if the aops of the left & result match or
4043 if they are in registers and the registers are the
4045 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4050 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4051 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4052 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4058 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4067 /*-----------------------------------------------------------------*/
4068 /* outBitAcc - output a bit in acc */
4069 /*-----------------------------------------------------------------*/
4071 outBitAcc (operand * result)
4073 symbol *tlbl = newiTempLabel (NULL);
4074 /* if the result is a bit */
4075 if (AOP_TYPE (result) == AOP_CRY)
4077 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4081 emitcode ("jz", "%05d$", tlbl->key + 100);
4082 emitcode ("mov", "a,%s", one);
4083 emitcode ("", "%05d$:", tlbl->key + 100);
4088 /*-----------------------------------------------------------------*/
4089 /* genPlusBits - generates code for addition of two bits */
4090 /*-----------------------------------------------------------------*/
4092 genPlusBits (iCode * ic)
4094 D(emitcode ("; genPlusBits",""));
4096 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4098 symbol *lbl = newiTempLabel (NULL);
4099 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4100 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4101 emitcode ("cpl", "c");
4102 emitcode ("", "%05d$:", (lbl->key + 100));
4103 outBitC (IC_RESULT (ic));
4107 emitcode ("clr", "a");
4108 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4109 emitcode ("rlc", "a");
4110 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4111 emitcode ("addc", "a,#0x00");
4112 outAcc (IC_RESULT (ic));
4117 /* This is the original version of this code.
4119 * This is being kept around for reference,
4120 * because I am not entirely sure I got it right...
4123 adjustArithmeticResult (iCode * ic)
4125 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4126 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4127 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4128 aopPut (IC_RESULT (ic),
4129 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4131 isOperandVolatile (IC_RESULT (ic), FALSE));
4133 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4134 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4135 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4136 aopPut (IC_RESULT (ic),
4137 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4139 isOperandVolatile (IC_RESULT (ic), FALSE));
4141 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4142 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4143 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4144 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4145 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4148 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4149 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4153 /* This is the pure and virtuous version of this code.
4154 * I'm pretty certain it's right, but not enough to toss the old
4158 adjustArithmeticResult (iCode * ic)
4160 if (opIsGptr (IC_RESULT (ic)) &&
4161 opIsGptr (IC_LEFT (ic)) &&
4162 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4164 aopPut (IC_RESULT (ic),
4165 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4167 isOperandVolatile (IC_RESULT (ic), FALSE));
4170 if (opIsGptr (IC_RESULT (ic)) &&
4171 opIsGptr (IC_RIGHT (ic)) &&
4172 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4174 aopPut (IC_RESULT (ic),
4175 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4177 isOperandVolatile (IC_RESULT (ic), FALSE));
4180 if (opIsGptr (IC_RESULT (ic)) &&
4181 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4182 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4183 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4184 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4187 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4188 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4193 /*-----------------------------------------------------------------*/
4194 /* genPlus - generates code for addition */
4195 /*-----------------------------------------------------------------*/
4197 genPlus (iCode * ic)
4199 int size, offset = 0;
4202 operand *leftOp, *rightOp;
4205 /* special cases :- */
4207 D(emitcode ("; genPlus",""));
4209 aopOp (IC_LEFT (ic), ic, FALSE);
4210 aopOp (IC_RIGHT (ic), ic, FALSE);
4211 aopOp (IC_RESULT (ic), ic, TRUE);
4213 /* if literal, literal on the right or
4214 if left requires ACC or right is already
4216 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4217 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4218 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4220 operand *t = IC_RIGHT (ic);
4221 IC_RIGHT (ic) = IC_LEFT (ic);
4225 /* if both left & right are in bit
4227 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4228 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4234 /* if left in bit space & right literal */
4235 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4236 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4238 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4239 /* if result in bit space */
4240 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4242 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4243 emitcode ("cpl", "c");
4244 outBitC (IC_RESULT (ic));
4248 size = getDataSize (IC_RESULT (ic));
4251 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4252 emitcode ("addc", "a,#00");
4253 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4259 /* if I can do an increment instead
4260 of add then GOOD for ME */
4261 if (genPlusIncr (ic) == TRUE)
4264 size = getDataSize (IC_RESULT (ic));
4265 leftOp = IC_LEFT(ic);
4266 rightOp = IC_RIGHT(ic);
4269 /* if this is an add for an array access
4270 at a 256 byte boundary */
4272 && AOP_TYPE (op) == AOP_IMMD
4274 && IS_SPEC (OP_SYM_ETYPE (op))
4275 && SPEC_ABSA (OP_SYM_ETYPE (op))
4276 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4279 D(emitcode ("; genPlus aligned array",""));
4280 aopPut (IC_RESULT (ic),
4281 aopGet (rightOp, 0, FALSE, FALSE),
4283 isOperandVolatile (IC_RESULT (ic), FALSE));
4285 if( 1 == getDataSize (IC_RIGHT (ic)) )
4287 aopPut (IC_RESULT (ic),
4288 aopGet (leftOp, 1, FALSE, FALSE),
4290 isOperandVolatile (IC_RESULT (ic), FALSE));
4294 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4295 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4296 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4301 /* if the lower bytes of a literal are zero skip the addition */
4302 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4304 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4305 (skip_bytes+1 < size))
4310 D(emitcode ("; genPlus shortcut",""));
4315 if( offset >= skip_bytes )
4317 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4320 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4322 emitcode("xch", "a,b");
4323 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4324 emitcode (add, "a,b");
4327 else if (aopGetUsesAcc (leftOp, offset))
4329 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4330 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4334 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4335 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4337 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4338 add = "addc"; /* further adds must propagate carry */
4342 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4343 isOperandVolatile (IC_RESULT (ic), FALSE))
4346 aopPut (IC_RESULT (ic),
4347 aopGet (leftOp, offset, FALSE, FALSE),
4349 isOperandVolatile (IC_RESULT (ic), FALSE));
4355 adjustArithmeticResult (ic);
4358 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4359 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4360 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4363 /*-----------------------------------------------------------------*/
4364 /* genMinusDec :- does subtraction with decrement if possible */
4365 /*-----------------------------------------------------------------*/
4367 genMinusDec (iCode * ic)
4369 unsigned int icount;
4370 unsigned int size = getDataSize (IC_RESULT (ic));
4372 /* will try to generate an increment */
4373 /* if the right side is not a literal
4375 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4378 /* if the literal value of the right hand side
4379 is greater than 4 then it is not worth it */
4380 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4383 D(emitcode ("; genMinusDec",""));
4385 /* if decrement >=16 bits in register or direct space */
4386 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4387 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4395 /* If the next instruction is a goto and the goto target
4396 * is <= 10 instructions previous to this, we can generate
4397 * jumps straight to that target.
4399 if (ic->next && ic->next->op == GOTO
4400 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4401 && labelRange <= 10)
4403 emitcode (";", "tail decrement optimized");
4404 tlbl = IC_LABEL (ic->next);
4409 tlbl = newiTempLabel (NULL);
4413 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4414 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4415 IS_AOP_PREG (IC_RESULT (ic)))
4416 emitcode ("cjne", "%s,#0xff,%05d$"
4417 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4421 emitcode ("mov", "a,#0xff");
4422 emitcode ("cjne", "a,%s,%05d$"
4423 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4426 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4429 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4430 IS_AOP_PREG (IC_RESULT (ic)))
4431 emitcode ("cjne", "%s,#0xff,%05d$"
4432 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4436 emitcode ("cjne", "a,%s,%05d$"
4437 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4440 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, 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), MSB24, FALSE, FALSE)
4451 emitcode ("cjne", "a,%s,%05d$"
4452 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4455 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4459 emitcode ("", "%05d$:", tlbl->key + 100);
4464 /* if the sizes are greater than 1 then we cannot */
4465 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4466 AOP_SIZE (IC_LEFT (ic)) > 1)
4469 /* we can if the aops of the left & result match or
4470 if they are in registers and the registers are the
4472 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4476 if (aopGetUsesAcc (IC_LEFT (ic), 0))
4478 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4483 l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
4487 emitcode ("dec", "%s", l);
4489 if (AOP_NEEDSACC (IC_RESULT (ic)))
4490 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4498 /*-----------------------------------------------------------------*/
4499 /* addSign - complete with sign */
4500 /*-----------------------------------------------------------------*/
4502 addSign (operand * result, int offset, int sign)
4504 int size = (getDataSize (result) - offset);
4509 emitcode ("rlc", "a");
4510 emitcode ("subb", "a,acc");
4512 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4516 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4520 /*-----------------------------------------------------------------*/
4521 /* genMinusBits - generates code for subtraction of two bits */
4522 /*-----------------------------------------------------------------*/
4524 genMinusBits (iCode * ic)
4526 symbol *lbl = newiTempLabel (NULL);
4528 D(emitcode ("; genMinusBits",""));
4530 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4532 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4533 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4534 emitcode ("cpl", "c");
4535 emitcode ("", "%05d$:", (lbl->key + 100));
4536 outBitC (IC_RESULT (ic));
4540 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4541 emitcode ("subb", "a,acc");
4542 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4543 emitcode ("inc", "a");
4544 emitcode ("", "%05d$:", (lbl->key + 100));
4545 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4546 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4550 /*-----------------------------------------------------------------*/
4551 /* genMinus - generates code for subtraction */
4552 /*-----------------------------------------------------------------*/
4554 genMinus (iCode * ic)
4556 int size, offset = 0;
4558 D(emitcode ("; genMinus",""));
4560 aopOp (IC_LEFT (ic), ic, FALSE);
4561 aopOp (IC_RIGHT (ic), ic, FALSE);
4562 aopOp (IC_RESULT (ic), ic, TRUE);
4564 /* special cases :- */
4565 /* if both left & right are in bit space */
4566 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4567 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4573 /* if I can do an decrement instead
4574 of subtract then GOOD for ME */
4575 if (genMinusDec (ic) == TRUE)
4578 size = getDataSize (IC_RESULT (ic));
4580 /* if literal, add a,#-lit, else normal subb */
4581 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4583 unsigned long lit = 0L;
4584 bool useCarry = FALSE;
4586 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4591 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4593 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4594 if (!offset && !size && lit== (unsigned long) -1)
4596 emitcode ("dec", "a");
4600 /* first add without previous c */
4601 emitcode ("add", "a,#0x%02x",
4602 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4607 emitcode ("addc", "a,#0x%02x",
4608 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4610 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4614 /* no need to add zeroes */
4615 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4617 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4618 offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4626 operand *leftOp, *rightOp;
4628 leftOp = IC_LEFT(ic);
4629 rightOp = IC_RIGHT(ic);
4633 if (aopGetUsesAcc(rightOp, offset)) {
4634 if (aopGetUsesAcc(leftOp, offset)) {
4637 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4639 emitcode ("mov", "b,a");
4642 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4643 emitcode ("subb", "a,b");
4646 /* reverse subtraction with 2's complement */
4648 emitcode( "setb", "c");
4650 emitcode( "cpl", "c");
4651 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4652 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4653 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4654 emitcode("cpl", "a");
4655 if (size) /* skip if last byte */
4656 emitcode( "cpl", "c");
4659 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4662 emitcode ("subb", "a,%s",
4663 aopGet(rightOp, offset, FALSE, TRUE));
4666 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4671 adjustArithmeticResult (ic);
4674 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4675 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4676 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4680 /*-----------------------------------------------------------------*/
4681 /* genMultbits :- multiplication of bits */
4682 /*-----------------------------------------------------------------*/
4684 genMultbits (operand * left,
4688 D(emitcode ("; genMultbits",""));
4690 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4691 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4695 /*-----------------------------------------------------------------*/
4696 /* genMultOneByte : 8*8=8/16 bit multiplication */
4697 /*-----------------------------------------------------------------*/
4699 genMultOneByte (operand * left,
4704 int size = AOP_SIZE (result);
4705 bool runtimeSign, compiletimeSign;
4706 bool lUnsigned, rUnsigned, pushedB;
4708 D(emitcode ("; genMultOneByte",""));
4710 if (size < 1 || size > 2)
4712 /* this should never happen */
4713 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4714 AOP_SIZE(result), __FILE__, lineno);
4718 /* (if two literals: the value is computed before) */
4719 /* if one literal, literal on the right */
4720 if (AOP_TYPE (left) == AOP_LIT)
4725 /* emitcode (";", "swapped left and right"); */
4727 /* if no literal, unsigned on the right: shorter code */
4728 if ( AOP_TYPE (right) != AOP_LIT
4729 && SPEC_USIGN (getSpec (operandType (left))))
4736 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4737 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4741 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4742 no need to take care about the signedness! */
4743 || (lUnsigned && rUnsigned))
4745 /* just an unsigned 8 * 8 = 8 multiply
4747 /* emitcode (";","unsigned"); */
4748 /* TODO: check for accumulator clash between left & right aops? */
4750 if (AOP_TYPE (right) == AOP_LIT)
4752 /* moving to accumulator first helps peepholes */
4753 MOVA (aopGet (left, 0, FALSE, FALSE));
4754 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4758 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4759 MOVA (aopGet (left, 0, FALSE, FALSE));
4762 emitcode ("mul", "ab");
4763 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4765 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4771 /* we have to do a signed multiply */
4772 /* emitcode (";", "signed"); */
4774 /* now sign adjust for both left & right */
4776 /* let's see what's needed: */
4777 /* apply negative sign during runtime */
4778 runtimeSign = FALSE;
4779 /* negative sign from literals */
4780 compiletimeSign = FALSE;
4784 if (AOP_TYPE(left) == AOP_LIT)
4786 /* signed literal */
4787 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4789 compiletimeSign = TRUE;
4792 /* signed but not literal */
4798 if (AOP_TYPE(right) == AOP_LIT)
4800 /* signed literal */
4801 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4803 compiletimeSign ^= TRUE;
4806 /* signed but not literal */
4810 /* initialize F0, which stores the runtime sign */
4813 if (compiletimeSign)
4814 emitcode ("setb", "F0"); /* set sign flag */
4816 emitcode ("clr", "F0"); /* reset sign flag */
4819 /* save the signs of the operands */
4820 if (AOP_TYPE(right) == AOP_LIT)
4822 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4824 if (!rUnsigned && val < 0)
4825 emitcode ("mov", "b,#0x%02x", -val);
4827 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4829 else /* ! literal */
4831 if (rUnsigned) /* emitcode (";", "signed"); */
4833 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4836 MOVA (aopGet (right, 0, FALSE, FALSE));
4837 lbl = newiTempLabel (NULL);
4838 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4839 emitcode ("cpl", "F0"); /* complement sign flag */
4840 emitcode ("cpl", "a"); /* 2's complement */
4841 emitcode ("inc", "a");
4842 emitcode ("", "%05d$:", (lbl->key + 100));
4843 emitcode ("mov", "b,a");
4847 if (AOP_TYPE(left) == AOP_LIT)
4849 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4851 if (!lUnsigned && val < 0)
4852 emitcode ("mov", "a,#0x%02x", -val);
4854 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4856 else /* ! literal */
4858 MOVA (aopGet (left, 0, FALSE, FALSE));
4862 lbl = newiTempLabel (NULL);
4863 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4864 emitcode ("cpl", "F0"); /* complement sign flag */
4865 emitcode ("cpl", "a"); /* 2's complement */
4866 emitcode ("inc", "a");
4867 emitcode ("", "%05d$:", (lbl->key + 100));
4871 /* now the multiplication */
4872 emitcode ("mul", "ab");
4873 if (runtimeSign || compiletimeSign)
4875 lbl = newiTempLabel (NULL);
4877 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4878 emitcode ("cpl", "a"); /* lsb 2's complement */
4880 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4883 emitcode ("add", "a,#1"); /* this sets carry flag */
4884 emitcode ("xch", "a,b");
4885 emitcode ("cpl", "a"); /* msb 2's complement */
4886 emitcode ("addc", "a,#0");
4887 emitcode ("xch", "a,b");
4889 emitcode ("", "%05d$:", (lbl->key + 100));
4891 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4893 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4898 /*-----------------------------------------------------------------*/
4899 /* genMult - generates code for multiplication */
4900 /*-----------------------------------------------------------------*/
4902 genMult (iCode * ic)
4904 operand *left = IC_LEFT (ic);
4905 operand *right = IC_RIGHT (ic);
4906 operand *result = IC_RESULT (ic);
4908 D(emitcode ("; genMult",""));
4910 /* assign the asmops */
4911 aopOp (left, ic, FALSE);
4912 aopOp (right, ic, FALSE);
4913 aopOp (result, ic, TRUE);
4915 /* special cases first */
4917 if (AOP_TYPE (left) == AOP_CRY &&
4918 AOP_TYPE (right) == AOP_CRY)
4920 genMultbits (left, right, result);
4924 /* if both are of size == 1 */
4925 #if 0 // one of them can be a sloc shared with the result
4926 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4928 if (getSize(operandType(left)) == 1 &&
4929 getSize(operandType(right)) == 1)
4932 genMultOneByte (left, right, result);
4936 /* should have been converted to function call */
4937 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4938 getSize(OP_SYMBOL(right)->type));
4942 freeAsmop (result, NULL, ic, TRUE);
4943 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4944 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4947 /*-----------------------------------------------------------------*/
4948 /* genDivbits :- division of bits */
4949 /*-----------------------------------------------------------------*/
4951 genDivbits (operand * left,
4958 D(emitcode ("; genDivbits",""));
4962 /* the result must be bit */
4963 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4964 l = aopGet (left, 0, FALSE, FALSE);
4968 emitcode ("div", "ab");
4969 emitcode ("rrc", "a");
4973 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4976 /*-----------------------------------------------------------------*/
4977 /* genDivOneByte : 8 bit division */
4978 /*-----------------------------------------------------------------*/
4980 genDivOneByte (operand * left,
4984 bool lUnsigned, rUnsigned, pushedB;
4985 bool runtimeSign, compiletimeSign;
4986 bool accuse = FALSE;
4987 bool pushedA = FALSE;
4991 D(emitcode ("; genDivOneByte",""));
4993 /* Why is it necessary that genDivOneByte() can return an int result?
4996 volatile unsigned char uc;
4997 volatile signed char sc1, sc2;
5010 In all cases a one byte result would overflow, the following cast to int
5011 would return the wrong result.
5013 Two possible solution:
5014 a) cast operands to int, if ((unsigned) / (signed)) or
5015 ((signed) / (signed))
5016 b) return an 16 bit signed int; this is what we're doing here!
5019 size = AOP_SIZE (result) - 1;
5021 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5022 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5026 /* signed or unsigned */
5027 if (lUnsigned && rUnsigned)
5029 /* unsigned is easy */
5030 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5031 MOVA (aopGet (left, 0, FALSE, FALSE));
5032 emitcode ("div", "ab");
5033 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5035 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5041 /* signed is a little bit more difficult */
5043 /* now sign adjust for both left & right */
5045 /* let's see what's needed: */
5046 /* apply negative sign during runtime */
5047 runtimeSign = FALSE;
5048 /* negative sign from literals */
5049 compiletimeSign = FALSE;
5053 if (AOP_TYPE(left) == AOP_LIT)
5055 /* signed literal */
5056 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5058 compiletimeSign = TRUE;
5061 /* signed but not literal */
5067 if (AOP_TYPE(right) == AOP_LIT)
5069 /* signed literal */
5070 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5072 compiletimeSign ^= TRUE;
5075 /* signed but not literal */
5079 /* initialize F0, which stores the runtime sign */
5082 if (compiletimeSign)
5083 emitcode ("setb", "F0"); /* set sign flag */
5085 emitcode ("clr", "F0"); /* reset sign flag */
5088 /* save the signs of the operands */
5089 if (AOP_TYPE(right) == AOP_LIT)
5091 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5093 if (!rUnsigned && val < 0)
5094 emitcode ("mov", "b,#0x%02x", -val);
5096 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5098 else /* ! literal */
5101 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5104 MOVA (aopGet (right, 0, FALSE, FALSE));
5105 lbl = newiTempLabel (NULL);
5106 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5107 emitcode ("cpl", "F0"); /* complement sign flag */
5108 emitcode ("cpl", "a"); /* 2's complement */
5109 emitcode ("inc", "a");
5110 emitcode ("", "%05d$:", (lbl->key + 100));
5111 emitcode ("mov", "b,a");
5115 if (AOP_TYPE(left) == AOP_LIT)
5117 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5119 if (!lUnsigned && val < 0)
5120 emitcode ("mov", "a,#0x%02x", -val);
5122 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5124 else /* ! literal */
5126 MOVA (aopGet (left, 0, FALSE, FALSE));
5130 lbl = newiTempLabel (NULL);
5131 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5132 emitcode ("cpl", "F0"); /* complement sign flag */
5133 emitcode ("cpl", "a"); /* 2's complement */
5134 emitcode ("inc", "a");
5135 emitcode ("", "%05d$:", (lbl->key + 100));
5139 /* now the division */
5140 emitcode ("div", "ab");
5142 if (runtimeSign || compiletimeSign)
5144 lbl = newiTempLabel (NULL);
5146 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5147 emitcode ("cpl", "a"); /* lsb 2's complement */
5148 emitcode ("inc", "a");
5149 emitcode ("", "%05d$:", (lbl->key + 100));
5151 accuse = aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5154 /* msb is 0x00 or 0xff depending on the sign */
5159 emitcode ("push", "acc");
5162 emitcode ("mov", "c,F0");
5163 emitcode ("subb", "a,acc");
5165 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5167 else /* compiletimeSign */
5169 if (aopPutUsesAcc (result, "#0xFF", offset))
5171 emitcode ("push", "acc");
5175 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5181 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5183 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5187 emitcode ("pop", "acc");
5191 /*-----------------------------------------------------------------*/
5192 /* genDiv - generates code for division */
5193 /*-----------------------------------------------------------------*/
5197 operand *left = IC_LEFT (ic);
5198 operand *right = IC_RIGHT (ic);
5199 operand *result = IC_RESULT (ic);
5201 D(emitcode ("; genDiv",""));
5203 /* assign the amsops */
5204 aopOp (left, ic, FALSE);
5205 aopOp (right, ic, FALSE);
5206 aopOp (result, ic, TRUE);
5208 /* special cases first */
5210 if (AOP_TYPE (left) == AOP_CRY &&
5211 AOP_TYPE (right) == AOP_CRY)
5213 genDivbits (left, right, result);
5217 /* if both are of size == 1 */
5218 if (AOP_SIZE (left) == 1 &&
5219 AOP_SIZE (right) == 1)
5221 genDivOneByte (left, right, result);
5225 /* should have been converted to function call */
5228 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5229 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5230 freeAsmop (result, NULL, ic, TRUE);
5233 /*-----------------------------------------------------------------*/
5234 /* genModbits :- modulus of bits */
5235 /*-----------------------------------------------------------------*/
5237 genModbits (operand * left,
5244 D(emitcode ("; genModbits",""));
5248 /* the result must be bit */
5249 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5250 l = aopGet (left, 0, FALSE, FALSE);
5254 emitcode ("div", "ab");
5255 emitcode ("mov", "a,b");
5256 emitcode ("rrc", "a");
5260 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5263 /*-----------------------------------------------------------------*/
5264 /* genModOneByte : 8 bit modulus */
5265 /*-----------------------------------------------------------------*/
5267 genModOneByte (operand * left,
5271 bool lUnsigned, rUnsigned, pushedB;
5272 bool runtimeSign, compiletimeSign;
5276 D(emitcode ("; genModOneByte",""));
5278 size = AOP_SIZE (result) - 1;
5280 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5281 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5283 /* if right is a literal, check it for 2^n */
5284 if (AOP_TYPE(right) == AOP_LIT)
5286 unsigned char val = abs((int) operandLitValue(right));
5287 symbol *lbl2 = NULL;
5291 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5300 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5301 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5302 /* because iCode should have been changed to genAnd */
5303 /* see file "SDCCopt.c", function "convertToFcall()" */
5305 MOVA (aopGet (left, 0, FALSE, FALSE));
5306 emitcode ("mov", "c,acc.7");
5307 emitcode ("anl", "a,#0x%02x", val - 1);
5308 lbl = newiTempLabel (NULL);
5309 emitcode ("jz", "%05d$", (lbl->key + 100));
5310 emitcode ("jnc", "%05d$", (lbl->key + 100));
5311 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5317 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5319 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5320 lbl2 = newiTempLabel (NULL);
5321 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5323 emitcode ("", "%05d$:", (lbl->key + 100));
5324 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5326 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5329 emitcode ("", "%05d$:", (lbl2->key + 100));
5340 /* signed or unsigned */
5341 if (lUnsigned && rUnsigned)
5343 /* unsigned is easy */
5344 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5345 MOVA (aopGet (left, 0, FALSE, FALSE));
5346 emitcode ("div", "ab");
5347 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5349 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5355 /* signed is a little bit more difficult */
5357 /* now sign adjust for both left & right */
5359 /* modulus: sign of the right operand has no influence on the result! */
5360 if (AOP_TYPE(right) == AOP_LIT)
5362 signed char val = (char) operandLitValue(right);
5364 if (!rUnsigned && val < 0)
5365 emitcode ("mov", "b,#0x%02x", -val);
5367 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5369 else /* not literal */
5372 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5375 MOVA (aopGet (right, 0, FALSE, FALSE));
5376 lbl = newiTempLabel (NULL);
5377 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5378 emitcode ("cpl", "a"); /* 2's complement */
5379 emitcode ("inc", "a");
5380 emitcode ("", "%05d$:", (lbl->key + 100));
5381 emitcode ("mov", "b,a");
5385 /* let's see what's needed: */
5386 /* apply negative sign during runtime */
5387 runtimeSign = FALSE;
5388 /* negative sign from literals */
5389 compiletimeSign = FALSE;
5391 /* sign adjust left side */
5392 if (AOP_TYPE(left) == AOP_LIT)
5394 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5396 if (!lUnsigned && val < 0)
5398 compiletimeSign = TRUE; /* set sign flag */
5399 emitcode ("mov", "a,#0x%02x", -val);
5402 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5404 else /* ! literal */
5406 MOVA (aopGet (left, 0, FALSE, FALSE));
5411 emitcode ("clr", "F0"); /* clear sign flag */
5413 lbl = newiTempLabel (NULL);
5414 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5415 emitcode ("setb", "F0"); /* set sign flag */
5416 emitcode ("cpl", "a"); /* 2's complement */
5417 emitcode ("inc", "a");
5418 emitcode ("", "%05d$:", (lbl->key + 100));
5422 /* now the modulus */
5423 emitcode ("div", "ab");
5425 if (runtimeSign || compiletimeSign)
5427 emitcode ("mov", "a,b");
5428 lbl = newiTempLabel (NULL);
5430 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5431 emitcode ("cpl", "a"); /* 2's complement */
5432 emitcode ("inc", "a");
5433 emitcode ("", "%05d$:", (lbl->key + 100));
5435 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5438 /* msb is 0x00 or 0xff depending on the sign */
5441 emitcode ("mov", "c,F0");
5442 emitcode ("subb", "a,acc");
5444 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5446 else /* compiletimeSign */
5448 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5453 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5455 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5461 /*-----------------------------------------------------------------*/
5462 /* genMod - generates code for division */
5463 /*-----------------------------------------------------------------*/
5467 operand *left = IC_LEFT (ic);
5468 operand *right = IC_RIGHT (ic);
5469 operand *result = IC_RESULT (ic);
5471 D(emitcode ("; genMod",""));
5473 /* assign the asmops */
5474 aopOp (left, ic, FALSE);
5475 aopOp (right, ic, FALSE);
5476 aopOp (result, ic, TRUE);
5478 /* special cases first */
5480 if (AOP_TYPE (left) == AOP_CRY &&
5481 AOP_TYPE (right) == AOP_CRY)
5483 genModbits (left, right, result);
5487 /* if both are of size == 1 */
5488 if (AOP_SIZE (left) == 1 &&
5489 AOP_SIZE (right) == 1)
5491 genModOneByte (left, right, result);
5495 /* should have been converted to function call */
5499 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5500 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5501 freeAsmop (result, NULL, ic, TRUE);
5504 /*-----------------------------------------------------------------*/
5505 /* genIfxJump :- will create a jump depending on the ifx */
5506 /*-----------------------------------------------------------------*/
5508 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5511 symbol *tlbl = newiTempLabel (NULL);
5514 D(emitcode ("; genIfxJump",""));
5516 /* if true label then we jump if condition
5520 jlbl = IC_TRUE (ic);
5521 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5522 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5526 /* false label is present */
5527 jlbl = IC_FALSE (ic);
5528 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5529 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5531 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5532 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5534 emitcode (inst, "%05d$", tlbl->key + 100);
5535 freeForBranchAsmop (result);
5536 freeForBranchAsmop (right);
5537 freeForBranchAsmop (left);
5538 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5539 emitcode ("", "%05d$:", tlbl->key + 100);
5541 /* mark the icode as generated */
5545 /*-----------------------------------------------------------------*/
5546 /* genCmp :- greater or less than comparison */
5547 /*-----------------------------------------------------------------*/
5549 genCmp (operand * left, operand * right,
5550 operand * result, iCode * ifx, int sign, iCode *ic)
5552 int size, offset = 0;
5553 unsigned long lit = 0L;
5556 D(emitcode ("; genCmp",""));
5558 /* if left & right are bit variables */
5559 if (AOP_TYPE (left) == AOP_CRY &&
5560 AOP_TYPE (right) == AOP_CRY)
5562 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5563 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5567 /* subtract right from left if at the
5568 end the carry flag is set then we know that
5569 left is greater than right */
5570 size = max (AOP_SIZE (left), AOP_SIZE (right));
5572 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5573 if ((size == 1) && !sign &&
5574 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5576 symbol *lbl = newiTempLabel (NULL);
5577 emitcode ("cjne", "%s,%s,%05d$",
5578 aopGet (left, offset, FALSE, FALSE),
5579 aopGet (right, offset, FALSE, FALSE),
5581 emitcode ("", "%05d$:", lbl->key + 100);
5585 if (AOP_TYPE (right) == AOP_LIT)
5587 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5588 /* optimize if(x < 0) or if(x >= 0) */
5597 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5598 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5600 genIfxJump (ifx, "acc.7", left, right, result);
5601 freeAsmop (right, NULL, ic, TRUE);
5602 freeAsmop (left, NULL, ic, TRUE);
5607 emitcode ("rlc", "a");
5615 bool pushedB = FALSE;
5616 rightInB = aopGetUsesAcc(right, offset);
5620 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5622 MOVA (aopGet (left, offset, FALSE, FALSE));
5623 if (sign && size == 0)
5625 emitcode ("xrl", "a,#0x80");
5626 if (AOP_TYPE (right) == AOP_LIT)
5628 unsigned long lit = (unsigned long)
5629 floatFromVal (AOP (right)->aopu.aop_lit);
5630 emitcode ("subb", "a,#0x%02x",
5631 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5639 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5641 emitcode ("xrl", "b,#0x80");
5642 emitcode ("subb", "a,b");
5648 emitcode ("subb", "a,b");
5650 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5660 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5661 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5662 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5668 /* if the result is used in the next
5669 ifx conditional branch then generate
5670 code a little differently */
5672 genIfxJump (ifx, "c", NULL, NULL, result);
5675 /* leave the result in acc */
5679 /*-----------------------------------------------------------------*/
5680 /* genCmpGt :- greater than comparison */
5681 /*-----------------------------------------------------------------*/
5683 genCmpGt (iCode * ic, iCode * ifx)
5685 operand *left, *right, *result;
5686 sym_link *letype, *retype;
5689 D(emitcode ("; genCmpGt",""));
5691 left = IC_LEFT (ic);
5692 right = IC_RIGHT (ic);
5693 result = IC_RESULT (ic);
5695 letype = getSpec (operandType (left));
5696 retype = getSpec (operandType (right));
5697 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5698 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5699 /* assign the amsops */
5700 aopOp (left, ic, FALSE);
5701 aopOp (right, ic, FALSE);
5702 aopOp (result, ic, TRUE);
5704 genCmp (right, left, result, ifx, sign, ic);
5706 freeAsmop (result, NULL, ic, TRUE);
5709 /*-----------------------------------------------------------------*/
5710 /* genCmpLt - less than comparisons */
5711 /*-----------------------------------------------------------------*/
5713 genCmpLt (iCode * ic, iCode * ifx)
5715 operand *left, *right, *result;
5716 sym_link *letype, *retype;
5719 D(emitcode ("; genCmpLt",""));
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 (left, right, result, ifx, sign, ic);
5736 freeAsmop (result, NULL, ic, TRUE);
5739 /*-----------------------------------------------------------------*/
5740 /* gencjneshort - compare and jump if not equal */
5741 /*-----------------------------------------------------------------*/
5743 gencjneshort (operand * left, operand * right, symbol * lbl)
5745 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5747 unsigned long lit = 0L;
5749 /* if the left side is a literal or
5750 if the right is in a pointer register and left
5752 if ((AOP_TYPE (left) == AOP_LIT) ||
5753 (AOP_TYPE (left) == AOP_IMMD) ||
5754 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5761 if (AOP_TYPE (right) == AOP_LIT)
5762 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5764 /* if the right side is a literal then anything goes */
5765 if (AOP_TYPE (right) == AOP_LIT &&
5766 AOP_TYPE (left) != AOP_DIR &&
5767 AOP_TYPE (left) != AOP_IMMD)
5771 emitcode ("cjne", "%s,%s,%05d$",
5772 aopGet (left, offset, FALSE, FALSE),
5773 aopGet (right, offset, FALSE, FALSE),
5779 /* if the right side is in a register or in direct space or
5780 if the left is a pointer register & right is not */
5781 else if (AOP_TYPE (right) == AOP_REG ||
5782 AOP_TYPE (right) == AOP_DIR ||
5783 AOP_TYPE (right) == AOP_LIT ||
5784 AOP_TYPE (right) == AOP_IMMD ||
5785 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5786 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5790 MOVA (aopGet (left, offset, FALSE, FALSE));
5791 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5792 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5793 emitcode ("jnz", "%05d$", lbl->key + 100);
5795 emitcode ("cjne", "a,%s,%05d$",
5796 aopGet (right, offset, FALSE, TRUE),
5803 /* right is a pointer reg need both a & b */
5807 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5808 wassertl(!BINUSE, "B was in use");
5809 l = aopGet (left, offset, FALSE, FALSE);
5810 if (strcmp (l, "b"))
5811 emitcode ("mov", "b,%s", l);
5812 MOVA (aopGet (right, offset, FALSE, FALSE));
5813 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5819 /*-----------------------------------------------------------------*/
5820 /* gencjne - compare and jump if not equal */
5821 /*-----------------------------------------------------------------*/
5823 gencjne (operand * left, operand * right, symbol * lbl)
5825 symbol *tlbl = newiTempLabel (NULL);
5827 gencjneshort (left, right, lbl);
5829 emitcode ("mov", "a,%s", one);
5830 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5831 emitcode ("", "%05d$:", lbl->key + 100);
5832 emitcode ("clr", "a");
5833 emitcode ("", "%05d$:", tlbl->key + 100);
5836 /*-----------------------------------------------------------------*/
5837 /* genCmpEq - generates code for equal to */
5838 /*-----------------------------------------------------------------*/
5840 genCmpEq (iCode * ic, iCode * ifx)
5842 operand *left, *right, *result;
5844 D(emitcode ("; genCmpEq",""));
5846 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5847 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5848 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5850 /* if literal, literal on the right or
5851 if the right is in a pointer register and left
5853 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5854 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5856 operand *t = IC_RIGHT (ic);
5857 IC_RIGHT (ic) = IC_LEFT (ic);
5861 if (ifx && !AOP_SIZE (result))
5864 /* if they are both bit variables */
5865 if (AOP_TYPE (left) == AOP_CRY &&
5866 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5868 if (AOP_TYPE (right) == AOP_LIT)
5870 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5873 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5874 emitcode ("cpl", "c");
5878 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5882 emitcode ("clr", "c");
5884 /* AOP_TYPE(right) == AOP_CRY */
5888 symbol *lbl = newiTempLabel (NULL);
5889 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5890 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5891 emitcode ("cpl", "c");
5892 emitcode ("", "%05d$:", (lbl->key + 100));
5894 /* if true label then we jump if condition
5896 tlbl = newiTempLabel (NULL);
5899 emitcode ("jnc", "%05d$", tlbl->key + 100);
5900 freeForBranchAsmop (result);
5901 freeForBranchAsmop (right);
5902 freeForBranchAsmop (left);
5903 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5907 emitcode ("jc", "%05d$", tlbl->key + 100);
5908 freeForBranchAsmop (result);
5909 freeForBranchAsmop (right);
5910 freeForBranchAsmop (left);
5911 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5913 emitcode ("", "%05d$:", tlbl->key + 100);
5917 tlbl = newiTempLabel (NULL);
5918 gencjneshort (left, right, tlbl);
5921 freeForBranchAsmop (result);
5922 freeForBranchAsmop (right);
5923 freeForBranchAsmop (left);
5924 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5925 emitcode ("", "%05d$:", tlbl->key + 100);
5929 symbol *lbl = newiTempLabel (NULL);
5930 emitcode ("sjmp", "%05d$", lbl->key + 100);
5931 emitcode ("", "%05d$:", tlbl->key + 100);
5932 freeForBranchAsmop (result);
5933 freeForBranchAsmop (right);
5934 freeForBranchAsmop (left);
5935 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5936 emitcode ("", "%05d$:", lbl->key + 100);
5939 /* mark the icode as generated */
5944 /* if they are both bit variables */
5945 if (AOP_TYPE (left) == AOP_CRY &&
5946 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5948 if (AOP_TYPE (right) == AOP_LIT)
5950 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5953 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5954 emitcode ("cpl", "c");
5958 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5962 emitcode ("clr", "c");
5964 /* AOP_TYPE(right) == AOP_CRY */
5968 symbol *lbl = newiTempLabel (NULL);
5969 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5970 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5971 emitcode ("cpl", "c");
5972 emitcode ("", "%05d$:", (lbl->key + 100));
5975 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5982 genIfxJump (ifx, "c", left, right, result);
5985 /* if the result is used in an arithmetic operation
5986 then put the result in place */
5991 gencjne (left, right, newiTempLabel (NULL));
5992 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5994 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5999 genIfxJump (ifx, "a", left, right, result);
6002 /* if the result is used in an arithmetic operation
6003 then put the result in place */
6004 if (AOP_TYPE (result) != AOP_CRY)
6006 /* leave the result in acc */
6010 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6011 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6012 freeAsmop (result, NULL, ic, TRUE);
6015 /*-----------------------------------------------------------------*/
6016 /* ifxForOp - returns the icode containing the ifx for operand */
6017 /*-----------------------------------------------------------------*/
6019 ifxForOp (operand * op, iCode * ic)
6021 /* if true symbol then needs to be assigned */
6022 if (IS_TRUE_SYMOP (op))
6025 /* if this has register type condition and
6026 the next instruction is ifx with the same operand
6027 and live to of the operand is upto the ifx only then */
6029 ic->next->op == IFX &&
6030 IC_COND (ic->next)->key == op->key &&
6031 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6037 /*-----------------------------------------------------------------*/
6038 /* hasInc - operand is incremented before any other use */
6039 /*-----------------------------------------------------------------*/
6041 hasInc (operand *op, iCode *ic,int osize)
6043 sym_link *type = operandType(op);
6044 sym_link *retype = getSpec (type);
6045 iCode *lic = ic->next;
6048 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6049 if (!IS_SYMOP(op)) return NULL;
6051 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6052 if (IS_AGGREGATE(type->next)) return NULL;
6053 if (osize != (isize = getSize(type->next))) return NULL;
6056 /* if operand of the form op = op + <sizeof *op> */
6057 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6058 isOperandEqual(IC_RESULT(lic),op) &&
6059 isOperandLiteral(IC_RIGHT(lic)) &&
6060 operandLitValue(IC_RIGHT(lic)) == isize) {
6063 /* if the operand used or deffed */
6064 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6067 /* if GOTO or IFX */
6068 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6074 /*-----------------------------------------------------------------*/
6075 /* genAndOp - for && operation */
6076 /*-----------------------------------------------------------------*/
6078 genAndOp (iCode * ic)
6080 operand *left, *right, *result;
6083 D(emitcode ("; genAndOp",""));
6085 /* note here that && operations that are in an
6086 if statement are taken away by backPatchLabels
6087 only those used in arthmetic operations remain */
6088 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6089 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6090 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6092 /* if both are bit variables */
6093 if (AOP_TYPE (left) == AOP_CRY &&
6094 AOP_TYPE (right) == AOP_CRY)
6096 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6097 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6102 tlbl = newiTempLabel (NULL);
6104 emitcode ("jz", "%05d$", tlbl->key + 100);
6106 emitcode ("", "%05d$:", tlbl->key + 100);
6110 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6111 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6112 freeAsmop (result, NULL, ic, TRUE);
6116 /*-----------------------------------------------------------------*/
6117 /* genOrOp - for || operation */
6118 /*-----------------------------------------------------------------*/
6120 genOrOp (iCode * ic)
6122 operand *left, *right, *result;
6125 D(emitcode ("; genOrOp",""));
6127 /* note here that || operations that are in an
6128 if statement are taken away by backPatchLabels
6129 only those used in arthmetic operations remain */
6130 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6131 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6132 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6134 /* if both are bit variables */
6135 if (AOP_TYPE (left) == AOP_CRY &&
6136 AOP_TYPE (right) == AOP_CRY)
6138 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6139 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6144 tlbl = newiTempLabel (NULL);
6146 emitcode ("jnz", "%05d$", tlbl->key + 100);
6148 emitcode ("", "%05d$:", tlbl->key + 100);
6152 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6153 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6154 freeAsmop (result, NULL, ic, TRUE);
6157 /*-----------------------------------------------------------------*/
6158 /* isLiteralBit - test if lit == 2^n */
6159 /*-----------------------------------------------------------------*/
6161 isLiteralBit (unsigned long lit)
6163 unsigned long pw[32] =
6164 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6165 0x100L, 0x200L, 0x400L, 0x800L,
6166 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6167 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6168 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6169 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6170 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6173 for (idx = 0; idx < 32; idx++)
6179 /*-----------------------------------------------------------------*/
6180 /* continueIfTrue - */
6181 /*-----------------------------------------------------------------*/
6183 continueIfTrue (iCode * ic)
6186 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6190 /*-----------------------------------------------------------------*/
6192 /*-----------------------------------------------------------------*/
6194 jumpIfTrue (iCode * ic)
6197 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6201 /*-----------------------------------------------------------------*/
6202 /* jmpTrueOrFalse - */
6203 /*-----------------------------------------------------------------*/
6205 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6207 // ugly but optimized by peephole
6210 symbol *nlbl = newiTempLabel (NULL);
6211 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6212 emitcode ("", "%05d$:", tlbl->key + 100);
6213 freeForBranchAsmop (result);
6214 freeForBranchAsmop (right);
6215 freeForBranchAsmop (left);
6216 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6217 emitcode ("", "%05d$:", nlbl->key + 100);
6221 freeForBranchAsmop (result);
6222 freeForBranchAsmop (right);
6223 freeForBranchAsmop (left);
6224 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6225 emitcode ("", "%05d$:", tlbl->key + 100);
6230 /*-----------------------------------------------------------------*/
6231 /* genAnd - code for and */
6232 /*-----------------------------------------------------------------*/
6234 genAnd (iCode * ic, iCode * ifx)
6236 operand *left, *right, *result;
6237 int size, offset = 0;
6238 unsigned long lit = 0L;
6242 D(emitcode ("; genAnd",""));
6244 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6245 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6246 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6249 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6251 AOP_TYPE (left), AOP_TYPE (right));
6252 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6254 AOP_SIZE (left), AOP_SIZE (right));
6257 /* if left is a literal & right is not then exchange them */
6258 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6259 AOP_NEEDSACC (left))
6261 operand *tmp = right;
6266 /* if result = right then exchange left and right */
6267 if (sameRegs (AOP (result), AOP (right)))
6269 operand *tmp = right;
6274 /* if right is bit then exchange them */
6275 if (AOP_TYPE (right) == AOP_CRY &&
6276 AOP_TYPE (left) != AOP_CRY)
6278 operand *tmp = right;
6282 if (AOP_TYPE (right) == AOP_LIT)
6283 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6285 size = AOP_SIZE (result);
6288 // result = bit & yy;
6289 if (AOP_TYPE (left) == AOP_CRY)
6291 // c = bit & literal;
6292 if (AOP_TYPE (right) == AOP_LIT)
6296 if (size && sameRegs (AOP (result), AOP (left)))
6299 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6304 if (size && (AOP_TYPE (result) == AOP_CRY))
6306 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6309 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6314 emitcode ("clr", "c");
6319 if (AOP_TYPE (right) == AOP_CRY)
6322 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6323 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6328 MOVA (aopGet (right, 0, FALSE, FALSE));
6330 emitcode ("rrc", "a");
6331 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6339 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6340 genIfxJump (ifx, "c", left, right, result);
6344 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6345 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6346 if ((AOP_TYPE (right) == AOP_LIT) &&
6347 (AOP_TYPE (result) == AOP_CRY) &&
6348 (AOP_TYPE (left) != AOP_CRY))
6350 int posbit = isLiteralBit (lit);
6355 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6359 switch (posbit & 0x07)
6361 case 0: emitcode ("rrc", "a");
6363 case 7: emitcode ("rlc", "a");
6365 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6374 SNPRINTF (buffer, sizeof(buffer),
6375 "acc.%d", posbit & 0x07);
6376 genIfxJump (ifx, buffer, left, right, result);
6379 {// what is this case? just found it in ds390/gen.c
6380 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6387 symbol *tlbl = newiTempLabel (NULL);
6388 int sizel = AOP_SIZE (left);
6390 emitcode ("setb", "c");
6393 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6395 MOVA (aopGet (left, offset, FALSE, FALSE));
6397 if ((posbit = isLiteralBit (bytelit)) != 0)
6398 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6401 if (bytelit != 0x0FFL)
6402 emitcode ("anl", "a,%s",
6403 aopGet (right, offset, FALSE, TRUE));
6404 emitcode ("jnz", "%05d$", tlbl->key + 100);
6409 // bit = left & literal
6412 emitcode ("clr", "c");
6413 emitcode ("", "%05d$:", tlbl->key + 100);
6415 // if(left & literal)
6419 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6421 emitcode ("", "%05d$:", tlbl->key + 100);
6429 /* if left is same as result */
6430 if (sameRegs (AOP (result), AOP (left)))
6432 for (; size--; offset++)
6434 if (AOP_TYPE (right) == AOP_LIT)
6436 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6437 if (bytelit == 0x0FF)
6439 /* dummy read of volatile operand */
6440 if (isOperandVolatile (left, FALSE))
6441 MOVA (aopGet (left, offset, FALSE, FALSE));
6445 else if (bytelit == 0)
6447 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6449 else if (IS_AOP_PREG (result))
6451 MOVA (aopGet (left, offset, FALSE, TRUE));
6452 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6453 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6456 emitcode ("anl", "%s,%s",
6457 aopGet (left, offset, FALSE, TRUE),
6458 aopGet (right, offset, FALSE, FALSE));
6462 if (AOP_TYPE (left) == AOP_ACC)
6465 emitcode("mov", "a,b");
6466 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6468 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6470 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6471 MOVA (aopGet (right, offset, FALSE, FALSE));
6472 emitcode ("anl", "a,b");
6473 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6475 else if (aopGetUsesAcc (left, offset))
6477 MOVA (aopGet (left, offset, FALSE, FALSE));
6478 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6479 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6483 MOVA (aopGet (right, offset, FALSE, FALSE));
6484 if (IS_AOP_PREG (result))
6486 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6487 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6490 emitcode ("anl", "%s,a",
6491 aopGet (left, offset, FALSE, TRUE));
6498 // left & result in different registers
6499 if (AOP_TYPE (result) == AOP_CRY)
6502 // if(size), result in bit
6503 // if(!size && ifx), conditional oper: if(left & right)
6504 symbol *tlbl = newiTempLabel (NULL);
6505 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6507 emitcode ("setb", "c");
6510 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6511 && AOP_TYPE(left)==AOP_ACC)
6514 emitcode("mov", "a,b");
6515 emitcode ("anl", "a,%s",
6516 aopGet (right, offset, FALSE, FALSE));
6518 if (AOP_TYPE(left)==AOP_ACC)
6522 bool pushedB = pushB ();
6523 emitcode("mov", "b,a");
6524 MOVA (aopGet (right, offset, FALSE, FALSE));
6525 emitcode("anl", "a,b");
6530 MOVA (aopGet (right, offset, FALSE, FALSE));
6531 emitcode("anl", "a,b");
6534 MOVA (aopGet (right, offset, FALSE, FALSE));
6535 emitcode ("anl", "a,%s",
6536 aopGet (left, offset, FALSE, FALSE));
6539 emitcode ("jnz", "%05d$", tlbl->key + 100);
6545 emitcode ("", "%05d$:", tlbl->key + 100);
6549 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6551 emitcode ("", "%05d$:", tlbl->key + 100);
6555 for (; (size--); offset++)
6558 // result = left & right
6559 if (AOP_TYPE (right) == AOP_LIT)
6561 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6562 if (bytelit == 0x0FF)
6565 aopGet (left, offset, FALSE, FALSE),
6567 isOperandVolatile (result, FALSE));
6570 else if (bytelit == 0)
6572 /* dummy read of volatile operand */
6573 if (isOperandVolatile (left, FALSE))
6574 MOVA (aopGet (left, offset, FALSE, FALSE));
6575 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6578 else if (AOP_TYPE (left) == AOP_ACC)
6582 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6583 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6588 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6589 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6594 // faster than result <- left, anl result,right
6595 // and better if result is SFR
6596 if (AOP_TYPE (left) == AOP_ACC)
6599 emitcode("mov", "a,b");
6600 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6602 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6604 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6605 MOVA (aopGet (right, offset, FALSE, FALSE));
6606 emitcode ("anl", "a,b");
6608 else if (aopGetUsesAcc (left, offset))
6610 MOVA (aopGet (left, offset, FALSE, FALSE));
6611 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6615 MOVA (aopGet (right, offset, FALSE, FALSE));
6616 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6618 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6624 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6625 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6626 freeAsmop (result, NULL, ic, TRUE);
6629 /*-----------------------------------------------------------------*/
6630 /* genOr - code for or */
6631 /*-----------------------------------------------------------------*/
6633 genOr (iCode * ic, iCode * ifx)
6635 operand *left, *right, *result;
6636 int size, offset = 0;
6637 unsigned long lit = 0L;
6640 D(emitcode ("; genOr",""));
6642 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6643 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6644 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6647 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6649 AOP_TYPE (left), AOP_TYPE (right));
6650 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6652 AOP_SIZE (left), AOP_SIZE (right));
6655 /* if left is a literal & right is not then exchange them */
6656 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6657 AOP_NEEDSACC (left))
6659 operand *tmp = right;
6664 /* if result = right then exchange them */
6665 if (sameRegs (AOP (result), AOP (right)))
6667 operand *tmp = right;
6672 /* if right is bit then exchange them */
6673 if (AOP_TYPE (right) == AOP_CRY &&
6674 AOP_TYPE (left) != AOP_CRY)
6676 operand *tmp = right;
6680 if (AOP_TYPE (right) == AOP_LIT)
6681 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6683 size = AOP_SIZE (result);
6687 if (AOP_TYPE (left) == AOP_CRY)
6689 if (AOP_TYPE (right) == AOP_LIT)
6691 // c = bit | literal;
6694 // lit != 0 => result = 1
6695 if (AOP_TYPE (result) == AOP_CRY)
6698 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6700 continueIfTrue (ifx);
6703 emitcode ("setb", "c");
6707 // lit == 0 => result = left
6708 if (size && sameRegs (AOP (result), AOP (left)))
6710 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6715 if (AOP_TYPE (right) == AOP_CRY)
6718 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6719 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6724 symbol *tlbl = newiTempLabel (NULL);
6725 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6726 emitcode ("setb", "c");
6727 emitcode ("jb", "%s,%05d$",
6728 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6730 emitcode ("jnz", "%05d$", tlbl->key + 100);
6731 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6733 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6739 emitcode ("", "%05d$:", tlbl->key + 100);
6748 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6749 genIfxJump (ifx, "c", left, right, result);
6753 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6754 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6755 if ((AOP_TYPE (right) == AOP_LIT) &&
6756 (AOP_TYPE (result) == AOP_CRY) &&
6757 (AOP_TYPE (left) != AOP_CRY))
6763 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6765 continueIfTrue (ifx);
6770 // lit = 0, result = boolean(left)
6772 emitcode ("setb", "c");
6776 symbol *tlbl = newiTempLabel (NULL);
6777 emitcode ("jnz", "%05d$", tlbl->key + 100);
6779 emitcode ("", "%05d$:", tlbl->key + 100);
6783 genIfxJump (ifx, "a", left, right, result);
6791 /* if left is same as result */
6792 if (sameRegs (AOP (result), AOP (left)))
6794 for (; size--; offset++)
6796 if (AOP_TYPE (right) == AOP_LIT)
6798 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6801 /* dummy read of volatile operand */
6802 if (isOperandVolatile (left, FALSE))
6803 MOVA (aopGet (left, offset, FALSE, FALSE));
6807 else if (bytelit == 0x0FF)
6809 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6811 else if (IS_AOP_PREG (left))
6813 MOVA (aopGet (left, offset, FALSE, TRUE));
6814 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6815 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6819 emitcode ("orl", "%s,%s",
6820 aopGet (left, offset, FALSE, TRUE),
6821 aopGet (right, offset, FALSE, FALSE));
6826 if (AOP_TYPE (left) == AOP_ACC)
6829 emitcode("mov", "a,b");
6830 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6832 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6834 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6835 MOVA (aopGet (right, offset, FALSE, FALSE));
6836 emitcode ("orl", "a,b");
6837 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6839 else if (aopGetUsesAcc (left, offset))
6841 MOVA (aopGet (left, offset, FALSE, FALSE));
6842 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6843 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6847 MOVA (aopGet (right, offset, FALSE, FALSE));
6848 if (IS_AOP_PREG (left))
6850 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6851 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6855 emitcode ("orl", "%s,a",
6856 aopGet (left, offset, FALSE, TRUE));
6864 // left & result in different registers
6865 if (AOP_TYPE (result) == AOP_CRY)
6868 // if(size), result in bit
6869 // if(!size && ifx), conditional oper: if(left | right)
6870 symbol *tlbl = newiTempLabel (NULL);
6871 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6873 emitcode ("setb", "c");
6876 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6878 emitcode("mov", "a,b");
6879 emitcode ("orl", "a,%s",
6880 aopGet (right, offset, FALSE, FALSE));
6882 MOVA (aopGet (right, offset, FALSE, FALSE));
6883 emitcode ("orl", "a,%s",
6884 aopGet (left, offset, FALSE, FALSE));
6886 emitcode ("jnz", "%05d$", tlbl->key + 100);
6892 emitcode ("", "%05d$:", tlbl->key + 100);
6896 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6898 emitcode ("", "%05d$:", tlbl->key + 100);
6902 for (; (size--); offset++)
6905 // result = left | right
6906 if (AOP_TYPE (right) == AOP_LIT)
6908 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6912 aopGet (left, offset, FALSE, FALSE),
6914 isOperandVolatile (result, FALSE));
6917 else if (bytelit == 0x0FF)
6919 /* dummy read of volatile operand */
6920 if (isOperandVolatile (left, FALSE))
6921 MOVA (aopGet (left, offset, FALSE, FALSE));
6922 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6926 // faster than result <- left, anl result,right
6927 // and better if result is SFR
6928 if (AOP_TYPE (left) == AOP_ACC)
6931 emitcode("mov", "a,b");
6932 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6934 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6936 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6937 MOVA (aopGet (right, offset, FALSE, FALSE));
6938 emitcode ("orl", "a,b");
6940 else if (aopGetUsesAcc (left, offset))
6942 MOVA (aopGet (left, offset, FALSE, FALSE));
6943 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6947 MOVA (aopGet (right, offset, FALSE, FALSE));
6948 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6950 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6956 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6957 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6958 freeAsmop (result, NULL, ic, TRUE);
6961 /*-----------------------------------------------------------------*/
6962 /* genXor - code for xclusive or */
6963 /*-----------------------------------------------------------------*/
6965 genXor (iCode * ic, iCode * ifx)
6967 operand *left, *right, *result;
6968 int size, offset = 0;
6969 unsigned long lit = 0L;
6972 D(emitcode ("; genXor",""));
6974 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6975 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6976 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6979 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6981 AOP_TYPE (left), AOP_TYPE (right));
6982 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6984 AOP_SIZE (left), AOP_SIZE (right));
6987 /* if left is a literal & right is not ||
6988 if left needs acc & right does not */
6989 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6990 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6992 operand *tmp = right;
6997 /* if result = right then exchange them */
6998 if (sameRegs (AOP (result), AOP (right)))
7000 operand *tmp = right;
7005 /* if right is bit then exchange them */
7006 if (AOP_TYPE (right) == AOP_CRY &&
7007 AOP_TYPE (left) != AOP_CRY)
7009 operand *tmp = right;
7013 if (AOP_TYPE (right) == AOP_LIT)
7014 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7016 size = AOP_SIZE (result);
7020 if (AOP_TYPE (left) == AOP_CRY)
7022 if (AOP_TYPE (right) == AOP_LIT)
7024 // c = bit & literal;
7027 // lit>>1 != 0 => result = 1
7028 if (AOP_TYPE (result) == AOP_CRY)
7031 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7033 continueIfTrue (ifx);
7036 emitcode ("setb", "c");
7043 // lit == 0, result = left
7044 if (size && sameRegs (AOP (result), AOP (left)))
7046 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7050 // lit == 1, result = not(left)
7051 if (size && sameRegs (AOP (result), AOP (left)))
7053 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7058 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7059 emitcode ("cpl", "c");
7068 symbol *tlbl = newiTempLabel (NULL);
7069 if (AOP_TYPE (right) == AOP_CRY)
7072 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7076 int sizer = AOP_SIZE (right);
7078 // if val>>1 != 0, result = 1
7079 emitcode ("setb", "c");
7082 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7084 // test the msb of the lsb
7085 emitcode ("anl", "a,#0xfe");
7086 emitcode ("jnz", "%05d$", tlbl->key + 100);
7090 emitcode ("rrc", "a");
7092 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7093 emitcode ("cpl", "c");
7094 emitcode ("", "%05d$:", (tlbl->key + 100));
7101 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7102 genIfxJump (ifx, "c", left, right, result);
7106 /* if left is same as result */
7107 if (sameRegs (AOP (result), AOP (left)))
7109 for (; size--; offset++)
7111 if (AOP_TYPE (right) == AOP_LIT)
7113 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7116 /* dummy read of volatile operand */
7117 if (isOperandVolatile (left, FALSE))
7118 MOVA (aopGet (left, offset, FALSE, FALSE));
7122 else if (IS_AOP_PREG (left))
7124 MOVA (aopGet (left, offset, FALSE, TRUE));
7125 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7126 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7130 emitcode ("xrl", "%s,%s",
7131 aopGet (left, offset, FALSE, TRUE),
7132 aopGet (right, offset, FALSE, FALSE));
7137 if (AOP_TYPE (left) == AOP_ACC)
7140 emitcode("mov", "a,b");
7141 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7143 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7145 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7146 MOVA (aopGet (right, offset, FALSE, FALSE));
7147 emitcode ("xrl", "a,b");
7148 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7150 else if (aopGetUsesAcc (left, offset))
7152 MOVA (aopGet (left, offset, FALSE, FALSE));
7153 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7154 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7158 MOVA (aopGet (right, offset, FALSE, FALSE));
7159 if (IS_AOP_PREG (left))
7161 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7162 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7165 emitcode ("xrl", "%s,a",
7166 aopGet (left, offset, FALSE, TRUE));
7173 // left & result in different registers
7174 if (AOP_TYPE (result) == AOP_CRY)
7177 // if(size), result in bit
7178 // if(!size && ifx), conditional oper: if(left ^ right)
7179 symbol *tlbl = newiTempLabel (NULL);
7180 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7182 emitcode ("setb", "c");
7185 if ((AOP_TYPE (right) == AOP_LIT) &&
7186 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7188 MOVA (aopGet (left, offset, FALSE, FALSE));
7192 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7194 emitcode("mov", "a,b");
7195 emitcode ("xrl", "a,%s",
7196 aopGet (right, offset, FALSE, FALSE));
7198 MOVA (aopGet (right, offset, FALSE, FALSE));
7199 emitcode ("xrl", "a,%s",
7200 aopGet (left, offset, FALSE, FALSE));
7203 emitcode ("jnz", "%05d$", tlbl->key + 100);
7209 emitcode ("", "%05d$:", tlbl->key + 100);
7213 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7217 for (; (size--); offset++)
7220 // result = left & right
7221 if (AOP_TYPE (right) == AOP_LIT)
7223 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7227 aopGet (left, offset, FALSE, FALSE),
7229 isOperandVolatile (result, FALSE));
7233 // faster than result <- left, anl result,right
7234 // and better if result is SFR
7235 if (AOP_TYPE (left) == AOP_ACC)
7238 emitcode("mov", "a,b");
7239 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7241 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7243 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7244 MOVA (aopGet (right, offset, FALSE, FALSE));
7245 emitcode ("xrl", "a,b");
7247 else if (aopGetUsesAcc (left, offset))
7249 MOVA (aopGet (left, offset, FALSE, FALSE));
7250 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7254 MOVA (aopGet (right, offset, FALSE, FALSE));
7255 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7257 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7263 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7264 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7265 freeAsmop (result, NULL, ic, TRUE);
7268 /*-----------------------------------------------------------------*/
7269 /* genInline - write the inline code out */
7270 /*-----------------------------------------------------------------*/
7272 genInline (iCode * ic)
7274 char *buffer, *bp, *bp1;
7276 D(emitcode ("; genInline",""));
7278 _G.inLine += (!options.asmpeep);
7280 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7281 strcpy (buffer, IC_INLINE (ic));
7283 /* emit each line as a code */
7294 /* Add \n for labels, not dirs such as c:\mydir */
7295 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7309 /* emitcode("",buffer); */
7310 _G.inLine -= (!options.asmpeep);
7313 /*-----------------------------------------------------------------*/
7314 /* genRRC - rotate right with carry */
7315 /*-----------------------------------------------------------------*/
7319 operand *left, *result;
7320 int size, offset = 0;
7323 D(emitcode ("; genRRC",""));
7325 /* rotate right with carry */
7326 left = IC_LEFT (ic);
7327 result = IC_RESULT (ic);
7328 aopOp (left, ic, FALSE);
7329 aopOp (result, ic, FALSE);
7331 /* move it to the result */
7332 size = AOP_SIZE (result);
7334 if (size == 1) { /* special case for 1 byte */
7335 l = aopGet (left, offset, FALSE, FALSE);
7337 emitcode ("rr", "a");
7340 /* no need to clear carry, bit7 will be written later */
7343 l = aopGet (left, offset, FALSE, FALSE);
7345 emitcode ("rrc", "a");
7346 if (AOP_SIZE (result) > 1)
7347 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7349 /* now we need to put the carry into the
7350 highest order byte of the result */
7351 if (AOP_SIZE (result) > 1)
7353 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7356 emitcode ("mov", "acc.7,c");
7358 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7359 freeAsmop (left, NULL, ic, TRUE);
7360 freeAsmop (result, NULL, ic, TRUE);
7363 /*-----------------------------------------------------------------*/
7364 /* genRLC - generate code for rotate left with carry */
7365 /*-----------------------------------------------------------------*/
7369 operand *left, *result;
7370 int size, offset = 0;
7373 D(emitcode ("; genRLC",""));
7375 /* rotate right with carry */
7376 left = IC_LEFT (ic);
7377 result = IC_RESULT (ic);
7378 aopOp (left, ic, FALSE);
7379 aopOp (result, ic, FALSE);
7381 /* move it to the result */
7382 size = AOP_SIZE (result);
7386 l = aopGet (left, offset, FALSE, FALSE);
7388 if (size == 0) { /* special case for 1 byte */
7392 emitcode("rlc","a"); /* bit0 will be written later */
7393 if (AOP_SIZE (result) > 1)
7394 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7397 l = aopGet (left, offset, FALSE, FALSE);
7399 emitcode ("rlc", "a");
7400 if (AOP_SIZE (result) > 1)
7401 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7404 /* now we need to put the carry into the
7405 highest order byte of the result */
7406 if (AOP_SIZE (result) > 1)
7408 l = aopGet (result, 0, FALSE, FALSE);
7411 emitcode ("mov", "acc.0,c");
7413 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7414 freeAsmop (left, NULL, ic, TRUE);
7415 freeAsmop (result, NULL, ic, TRUE);
7418 /*-----------------------------------------------------------------*/
7419 /* genGetHbit - generates code get highest order bit */
7420 /*-----------------------------------------------------------------*/
7422 genGetHbit (iCode * ic)
7424 operand *left, *result;
7426 D(emitcode ("; genGetHbit",""));
7428 left = IC_LEFT (ic);
7429 result = IC_RESULT (ic);
7430 aopOp (left, ic, FALSE);
7431 aopOp (result, ic, FALSE);
7433 /* get the highest order byte into a */
7434 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7435 if (AOP_TYPE (result) == AOP_CRY)
7437 emitcode ("rlc", "a");
7442 emitcode ("rl", "a");
7443 emitcode ("anl", "a,#0x01");
7448 freeAsmop (left, NULL, ic, TRUE);
7449 freeAsmop (result, NULL, ic, TRUE);
7452 /*-----------------------------------------------------------------*/
7453 /* genGetAbit - generates code get a single bit */
7454 /*-----------------------------------------------------------------*/
7456 genGetAbit (iCode * ic)
7458 operand *left, *right, *result;
7461 D(emitcode ("; genGetAbit",""));
7463 left = IC_LEFT (ic);
7464 right = IC_RIGHT (ic);
7465 result = IC_RESULT (ic);
7466 aopOp (left, ic, FALSE);
7467 aopOp (right, ic, FALSE);
7468 aopOp (result, ic, FALSE);
7470 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7472 /* get the needed byte into a */
7473 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7475 if (AOP_TYPE (result) == AOP_CRY)
7478 emitcode ("rlc", "a");
7479 else if ((shCount) == 0)
7480 emitcode ("rrc", "a");
7482 emitcode ("mov", "c,acc[%d]", shCount);
7490 emitcode ("rr", "a");
7493 emitcode ("rr", "a");
7496 emitcode ("anl", "a,#0x01");
7500 emitcode ("mov", "c,acc[%d]", shCount);
7501 emitcode ("clr", "a");
7502 emitcode ("rlc", "a");
7505 emitcode ("swap", "a");
7506 emitcode ("anl", "a,#0x01");
7509 emitcode ("rl", "a");
7512 emitcode ("rl", "a");
7513 emitcode ("anl", "a,#0x01");
7519 freeAsmop (left, NULL, ic, TRUE);
7520 freeAsmop (right, NULL, ic, TRUE);
7521 freeAsmop (result, NULL, ic, TRUE);
7524 /*-----------------------------------------------------------------*/
7525 /* genGetByte - generates code get a single byte */
7526 /*-----------------------------------------------------------------*/
7528 genGetByte (iCode * ic)
7530 operand *left, *right, *result;
7533 D(emitcode ("; genGetByte",""));
7535 left = IC_LEFT (ic);
7536 right = IC_RIGHT (ic);
7537 result = IC_RESULT (ic);
7538 aopOp (left, ic, FALSE);
7539 aopOp (right, ic, FALSE);
7540 aopOp (result, ic, FALSE);
7542 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7544 aopGet (left, offset, FALSE, FALSE),
7546 isOperandVolatile (result, FALSE));
7548 freeAsmop (left, NULL, ic, TRUE);
7549 freeAsmop (right, NULL, ic, TRUE);
7550 freeAsmop (result, NULL, ic, TRUE);
7553 /*-----------------------------------------------------------------*/
7554 /* genGetWord - generates code get two bytes */
7555 /*-----------------------------------------------------------------*/
7557 genGetWord (iCode * ic)
7559 operand *left, *right, *result;
7562 D(emitcode ("; genGetWord",""));
7564 left = IC_LEFT (ic);
7565 right = IC_RIGHT (ic);
7566 result = IC_RESULT (ic);
7567 aopOp (left, ic, FALSE);
7568 aopOp (right, ic, FALSE);
7569 aopOp (result, ic, FALSE);
7571 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7573 aopGet (left, offset, FALSE, FALSE),
7575 isOperandVolatile (result, FALSE));
7577 aopGet (left, offset+1, FALSE, FALSE),
7579 isOperandVolatile (result, FALSE));
7581 freeAsmop (left, NULL, ic, TRUE);
7582 freeAsmop (right, NULL, ic, TRUE);
7583 freeAsmop (result, NULL, ic, TRUE);
7586 /*-----------------------------------------------------------------*/
7587 /* genSwap - generates code to swap nibbles or bytes */
7588 /*-----------------------------------------------------------------*/
7590 genSwap (iCode * ic)
7592 operand *left, *result;
7594 D(emitcode ("; genSwap",""));
7596 left = IC_LEFT (ic);
7597 result = IC_RESULT (ic);
7598 aopOp (left, ic, FALSE);
7599 aopOp (result, ic, FALSE);
7601 switch (AOP_SIZE (left))
7603 case 1: /* swap nibbles in byte */
7604 MOVA (aopGet (left, 0, FALSE, FALSE));
7605 emitcode ("swap", "a");
7606 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7608 case 2: /* swap bytes in word */
7609 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7611 MOVA (aopGet (left, 0, FALSE, FALSE));
7612 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7613 0, isOperandVolatile (result, FALSE));
7614 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7616 else if (operandsEqu (left, result))
7619 bool pushedB = FALSE, leftInB = FALSE;
7621 MOVA (aopGet (left, 0, FALSE, FALSE));
7622 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7625 emitcode ("mov", "b,a");
7629 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7630 0, isOperandVolatile (result, FALSE));
7631 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7638 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7639 0, isOperandVolatile (result, FALSE));
7640 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7641 1, isOperandVolatile (result, FALSE));
7645 wassertl(FALSE, "unsupported SWAP operand size");
7648 freeAsmop (left, NULL, ic, TRUE);
7649 freeAsmop (result, NULL, ic, TRUE);
7653 /*-----------------------------------------------------------------*/
7654 /* AccRol - rotate left accumulator by known count */
7655 /*-----------------------------------------------------------------*/
7657 AccRol (int shCount)
7659 shCount &= 0x0007; // shCount : 0..7
7666 emitcode ("rl", "a");
7669 emitcode ("rl", "a");
7670 emitcode ("rl", "a");
7673 emitcode ("swap", "a");
7674 emitcode ("rr", "a");
7677 emitcode ("swap", "a");
7680 emitcode ("swap", "a");
7681 emitcode ("rl", "a");
7684 emitcode ("rr", "a");
7685 emitcode ("rr", "a");
7688 emitcode ("rr", "a");
7693 /*-----------------------------------------------------------------*/
7694 /* AccLsh - left shift accumulator by known count */
7695 /*-----------------------------------------------------------------*/
7697 AccLsh (int shCount)
7702 emitcode ("add", "a,acc");
7703 else if (shCount == 2)
7705 emitcode ("add", "a,acc");
7706 emitcode ("add", "a,acc");
7710 /* rotate left accumulator */
7712 /* and kill the lower order bits */
7713 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7718 /*-----------------------------------------------------------------*/
7719 /* AccRsh - right shift accumulator by known count */
7720 /*-----------------------------------------------------------------*/
7722 AccRsh (int shCount)
7729 emitcode ("rrc", "a");
7733 /* rotate right accumulator */
7734 AccRol (8 - shCount);
7735 /* and kill the higher order bits */
7736 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7741 /*-----------------------------------------------------------------*/
7742 /* AccSRsh - signed right shift accumulator by known count */
7743 /*-----------------------------------------------------------------*/
7745 AccSRsh (int shCount)
7752 emitcode ("mov", "c,acc.7");
7753 emitcode ("rrc", "a");
7755 else if (shCount == 2)
7757 emitcode ("mov", "c,acc.7");
7758 emitcode ("rrc", "a");
7759 emitcode ("mov", "c,acc.7");
7760 emitcode ("rrc", "a");
7764 tlbl = newiTempLabel (NULL);
7765 /* rotate right accumulator */
7766 AccRol (8 - shCount);
7767 /* and kill the higher order bits */
7768 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7769 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7770 emitcode ("orl", "a,#0x%02x",
7771 (unsigned char) ~SRMask[shCount]);
7772 emitcode ("", "%05d$:", tlbl->key + 100);
7777 /*-----------------------------------------------------------------*/
7778 /* shiftR1Left2Result - shift right one byte from left to result */
7779 /*-----------------------------------------------------------------*/
7781 shiftR1Left2Result (operand * left, int offl,
7782 operand * result, int offr,
7783 int shCount, int sign)
7785 MOVA (aopGet (left, offl, FALSE, FALSE));
7786 /* shift right accumulator */
7791 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7794 /*-----------------------------------------------------------------*/
7795 /* shiftL1Left2Result - shift left one byte from left to result */
7796 /*-----------------------------------------------------------------*/
7798 shiftL1Left2Result (operand * left, int offl,
7799 operand * result, int offr, int shCount)
7802 l = aopGet (left, offl, FALSE, FALSE);
7804 /* shift left accumulator */
7806 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7809 /*-----------------------------------------------------------------*/
7810 /* movLeft2Result - move byte from left to result */
7811 /*-----------------------------------------------------------------*/
7813 movLeft2Result (operand * left, int offl,
7814 operand * result, int offr, int sign)
7817 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7819 l = aopGet (left, offl, FALSE, FALSE);
7821 if (*l == '@' && (IS_AOP_PREG (result)))
7823 emitcode ("mov", "a,%s", l);
7824 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7829 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7832 /* MSB sign in acc.7 ! */
7833 if (getDataSize (left) == offl + 1)
7836 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7843 /*-----------------------------------------------------------------*/
7844 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7845 /*-----------------------------------------------------------------*/
7849 emitcode ("rrc", "a");
7850 emitcode ("xch", "a,%s", x);
7851 emitcode ("rrc", "a");
7852 emitcode ("xch", "a,%s", x);
7855 /*-----------------------------------------------------------------*/
7856 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7857 /*-----------------------------------------------------------------*/
7861 emitcode ("xch", "a,%s", x);
7862 emitcode ("rlc", "a");
7863 emitcode ("xch", "a,%s", x);
7864 emitcode ("rlc", "a");
7867 /*-----------------------------------------------------------------*/
7868 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7869 /*-----------------------------------------------------------------*/
7873 emitcode ("xch", "a,%s", x);
7874 emitcode ("add", "a,acc");
7875 emitcode ("xch", "a,%s", x);
7876 emitcode ("rlc", "a");
7879 /*-----------------------------------------------------------------*/
7880 /* AccAXLsh - left shift a:x by known count (0..7) */
7881 /*-----------------------------------------------------------------*/
7883 AccAXLsh (char *x, int shCount)
7898 case 5: // AAAAABBB:CCCCCDDD
7900 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7902 emitcode ("anl", "a,#0x%02x",
7903 SLMask[shCount]); // BBB00000:CCCCCDDD
7905 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7907 AccRol (shCount); // DDDCCCCC:BBB00000
7909 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7911 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7913 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7915 emitcode ("anl", "a,#0x%02x",
7916 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7918 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7920 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7923 case 6: // AAAAAABB:CCCCCCDD
7924 emitcode ("anl", "a,#0x%02x",
7925 SRMask[shCount]); // 000000BB:CCCCCCDD
7926 emitcode ("mov", "c,acc.0"); // c = B
7927 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7929 AccAXRrl1 (x); // BCCCCCCD:D000000B
7930 AccAXRrl1 (x); // BBCCCCCC:DD000000
7932 emitcode("rrc","a");
7933 emitcode("xch","a,%s", x);
7934 emitcode("rrc","a");
7935 emitcode("mov","c,acc.0"); //<< get correct bit
7936 emitcode("xch","a,%s", x);
7938 emitcode("rrc","a");
7939 emitcode("xch","a,%s", x);
7940 emitcode("rrc","a");
7941 emitcode("xch","a,%s", x);
7944 case 7: // a:x <<= 7
7946 emitcode ("anl", "a,#0x%02x",
7947 SRMask[shCount]); // 0000000B:CCCCCCCD
7949 emitcode ("mov", "c,acc.0"); // c = B
7951 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7953 AccAXRrl1 (x); // BCCCCCCC:D0000000
7961 /*-----------------------------------------------------------------*/
7962 /* AccAXRsh - right shift a:x known count (0..7) */
7963 /*-----------------------------------------------------------------*/
7965 AccAXRsh (char *x, int shCount)
7973 AccAXRrl1 (x); // 0->a:x
7978 AccAXRrl1 (x); // 0->a:x
7981 AccAXRrl1 (x); // 0->a:x
7986 case 5: // AAAAABBB:CCCCCDDD = a:x
7988 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7990 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7992 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7994 emitcode ("anl", "a,#0x%02x",
7995 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7997 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7999 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8001 emitcode ("anl", "a,#0x%02x",
8002 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8004 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8006 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8008 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8011 case 6: // AABBBBBB:CCDDDDDD
8013 emitcode ("mov", "c,acc.7");
8014 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8016 emitcode ("mov", "c,acc.7");
8017 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8019 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8021 emitcode ("anl", "a,#0x%02x",
8022 SRMask[shCount]); // 000000AA:BBBBBBCC
8025 case 7: // ABBBBBBB:CDDDDDDD
8027 emitcode ("mov", "c,acc.7"); // c = A
8029 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8031 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8033 emitcode ("anl", "a,#0x%02x",
8034 SRMask[shCount]); // 0000000A:BBBBBBBC
8042 /*-----------------------------------------------------------------*/
8043 /* AccAXRshS - right shift signed a:x known count (0..7) */
8044 /*-----------------------------------------------------------------*/
8046 AccAXRshS (char *x, int shCount)
8054 emitcode ("mov", "c,acc.7");
8055 AccAXRrl1 (x); // s->a:x
8059 emitcode ("mov", "c,acc.7");
8060 AccAXRrl1 (x); // s->a:x
8062 emitcode ("mov", "c,acc.7");
8063 AccAXRrl1 (x); // s->a:x
8068 case 5: // AAAAABBB:CCCCCDDD = a:x
8070 tlbl = newiTempLabel (NULL);
8071 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8073 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8075 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8077 emitcode ("anl", "a,#0x%02x",
8078 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8080 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8082 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8084 emitcode ("anl", "a,#0x%02x",
8085 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8087 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8089 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8091 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8093 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8094 emitcode ("orl", "a,#0x%02x",
8095 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8097 emitcode ("", "%05d$:", tlbl->key + 100);
8098 break; // SSSSAAAA:BBBCCCCC
8100 case 6: // AABBBBBB:CCDDDDDD
8102 tlbl = newiTempLabel (NULL);
8103 emitcode ("mov", "c,acc.7");
8104 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8106 emitcode ("mov", "c,acc.7");
8107 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8109 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8111 emitcode ("anl", "a,#0x%02x",
8112 SRMask[shCount]); // 000000AA:BBBBBBCC
8114 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8115 emitcode ("orl", "a,#0x%02x",
8116 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8118 emitcode ("", "%05d$:", tlbl->key + 100);
8120 case 7: // ABBBBBBB:CDDDDDDD
8122 tlbl = newiTempLabel (NULL);
8123 emitcode ("mov", "c,acc.7"); // c = A
8125 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8127 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8129 emitcode ("anl", "a,#0x%02x",
8130 SRMask[shCount]); // 0000000A:BBBBBBBC
8132 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8133 emitcode ("orl", "a,#0x%02x",
8134 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8136 emitcode ("", "%05d$:", tlbl->key + 100);
8143 /*-----------------------------------------------------------------*/
8144 /* shiftL2Left2Result - shift left two bytes from left to result */
8145 /*-----------------------------------------------------------------*/
8147 shiftL2Left2Result (operand * left, int offl,
8148 operand * result, int offr, int shCount)
8151 bool pushedB = FALSE;
8154 if (sameRegs (AOP (result), AOP (left)) &&
8155 ((offl + MSB16) == offr))
8157 /* don't crash result[offr] */
8158 MOVA (aopGet (left, offl, FALSE, FALSE));
8159 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8160 x = aopGet (result, offr, FALSE, FALSE);
8162 else if (aopGetUsesAcc (result, offr))
8164 movLeft2Result (left, offl, result, offr, 0);
8167 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8168 MOVA (aopGet (result, offr, FALSE, FALSE));
8169 emitcode ("xch", "a,b");
8174 movLeft2Result (left, offl, result, offr, 0);
8175 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8176 x = aopGet (result, offr, FALSE, FALSE);
8178 /* ax << shCount (x = lsb(result)) */
8179 AccAXLsh (x, shCount);
8182 emitcode ("xch", "a,b");
8183 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8184 aopPut (result, "b", offr + MSB16, isOperandVolatile (result, FALSE));
8189 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8194 /*-----------------------------------------------------------------*/
8195 /* shiftR2Left2Result - shift right two bytes from left to result */
8196 /*-----------------------------------------------------------------*/
8198 shiftR2Left2Result (operand * left, int offl,
8199 operand * result, int offr,
8200 int shCount, int sign)
8203 bool pushedB = FALSE;
8206 if (sameRegs (AOP (result), AOP (left)) &&
8207 ((offl + MSB16) == offr))
8209 /* don't crash result[offr] */
8210 MOVA (aopGet (left, offl, FALSE, FALSE));
8211 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8212 x = aopGet (result, offr, FALSE, FALSE);
8214 else if (aopGetUsesAcc (result, offr))
8216 movLeft2Result (left, offl, result, offr, 0);
8219 emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
8220 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8225 movLeft2Result (left, offl, result, offr, 0);
8226 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8227 x = aopGet (result, offr, FALSE, FALSE);
8229 /* a:x >> shCount (x = lsb(result)) */
8231 AccAXRshS (x, shCount);
8233 AccAXRsh (x, shCount);
8236 emitcode ("xch", "a,b");
8237 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8238 emitcode ("xch", "a,b");
8241 if (getDataSize (result) > 1)
8242 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8245 /*-----------------------------------------------------------------*/
8246 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8247 /*-----------------------------------------------------------------*/
8249 shiftLLeftOrResult (operand * left, int offl,
8250 operand * result, int offr, int shCount)
8252 MOVA (aopGet (left, offl, FALSE, FALSE));
8253 /* shift left accumulator */
8255 /* or with result */
8256 if (aopGetUsesAcc (result, offr))
8258 emitcode ("xch", "a,b");
8259 MOVA (aopGet (result, offr, FALSE, FALSE));
8260 emitcode ("orl", "a,b");
8264 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8266 /* back to result */
8267 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8270 /*-----------------------------------------------------------------*/
8271 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8272 /*-----------------------------------------------------------------*/
8274 shiftRLeftOrResult (operand * left, int offl,
8275 operand * result, int offr, int shCount)
8277 MOVA (aopGet (left, offl, FALSE, FALSE));
8278 /* shift right accumulator */
8280 /* or with result */
8281 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8282 /* back to result */
8283 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8286 /*-----------------------------------------------------------------*/
8287 /* genlshOne - left shift a one byte quantity by known count */
8288 /*-----------------------------------------------------------------*/
8290 genlshOne (operand * result, operand * left, int shCount)
8292 D(emitcode ("; genlshOne",""));
8294 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8297 /*-----------------------------------------------------------------*/
8298 /* genlshTwo - left shift two bytes by known amount != 0 */
8299 /*-----------------------------------------------------------------*/
8301 genlshTwo (operand * result, operand * left, int shCount)
8305 D(emitcode ("; genlshTwo",""));
8307 size = getDataSize (result);
8309 /* if shCount >= 8 */
8317 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8319 movLeft2Result (left, LSB, result, MSB16, 0);
8321 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8324 /* 1 <= shCount <= 7 */
8328 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8330 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8334 /*-----------------------------------------------------------------*/
8335 /* shiftLLong - shift left one long from left to result */
8336 /* offl = LSB or MSB16 */
8337 /*-----------------------------------------------------------------*/
8339 shiftLLong (operand * left, operand * result, int offr)
8342 int size = AOP_SIZE (result);
8344 if (size >= LSB + offr)
8346 l = aopGet (left, LSB, FALSE, FALSE);
8348 emitcode ("add", "a,acc");
8349 if (sameRegs (AOP (left), AOP (result)) &&
8350 size >= MSB16 + offr && offr != LSB)
8351 emitcode ("xch", "a,%s",
8352 aopGet (left, LSB + offr, FALSE, FALSE));
8354 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8357 if (size >= MSB16 + offr)
8359 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8361 l = aopGet (left, MSB16, FALSE, FALSE);
8364 emitcode ("rlc", "a");
8365 if (sameRegs (AOP (left), AOP (result)) &&
8366 size >= MSB24 + offr && offr != LSB)
8367 emitcode ("xch", "a,%s",
8368 aopGet (left, MSB16 + offr, FALSE, FALSE));
8370 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8373 if (size >= MSB24 + offr)
8375 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8377 l = aopGet (left, MSB24, FALSE, FALSE);
8380 emitcode ("rlc", "a");
8381 if (sameRegs (AOP (left), AOP (result)) &&
8382 size >= MSB32 + offr && offr != LSB)
8383 emitcode ("xch", "a,%s",
8384 aopGet (left, MSB24 + offr, FALSE, FALSE));
8386 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8389 if (size > MSB32 + offr)
8391 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8393 l = aopGet (left, MSB32, FALSE, FALSE);
8396 emitcode ("rlc", "a");
8397 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8400 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8403 /*-----------------------------------------------------------------*/
8404 /* genlshFour - shift four byte by a known amount != 0 */
8405 /*-----------------------------------------------------------------*/
8407 genlshFour (operand * result, operand * left, int shCount)
8411 D(emitcode ("; genlshFour",""));
8413 size = AOP_SIZE (result);
8415 /* if shifting more that 3 bytes */
8420 /* lowest order of left goes to the highest
8421 order of the destination */
8422 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8424 movLeft2Result (left, LSB, result, MSB32, 0);
8425 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8426 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8427 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8431 /* more than two bytes */
8432 else if (shCount >= 16)
8434 /* lower order two bytes goes to higher order two bytes */
8436 /* if some more remaining */
8438 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8441 movLeft2Result (left, MSB16, result, MSB32, 0);
8442 movLeft2Result (left, LSB, result, MSB24, 0);
8444 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8445 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8449 /* if more than 1 byte */
8450 else if (shCount >= 8)
8452 /* lower order three bytes goes to higher order three bytes */
8457 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8459 movLeft2Result (left, LSB, result, MSB16, 0);
8465 movLeft2Result (left, MSB24, result, MSB32, 0);
8466 movLeft2Result (left, MSB16, result, MSB24, 0);
8467 movLeft2Result (left, LSB, result, MSB16, 0);
8468 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8470 else if (shCount == 1)
8471 shiftLLong (left, result, MSB16);
8474 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8475 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8476 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8477 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8482 /* 1 <= shCount <= 7 */
8483 else if (shCount <= 2)
8485 shiftLLong (left, result, LSB);
8487 shiftLLong (result, result, LSB);
8489 /* 3 <= shCount <= 7, optimize */
8492 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8493 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8494 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8498 /*-----------------------------------------------------------------*/
8499 /* genLeftShiftLiteral - left shifting by known count */
8500 /*-----------------------------------------------------------------*/
8502 genLeftShiftLiteral (operand * left,
8507 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8510 D(emitcode ("; genLeftShiftLiteral",""));
8512 freeAsmop (right, NULL, ic, TRUE);
8514 aopOp (left, ic, FALSE);
8515 aopOp (result, ic, FALSE);
8517 size = getSize (operandType (result));
8520 emitcode ("; shift left ", "result %d, left %d", size,
8524 /* I suppose that the left size >= result size */
8529 movLeft2Result (left, size, result, size, 0);
8533 else if (shCount >= (size * 8))
8535 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8541 genlshOne (result, left, shCount);
8545 genlshTwo (result, left, shCount);
8549 genlshFour (result, left, shCount);
8552 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8553 "*** ack! mystery literal shift!\n");
8557 freeAsmop (left, NULL, ic, TRUE);
8558 freeAsmop (result, NULL, ic, TRUE);
8561 /*-----------------------------------------------------------------*/
8562 /* genLeftShift - generates code for left shifting */
8563 /*-----------------------------------------------------------------*/
8565 genLeftShift (iCode * ic)
8567 operand *left, *right, *result;
8570 symbol *tlbl, *tlbl1;
8573 D(emitcode ("; genLeftShift",""));
8575 right = IC_RIGHT (ic);
8576 left = IC_LEFT (ic);
8577 result = IC_RESULT (ic);
8579 aopOp (right, ic, FALSE);
8581 /* if the shift count is known then do it
8582 as efficiently as possible */
8583 if (AOP_TYPE (right) == AOP_LIT)
8585 genLeftShiftLiteral (left, right, result, ic);
8589 /* shift count is unknown then we have to form
8590 a loop get the loop count in B : Note: we take
8591 only the lower order byte since shifting
8592 more that 32 bits make no sense anyway, ( the
8593 largest size of an object can be only 32 bits ) */
8596 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8597 emitcode ("inc", "b");
8598 freeAsmop (right, NULL, ic, TRUE);
8599 aopOp (left, ic, FALSE);
8600 aopOp (result, ic, FALSE);
8602 /* now move the left to the result if they are not the same */
8603 if (!sameRegs (AOP (left), AOP (result)) &&
8604 AOP_SIZE (result) > 1)
8607 size = AOP_SIZE (result);
8611 l = aopGet (left, offset, FALSE, TRUE);
8612 if (*l == '@' && (IS_AOP_PREG (result)))
8615 emitcode ("mov", "a,%s", l);
8616 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8619 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8624 tlbl = newiTempLabel (NULL);
8625 size = AOP_SIZE (result);
8627 tlbl1 = newiTempLabel (NULL);
8629 /* if it is only one byte then */
8632 symbol *tlbl1 = newiTempLabel (NULL);
8634 l = aopGet (left, 0, FALSE, FALSE);
8636 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8637 emitcode ("", "%05d$:", tlbl->key + 100);
8638 emitcode ("add", "a,acc");
8639 emitcode ("", "%05d$:", tlbl1->key + 100);
8640 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8642 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8646 reAdjustPreg (AOP (result));
8648 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8649 emitcode ("", "%05d$:", tlbl->key + 100);
8650 l = aopGet (result, offset, FALSE, FALSE);
8652 emitcode ("add", "a,acc");
8653 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8656 l = aopGet (result, offset, FALSE, FALSE);
8658 emitcode ("rlc", "a");
8659 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8661 reAdjustPreg (AOP (result));
8663 emitcode ("", "%05d$:", tlbl1->key + 100);
8664 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8667 freeAsmop (left, NULL, ic, TRUE);
8668 freeAsmop (result, NULL, ic, TRUE);
8671 /*-----------------------------------------------------------------*/
8672 /* genrshOne - right shift a one byte quantity by known count */
8673 /*-----------------------------------------------------------------*/
8675 genrshOne (operand * result, operand * left,
8676 int shCount, int sign)
8678 D(emitcode ("; genrshOne",""));
8680 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8683 /*-----------------------------------------------------------------*/
8684 /* genrshTwo - right shift two bytes by known amount != 0 */
8685 /*-----------------------------------------------------------------*/
8687 genrshTwo (operand * result, operand * left,
8688 int shCount, int sign)
8690 D(emitcode ("; genrshTwo",""));
8692 /* if shCount >= 8 */
8697 shiftR1Left2Result (left, MSB16, result, LSB,
8700 movLeft2Result (left, MSB16, result, LSB, sign);
8701 addSign (result, MSB16, sign);
8704 /* 1 <= shCount <= 7 */
8706 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8709 /*-----------------------------------------------------------------*/
8710 /* shiftRLong - shift right one long from left to result */
8711 /* offl = LSB or MSB16 */
8712 /*-----------------------------------------------------------------*/
8714 shiftRLong (operand * left, int offl,
8715 operand * result, int sign)
8717 int isSameRegs=sameRegs(AOP(left),AOP(result));
8719 if (isSameRegs && offl>1) {
8720 // we are in big trouble, but this shouldn't happen
8721 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8724 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8729 emitcode ("rlc", "a");
8730 emitcode ("subb", "a,acc");
8732 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8734 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8735 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8738 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8743 emitcode ("clr", "c");
8745 emitcode ("mov", "c,acc.7");
8748 emitcode ("rrc", "a");
8750 if (isSameRegs && offl==MSB16) {
8751 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8753 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8754 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8757 emitcode ("rrc", "a");
8758 if (isSameRegs && offl==1) {
8759 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8761 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8762 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8764 emitcode ("rrc", "a");
8765 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8769 MOVA (aopGet (left, LSB, FALSE, FALSE));
8770 emitcode ("rrc", "a");
8771 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8775 /*-----------------------------------------------------------------*/
8776 /* genrshFour - shift four byte by a known amount != 0 */
8777 /*-----------------------------------------------------------------*/
8779 genrshFour (operand * result, operand * left,
8780 int shCount, int sign)
8782 D(emitcode ("; genrshFour",""));
8784 /* if shifting more that 3 bytes */
8789 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8791 movLeft2Result (left, MSB32, result, LSB, sign);
8792 addSign (result, MSB16, sign);
8794 else if (shCount >= 16)
8798 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8801 movLeft2Result (left, MSB24, result, LSB, 0);
8802 movLeft2Result (left, MSB32, result, MSB16, sign);
8804 addSign (result, MSB24, sign);
8806 else if (shCount >= 8)
8810 shiftRLong (left, MSB16, result, sign);
8811 else if (shCount == 0)
8813 movLeft2Result (left, MSB16, result, LSB, 0);
8814 movLeft2Result (left, MSB24, result, MSB16, 0);
8815 movLeft2Result (left, MSB32, result, MSB24, sign);
8816 addSign (result, MSB32, sign);
8820 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8821 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8822 /* the last shift is signed */
8823 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8824 addSign (result, MSB32, sign);
8828 { /* 1 <= shCount <= 7 */
8831 shiftRLong (left, LSB, result, sign);
8833 shiftRLong (result, LSB, result, sign);
8837 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8838 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8839 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8844 /*-----------------------------------------------------------------*/
8845 /* genRightShiftLiteral - right shifting by known count */
8846 /*-----------------------------------------------------------------*/
8848 genRightShiftLiteral (operand * left,
8854 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8857 D(emitcode ("; genRightShiftLiteral",""));
8859 freeAsmop (right, NULL, ic, TRUE);
8861 aopOp (left, ic, FALSE);
8862 aopOp (result, ic, FALSE);
8865 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8869 size = getDataSize (left);
8870 /* test the LEFT size !!! */
8872 /* I suppose that the left size >= result size */
8875 size = getDataSize (result);
8877 movLeft2Result (left, size, result, size, 0);
8880 else if (shCount >= (size * 8))
8883 /* get sign in acc.7 */
8884 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8886 addSign (result, LSB, sign);
8893 genrshOne (result, left, shCount, sign);
8897 genrshTwo (result, left, shCount, sign);
8901 genrshFour (result, left, shCount, sign);
8907 freeAsmop (left, NULL, ic, TRUE);
8908 freeAsmop (result, NULL, ic, TRUE);
8911 /*-----------------------------------------------------------------*/
8912 /* genSignedRightShift - right shift of signed number */
8913 /*-----------------------------------------------------------------*/
8915 genSignedRightShift (iCode * ic)
8917 operand *right, *left, *result;
8920 symbol *tlbl, *tlbl1;
8923 D(emitcode ("; genSignedRightShift",""));
8925 /* we do it the hard way put the shift count in b
8926 and loop thru preserving the sign */
8928 right = IC_RIGHT (ic);
8929 left = IC_LEFT (ic);
8930 result = IC_RESULT (ic);
8932 aopOp (right, ic, FALSE);
8935 if (AOP_TYPE (right) == AOP_LIT)
8937 genRightShiftLiteral (left, right, result, ic, 1);
8940 /* shift count is unknown then we have to form
8941 a loop get the loop count in B : Note: we take
8942 only the lower order byte since shifting
8943 more that 32 bits make no sense anyway, ( the
8944 largest size of an object can be only 32 bits ) */
8947 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8948 emitcode ("inc", "b");
8949 freeAsmop (right, NULL, ic, TRUE);
8950 aopOp (left, ic, FALSE);
8951 aopOp (result, ic, FALSE);
8953 /* now move the left to the result if they are not the
8955 if (!sameRegs (AOP (left), AOP (result)) &&
8956 AOP_SIZE (result) > 1)
8959 size = AOP_SIZE (result);
8963 l = aopGet (left, offset, FALSE, TRUE);
8964 if (*l == '@' && IS_AOP_PREG (result))
8967 emitcode ("mov", "a,%s", l);
8968 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8971 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8976 /* mov the highest order bit to OVR */
8977 tlbl = newiTempLabel (NULL);
8978 tlbl1 = newiTempLabel (NULL);
8980 size = AOP_SIZE (result);
8982 MOVA (aopGet (left, offset, FALSE, FALSE));
8983 emitcode ("rlc", "a");
8984 emitcode ("mov", "ov,c");
8985 /* if it is only one byte then */
8988 l = aopGet (left, 0, FALSE, FALSE);
8990 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8991 emitcode ("", "%05d$:", tlbl->key + 100);
8992 emitcode ("mov", "c,ov");
8993 emitcode ("rrc", "a");
8994 emitcode ("", "%05d$:", tlbl1->key + 100);
8995 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8997 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9001 reAdjustPreg (AOP (result));
9002 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9003 emitcode ("", "%05d$:", tlbl->key + 100);
9004 emitcode ("mov", "c,ov");
9007 l = aopGet (result, offset, FALSE, FALSE);
9009 emitcode ("rrc", "a");
9010 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9012 reAdjustPreg (AOP (result));
9013 emitcode ("", "%05d$:", tlbl1->key + 100);
9014 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9018 freeAsmop (left, NULL, ic, TRUE);
9019 freeAsmop (result, NULL, ic, TRUE);
9022 /*-----------------------------------------------------------------*/
9023 /* genRightShift - generate code for right shifting */
9024 /*-----------------------------------------------------------------*/
9026 genRightShift (iCode * ic)
9028 operand *right, *left, *result;
9032 symbol *tlbl, *tlbl1;
9035 D(emitcode ("; genRightShift",""));
9037 /* if signed then we do it the hard way preserve the
9038 sign bit moving it inwards */
9039 letype = getSpec (operandType (IC_LEFT (ic)));
9041 if (!SPEC_USIGN (letype))
9043 genSignedRightShift (ic);
9047 /* signed & unsigned types are treated the same : i.e. the
9048 signed is NOT propagated inwards : quoting from the
9049 ANSI - standard : "for E1 >> E2, is equivalent to division
9050 by 2**E2 if unsigned or if it has a non-negative value,
9051 otherwise the result is implementation defined ", MY definition
9052 is that the sign does not get propagated */
9054 right = IC_RIGHT (ic);
9055 left = IC_LEFT (ic);
9056 result = IC_RESULT (ic);
9058 aopOp (right, ic, FALSE);
9060 /* if the shift count is known then do it
9061 as efficiently as possible */
9062 if (AOP_TYPE (right) == AOP_LIT)
9064 genRightShiftLiteral (left, right, result, ic, 0);
9068 /* shift count is unknown then we have to form
9069 a loop get the loop count in B : Note: we take
9070 only the lower order byte since shifting
9071 more that 32 bits make no sense anyway, ( the
9072 largest size of an object can be only 32 bits ) */
9075 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9076 emitcode ("inc", "b");
9077 freeAsmop (right, NULL, ic, TRUE);
9078 aopOp (left, ic, FALSE);
9079 aopOp (result, ic, FALSE);
9081 /* now move the left to the result if they are not the
9083 if (!sameRegs (AOP (left), AOP (result)) &&
9084 AOP_SIZE (result) > 1)
9087 size = AOP_SIZE (result);
9091 l = aopGet (left, offset, FALSE, TRUE);
9092 if (*l == '@' && IS_AOP_PREG (result))
9095 emitcode ("mov", "a,%s", l);
9096 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9099 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9104 tlbl = newiTempLabel (NULL);
9105 tlbl1 = newiTempLabel (NULL);
9106 size = AOP_SIZE (result);
9109 /* if it is only one byte then */
9112 l = aopGet (left, 0, FALSE, FALSE);
9114 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9115 emitcode ("", "%05d$:", tlbl->key + 100);
9117 emitcode ("rrc", "a");
9118 emitcode ("", "%05d$:", tlbl1->key + 100);
9119 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9121 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9125 reAdjustPreg (AOP (result));
9126 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9127 emitcode ("", "%05d$:", tlbl->key + 100);
9131 l = aopGet (result, offset, FALSE, FALSE);
9133 emitcode ("rrc", "a");
9134 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9136 reAdjustPreg (AOP (result));
9138 emitcode ("", "%05d$:", tlbl1->key + 100);
9139 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9143 freeAsmop (left, NULL, ic, TRUE);
9144 freeAsmop (result, NULL, ic, TRUE);
9147 /*-----------------------------------------------------------------*/
9148 /* emitPtrByteGet - emits code to get a byte into A through a */
9149 /* pointer register (R0, R1, or DPTR). The */
9150 /* original value of A can be preserved in B. */
9151 /*-----------------------------------------------------------------*/
9153 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9160 emitcode ("mov", "b,a");
9161 emitcode ("mov", "a,@%s", rname);
9166 emitcode ("mov", "b,a");
9167 emitcode ("movx", "a,@%s", rname);
9172 emitcode ("mov", "b,a");
9173 emitcode ("movx", "a,@dptr");
9178 emitcode ("mov", "b,a");
9179 emitcode ("clr", "a");
9180 emitcode ("movc", "a,@a+dptr");
9186 emitcode ("push", "b");
9187 emitcode ("push", "acc");
9189 emitcode ("lcall", "__gptrget");
9191 emitcode ("pop", "b");
9196 /*-----------------------------------------------------------------*/
9197 /* emitPtrByteSet - emits code to set a byte from src through a */
9198 /* pointer register (R0, R1, or DPTR). */
9199 /*-----------------------------------------------------------------*/
9201 emitPtrByteSet (char *rname, int p_type, char *src)
9210 emitcode ("mov", "@%s,a", rname);
9213 emitcode ("mov", "@%s,%s", rname, src);
9218 emitcode ("movx", "@%s,a", rname);
9223 emitcode ("movx", "@dptr,a");
9228 emitcode ("lcall", "__gptrput");
9233 /*-----------------------------------------------------------------*/
9234 /* genUnpackBits - generates code for unpacking bits */
9235 /*-----------------------------------------------------------------*/
9237 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9239 int offset = 0; /* result byte offset */
9240 int rsize; /* result size */
9241 int rlen = 0; /* remaining bitfield length */
9242 sym_link *etype; /* bitfield type information */
9243 int blen; /* bitfield length */
9244 int bstr; /* bitfield starting bit within byte */
9247 D(emitcode ("; genUnpackBits",""));
9249 etype = getSpec (operandType (result));
9250 rsize = getSize (operandType (result));
9251 blen = SPEC_BLEN (etype);
9252 bstr = SPEC_BSTR (etype);
9254 if (ifx && blen <= 8)
9256 emitPtrByteGet (rname, ptype, FALSE);
9259 SNPRINTF (buffer, sizeof(buffer),
9261 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9266 emitcode ("anl", "a,#0x%02x",
9267 (((unsigned char) -1) >> (8 - blen)) << bstr);
9268 genIfxJump (ifx, "a", NULL, NULL, NULL);
9274 /* If the bitfield length is less than a byte */
9277 emitPtrByteGet (rname, ptype, FALSE);
9279 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9280 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9284 /* Bit field did not fit in a byte. Copy all
9285 but the partial byte at the end. */
9286 for (rlen=blen;rlen>=8;rlen-=8)
9288 emitPtrByteGet (rname, ptype, FALSE);
9289 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9291 emitcode ("inc", "%s", rname);
9294 /* Handle the partial byte at the end */
9297 emitPtrByteGet (rname, ptype, FALSE);
9298 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9299 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9307 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
9312 /*-----------------------------------------------------------------*/
9313 /* genDataPointerGet - generates code when ptr offset is known */
9314 /*-----------------------------------------------------------------*/
9316 genDataPointerGet (operand * left,
9322 int size, offset = 0;
9324 D(emitcode ("; genDataPointerGet",""));
9326 aopOp (result, ic, TRUE);
9328 /* get the string representation of the name */
9329 l = aopGet (left, 0, FALSE, TRUE);
9330 size = AOP_SIZE (result);
9334 sprintf (buffer, "(%s + %d)", l + 1, offset);
9336 sprintf (buffer, "%s", l + 1);
9337 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9340 freeAsmop (left, NULL, ic, TRUE);
9341 freeAsmop (result, NULL, ic, TRUE);
9344 /*-----------------------------------------------------------------*/
9345 /* genNearPointerGet - emitcode for near pointer fetch */
9346 /*-----------------------------------------------------------------*/
9348 genNearPointerGet (operand * left,
9357 sym_link *rtype, *retype;
9358 sym_link *ltype = operandType (left);
9361 D(emitcode ("; genNearPointerGet",""));
9363 rtype = operandType (result);
9364 retype = getSpec (rtype);
9366 aopOp (left, ic, FALSE);
9368 /* if left is rematerialisable and
9369 result is not bitfield variable type and
9370 the left is pointer to data space i.e
9371 lower 128 bytes of space */
9372 if (AOP_TYPE (left) == AOP_IMMD &&
9373 !IS_BITFIELD (retype) &&
9374 DCL_TYPE (ltype) == POINTER)
9376 genDataPointerGet (left, result, ic);
9380 /* if the value is already in a pointer register
9381 then don't need anything more */
9382 if (!AOP_INPREG (AOP (left)))
9384 if (IS_AOP_PREG (left))
9386 // Aha, it is a pointer, just in disguise.
9387 rname = aopGet (left, 0, FALSE, FALSE);
9390 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9391 __FILE__, __LINE__);
9396 emitcode ("mov", "a%s,%s", rname + 1, rname);
9397 rname++; // skip the '@'.
9402 /* otherwise get a free pointer register */
9404 preg = getFreePtr (ic, &aop, FALSE);
9405 emitcode ("mov", "%s,%s",
9407 aopGet (left, 0, FALSE, TRUE));
9412 rname = aopGet (left, 0, FALSE, FALSE);
9414 //aopOp (result, ic, FALSE);
9415 aopOp (result, ic, result?TRUE:FALSE);
9417 /* if bitfield then unpack the bits */
9418 if (IS_BITFIELD (retype))
9419 genUnpackBits (result, rname, POINTER, ifx);
9422 /* we have can just get the values */
9423 int size = AOP_SIZE (result);
9428 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9431 emitcode ("mov", "a,@%s", rname);
9433 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9437 sprintf (buffer, "@%s", rname);
9438 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9442 emitcode ("inc", "%s", rname);
9446 /* now some housekeeping stuff */
9447 if (aop) /* we had to allocate for this iCode */
9449 if (pi) { /* post increment present */
9450 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9452 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9456 /* we did not allocate which means left
9457 already in a pointer register, then
9458 if size > 0 && this could be used again
9459 we have to point it back to where it
9461 if ((AOP_SIZE (result) > 1 &&
9462 !OP_SYMBOL (left)->remat &&
9463 (OP_SYMBOL (left)->liveTo > ic->seq ||
9467 int size = AOP_SIZE (result) - 1;
9469 emitcode ("dec", "%s", rname);
9473 if (ifx && !ifx->generated)
9475 genIfxJump (ifx, "a", left, NULL, result);
9479 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9480 freeAsmop (left, NULL, ic, TRUE);
9481 if (pi) pi->generated = 1;
9484 /*-----------------------------------------------------------------*/
9485 /* genPagedPointerGet - emitcode for paged pointer fetch */
9486 /*-----------------------------------------------------------------*/
9488 genPagedPointerGet (operand * left,
9497 sym_link *rtype, *retype;
9499 D(emitcode ("; genPagedPointerGet",""));
9501 rtype = operandType (result);
9502 retype = getSpec (rtype);
9504 aopOp (left, ic, FALSE);
9506 /* if the value is already in a pointer register
9507 then don't need anything more */
9508 if (!AOP_INPREG (AOP (left)))
9510 /* otherwise get a free pointer register */
9512 preg = getFreePtr (ic, &aop, FALSE);
9513 emitcode ("mov", "%s,%s",
9515 aopGet (left, 0, FALSE, TRUE));
9519 rname = aopGet (left, 0, FALSE, FALSE);
9521 aopOp (result, ic, FALSE);
9523 /* if bitfield then unpack the bits */
9524 if (IS_BITFIELD (retype))
9525 genUnpackBits (result, rname, PPOINTER, ifx);
9528 /* we have can just get the values */
9529 int size = AOP_SIZE (result);
9535 emitcode ("movx", "a,@%s", rname);
9537 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9542 emitcode ("inc", "%s", rname);
9546 /* now some housekeeping stuff */
9547 if (aop) /* we had to allocate for this iCode */
9549 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9550 freeAsmop (NULL, aop, ic, TRUE);
9554 /* we did not allocate which means left
9555 already in a pointer register, then
9556 if size > 0 && this could be used again
9557 we have to point it back to where it
9559 if ((AOP_SIZE (result) > 1 &&
9560 !OP_SYMBOL (left)->remat &&
9561 (OP_SYMBOL (left)->liveTo > ic->seq ||
9565 int size = AOP_SIZE (result) - 1;
9567 emitcode ("dec", "%s", rname);
9571 if (ifx && !ifx->generated)
9573 genIfxJump (ifx, "a", left, NULL, result);
9577 freeAsmop (left, NULL, ic, TRUE);
9578 freeAsmop (result, NULL, ic, TRUE);
9579 if (pi) pi->generated = 1;
9583 /*--------------------------------------------------------------------*/
9584 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9585 /*--------------------------------------------------------------------*/
9587 loadDptrFromOperand (operand *op, bool loadBToo)
9589 if (AOP_TYPE (op) != AOP_STR)
9591 /* if this is rematerializable */
9592 if (AOP_TYPE (op) == AOP_IMMD)
9594 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9597 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9598 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9601 wassertl(FALSE, "need pointerCode");
9602 emitcode ("", "; mov b,???");
9603 /* genPointerGet and genPointerSet originally did different
9604 ** things for this case. Both seem wrong.
9605 ** from genPointerGet:
9606 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9607 ** from genPointerSet:
9608 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9613 else if (AOP_TYPE (op) == AOP_DPTR)
9617 MOVA (aopGet (op, 0, FALSE, FALSE));
9618 emitcode ("push", "acc");
9619 MOVA (aopGet (op, 1, FALSE, FALSE));
9620 emitcode ("push", "acc");
9621 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9622 emitcode ("pop", "dph");
9623 emitcode ("pop", "dpl");
9627 MOVA (aopGet (op, 0, FALSE, FALSE));
9628 emitcode ("push", "acc");
9629 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9630 emitcode ("pop", "dpl");
9634 { /* we need to get it byte by byte */
9635 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9636 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9638 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9643 /*-----------------------------------------------------------------*/
9644 /* genFarPointerGet - gget value from far space */
9645 /*-----------------------------------------------------------------*/
9647 genFarPointerGet (operand * left,
9648 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9651 sym_link *retype = getSpec (operandType (result));
9653 D(emitcode ("; genFarPointerGet",""));
9655 aopOp (left, ic, FALSE);
9656 loadDptrFromOperand (left, FALSE);
9658 /* so dptr now contains the address */
9659 aopOp (result, ic, FALSE);
9661 /* if bit then unpack */
9662 if (IS_BITFIELD (retype))
9663 genUnpackBits (result, "dptr", FPOINTER, ifx);
9666 size = AOP_SIZE (result);
9671 emitcode ("movx", "a,@dptr");
9673 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9675 emitcode ("inc", "dptr");
9679 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9681 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9682 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9686 if (ifx && !ifx->generated)
9688 genIfxJump (ifx, "a", left, NULL, result);
9691 freeAsmop (left, NULL, ic, TRUE);
9692 freeAsmop (result, NULL, ic, TRUE);
9695 /*-----------------------------------------------------------------*/
9696 /* genCodePointerGet - gget value from code space */
9697 /*-----------------------------------------------------------------*/
9699 genCodePointerGet (operand * left,
9700 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9703 sym_link *retype = getSpec (operandType (result));
9705 D(emitcode ("; genCodePointerGet",""));
9707 aopOp (left, ic, FALSE);
9708 loadDptrFromOperand (left, FALSE);
9710 /* so dptr now contains the address */
9711 aopOp (result, ic, FALSE);
9713 /* if bit then unpack */
9714 if (IS_BITFIELD (retype))
9715 genUnpackBits (result, "dptr", CPOINTER, ifx);
9718 size = AOP_SIZE (result);
9725 emitcode ("clr", "a");
9726 emitcode ("movc", "a,@a+dptr");
9728 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9729 emitcode ("inc", "dptr");
9733 emitcode ("mov", "a,#0x%02x", offset);
9734 emitcode ("movc", "a,@a+dptr");
9736 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9741 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9743 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9744 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9748 if (ifx && !ifx->generated)
9750 genIfxJump (ifx, "a", left, NULL, result);
9753 freeAsmop (left, NULL, ic, TRUE);
9754 freeAsmop (result, NULL, ic, TRUE);
9757 /*-----------------------------------------------------------------*/
9758 /* genGenPointerGet - gget value from generic pointer space */
9759 /*-----------------------------------------------------------------*/
9761 genGenPointerGet (operand * left,
9762 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9765 sym_link *retype = getSpec (operandType (result));
9767 D(emitcode ("; genGenPointerGet",""));
9769 aopOp (left, ic, FALSE);
9770 loadDptrFromOperand (left, TRUE);
9772 /* so dptr know contains the address */
9773 aopOp (result, ic, FALSE);
9775 /* if bit then unpack */
9776 if (IS_BITFIELD (retype))
9777 genUnpackBits (result, "dptr", GPOINTER, ifx);
9780 size = AOP_SIZE (result);
9785 emitcode ("lcall", "__gptrget");
9787 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9789 emitcode ("inc", "dptr");
9793 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9795 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9796 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9800 if (ifx && !ifx->generated)
9802 genIfxJump (ifx, "a", left, NULL, result);
9806 freeAsmop (left, NULL, ic, TRUE);
9807 freeAsmop (result, NULL, ic, TRUE);
9810 /*-----------------------------------------------------------------*/
9811 /* genPointerGet - generate code for pointer get */
9812 /*-----------------------------------------------------------------*/
9814 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9816 operand *left, *result;
9817 sym_link *type, *etype;
9820 D(emitcode ("; genPointerGet",""));
9822 left = IC_LEFT (ic);
9823 result = IC_RESULT (ic);
9825 if (getSize (operandType (result))>1)
9828 /* depending on the type of pointer we need to
9829 move it to the correct pointer register */
9830 type = operandType (left);
9831 etype = getSpec (type);
9832 /* if left is of type of pointer then it is simple */
9833 if (IS_PTR (type) && !IS_FUNC (type->next))
9834 p_type = DCL_TYPE (type);
9837 /* we have to go by the storage class */
9838 p_type = PTR_TYPE (SPEC_OCLS (etype));
9841 /* special case when cast remat */
9842 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9843 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9844 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9845 type = operandType (left);
9846 p_type = DCL_TYPE (type);
9848 /* now that we have the pointer type we assign
9849 the pointer values */
9855 genNearPointerGet (left, result, ic, pi, ifx);
9859 genPagedPointerGet (left, result, ic, pi, ifx);
9863 genFarPointerGet (left, result, ic, pi, ifx);
9867 genCodePointerGet (left, result, ic, pi, ifx);
9871 genGenPointerGet (left, result, ic, pi, ifx);
9879 /*-----------------------------------------------------------------*/
9880 /* genPackBits - generates code for packed bit storage */
9881 /*-----------------------------------------------------------------*/
9883 genPackBits (sym_link * etype,
9885 char *rname, int p_type)
9887 int offset = 0; /* source byte offset */
9888 int rlen = 0; /* remaining bitfield length */
9889 int blen; /* bitfield length */
9890 int bstr; /* bitfield starting bit within byte */
9891 int litval; /* source literal value (if AOP_LIT) */
9892 unsigned char mask; /* bitmask within current byte */
9894 D(emitcode ("; genPackBits",""));
9896 blen = SPEC_BLEN (etype);
9897 bstr = SPEC_BSTR (etype);
9899 /* If the bitfield length is less than a byte */
9902 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9903 (unsigned char) (0xFF >> (8 - bstr)));
9905 if (AOP_TYPE (right) == AOP_LIT)
9907 /* Case with a bitfield length <8 and literal source
9909 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9911 litval &= (~mask) & 0xff;
9912 emitPtrByteGet (rname, p_type, FALSE);
9913 if ((mask|litval)!=0xff)
9914 emitcode ("anl","a,#0x%02x", mask);
9916 emitcode ("orl","a,#0x%02x", litval);
9920 if ((blen==1) && (p_type!=GPOINTER))
9922 /* Case with a bitfield length == 1 and no generic pointer
9924 if (AOP_TYPE (right) == AOP_CRY)
9925 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9928 MOVA (aopGet (right, 0, FALSE, FALSE));
9929 emitcode ("rrc","a");
9931 emitPtrByteGet (rname, p_type, FALSE);
9932 emitcode ("mov","acc.%d,c",bstr);
9937 /* Case with a bitfield length < 8 and arbitrary source
9939 MOVA (aopGet (right, 0, FALSE, FALSE));
9940 /* shift and mask source value */
9942 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9945 /* transfer A to B and get next byte */
9946 emitPtrByteGet (rname, p_type, TRUE);
9948 emitcode ("anl", "a,#0x%02x", mask);
9949 emitcode ("orl", "a,b");
9950 if (p_type == GPOINTER)
9951 emitcode ("pop", "b");
9957 emitPtrByteSet (rname, p_type, "a");
9961 /* Bit length is greater than 7 bits. In this case, copy */
9962 /* all except the partial byte at the end */
9963 for (rlen=blen;rlen>=8;rlen-=8)
9965 emitPtrByteSet (rname, p_type,
9966 aopGet (right, offset++, FALSE, TRUE) );
9968 emitcode ("inc", "%s", rname);
9971 /* If there was a partial byte at the end */
9974 mask = (((unsigned char) -1 << rlen) & 0xff);
9976 if (AOP_TYPE (right) == AOP_LIT)
9978 /* Case with partial byte and literal source
9980 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9981 litval >>= (blen-rlen);
9982 litval &= (~mask) & 0xff;
9983 emitPtrByteGet (rname, p_type, FALSE);
9984 if ((mask|litval)!=0xff)
9985 emitcode ("anl","a,#0x%02x", mask);
9987 emitcode ("orl","a,#0x%02x", litval);
9992 /* Case with partial byte and arbitrary source
9994 MOVA (aopGet (right, offset++, FALSE, FALSE));
9995 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9998 /* transfer A to B and get next byte */
9999 emitPtrByteGet (rname, p_type, TRUE);
10001 emitcode ("anl", "a,#0x%02x", mask);
10002 emitcode ("orl", "a,b");
10003 if (p_type == GPOINTER)
10004 emitcode ("pop", "b");
10008 emitPtrByteSet (rname, p_type, "a");
10014 /*-----------------------------------------------------------------*/
10015 /* genDataPointerSet - remat pointer to data space */
10016 /*-----------------------------------------------------------------*/
10018 genDataPointerSet (operand * right,
10022 int size, offset = 0;
10023 char *l, buffer[256];
10025 D(emitcode ("; genDataPointerSet",""));
10027 aopOp (right, ic, FALSE);
10029 l = aopGet (result, 0, FALSE, TRUE);
10030 size = AOP_SIZE (right);
10034 sprintf (buffer, "(%s + %d)", l + 1, offset);
10036 sprintf (buffer, "%s", l + 1);
10037 emitcode ("mov", "%s,%s", buffer,
10038 aopGet (right, offset++, FALSE, FALSE));
10041 freeAsmop (right, NULL, ic, TRUE);
10042 freeAsmop (result, NULL, ic, TRUE);
10045 /*-----------------------------------------------------------------*/
10046 /* genNearPointerSet - emitcode for near pointer put */
10047 /*-----------------------------------------------------------------*/
10049 genNearPointerSet (operand * right,
10057 sym_link *retype, *letype;
10058 sym_link *ptype = operandType (result);
10060 D(emitcode ("; genNearPointerSet",""));
10062 retype = getSpec (operandType (right));
10063 letype = getSpec (ptype);
10064 aopOp (result, ic, FALSE);
10066 /* if the result is rematerializable &
10067 in data space & not a bit variable */
10068 if (AOP_TYPE (result) == AOP_IMMD &&
10069 DCL_TYPE (ptype) == POINTER &&
10070 !IS_BITVAR (retype) &&
10071 !IS_BITVAR (letype))
10073 genDataPointerSet (right, result, ic);
10077 /* if the value is already in a pointer register
10078 then don't need anything more */
10079 if (!AOP_INPREG (AOP (result)))
10082 //AOP_TYPE (result) == AOP_STK
10083 IS_AOP_PREG(result)
10086 // Aha, it is a pointer, just in disguise.
10087 rname = aopGet (result, 0, FALSE, FALSE);
10090 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10091 __FILE__, __LINE__);
10096 emitcode ("mov", "a%s,%s", rname + 1, rname);
10097 rname++; // skip the '@'.
10102 /* otherwise get a free pointer register */
10103 aop = newAsmop (0);
10104 preg = getFreePtr (ic, &aop, FALSE);
10105 emitcode ("mov", "%s,%s",
10107 aopGet (result, 0, FALSE, TRUE));
10108 rname = preg->name;
10113 rname = aopGet (result, 0, FALSE, FALSE);
10116 aopOp (right, ic, FALSE);
10118 /* if bitfield then unpack the bits */
10119 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10120 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10123 /* we have can just get the values */
10124 int size = AOP_SIZE (right);
10129 l = aopGet (right, offset, FALSE, TRUE);
10133 emitcode ("mov", "@%s,a", rname);
10136 emitcode ("mov", "@%s,%s", rname, l);
10138 emitcode ("inc", "%s", rname);
10143 /* now some housekeeping stuff */
10144 if (aop) /* we had to allocate for this iCode */
10147 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10148 freeAsmop (NULL, aop, ic, TRUE);
10152 /* we did not allocate which means left
10153 already in a pointer register, then
10154 if size > 0 && this could be used again
10155 we have to point it back to where it
10157 if ((AOP_SIZE (right) > 1 &&
10158 !OP_SYMBOL (result)->remat &&
10159 (OP_SYMBOL (result)->liveTo > ic->seq ||
10163 int size = AOP_SIZE (right) - 1;
10165 emitcode ("dec", "%s", rname);
10170 if (pi) pi->generated = 1;
10171 freeAsmop (result, NULL, ic, TRUE);
10172 freeAsmop (right, NULL, ic, TRUE);
10175 /*-----------------------------------------------------------------*/
10176 /* genPagedPointerSet - emitcode for Paged pointer put */
10177 /*-----------------------------------------------------------------*/
10179 genPagedPointerSet (operand * right,
10187 sym_link *retype, *letype;
10189 D(emitcode ("; genPagedPointerSet",""));
10191 retype = getSpec (operandType (right));
10192 letype = getSpec (operandType (result));
10194 aopOp (result, ic, FALSE);
10196 /* if the value is already in a pointer register
10197 then don't need anything more */
10198 if (!AOP_INPREG (AOP (result)))
10200 /* otherwise get a free pointer register */
10201 aop = newAsmop (0);
10202 preg = getFreePtr (ic, &aop, FALSE);
10203 emitcode ("mov", "%s,%s",
10205 aopGet (result, 0, FALSE, TRUE));
10206 rname = preg->name;
10209 rname = aopGet (result, 0, FALSE, FALSE);
10211 aopOp (right, ic, FALSE);
10213 /* if bitfield then unpack the bits */
10214 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10215 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10218 /* we have can just get the values */
10219 int size = AOP_SIZE (right);
10224 l = aopGet (right, offset, FALSE, TRUE);
10227 emitcode ("movx", "@%s,a", rname);
10230 emitcode ("inc", "%s", rname);
10236 /* now some housekeeping stuff */
10237 if (aop) /* we had to allocate for this iCode */
10240 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10241 freeAsmop (NULL, aop, ic, TRUE);
10245 /* we did not allocate which means left
10246 already in a pointer register, then
10247 if size > 0 && this could be used again
10248 we have to point it back to where it
10250 if (AOP_SIZE (right) > 1 &&
10251 !OP_SYMBOL (result)->remat &&
10252 (OP_SYMBOL (result)->liveTo > ic->seq ||
10255 int size = AOP_SIZE (right) - 1;
10257 emitcode ("dec", "%s", rname);
10262 if (pi) pi->generated = 1;
10263 freeAsmop (result, NULL, ic, TRUE);
10264 freeAsmop (right, NULL, ic, TRUE);
10269 /*-----------------------------------------------------------------*/
10270 /* genFarPointerSet - set value from far space */
10271 /*-----------------------------------------------------------------*/
10273 genFarPointerSet (operand * right,
10274 operand * result, iCode * ic, iCode * pi)
10277 sym_link *retype = getSpec (operandType (right));
10278 sym_link *letype = getSpec (operandType (result));
10280 D(emitcode ("; genFarPointerSet",""));
10282 aopOp (result, ic, FALSE);
10283 loadDptrFromOperand (result, FALSE);
10285 /* so dptr know contains the address */
10286 aopOp (right, ic, FALSE);
10288 /* if bit then unpack */
10289 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10290 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10293 size = AOP_SIZE (right);
10298 char *l = aopGet (right, offset++, FALSE, FALSE);
10300 emitcode ("movx", "@dptr,a");
10302 emitcode ("inc", "dptr");
10305 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10306 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10307 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10310 freeAsmop (result, NULL, ic, TRUE);
10311 freeAsmop (right, NULL, ic, TRUE);
10314 /*-----------------------------------------------------------------*/
10315 /* genGenPointerSet - set value from generic pointer space */
10316 /*-----------------------------------------------------------------*/
10318 genGenPointerSet (operand * right,
10319 operand * result, iCode * ic, iCode * pi)
10322 sym_link *retype = getSpec (operandType (right));
10323 sym_link *letype = getSpec (operandType (result));
10325 D(emitcode ("; genGenPointerSet",""));
10327 aopOp (result, ic, FALSE);
10328 loadDptrFromOperand (result, TRUE);
10330 /* so dptr know contains the address */
10331 aopOp (right, ic, FALSE);
10333 /* if bit then unpack */
10334 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10335 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10338 size = AOP_SIZE (right);
10343 char *l = aopGet (right, offset++, FALSE, FALSE);
10345 emitcode ("lcall", "__gptrput");
10347 emitcode ("inc", "dptr");
10351 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10352 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10353 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10356 freeAsmop (result, NULL, ic, TRUE);
10357 freeAsmop (right, NULL, ic, TRUE);
10360 /*-----------------------------------------------------------------*/
10361 /* genPointerSet - stores the value into a pointer location */
10362 /*-----------------------------------------------------------------*/
10364 genPointerSet (iCode * ic, iCode *pi)
10366 operand *right, *result;
10367 sym_link *type, *etype;
10370 D(emitcode ("; genPointerSet",""));
10372 right = IC_RIGHT (ic);
10373 result = IC_RESULT (ic);
10375 /* depending on the type of pointer we need to
10376 move it to the correct pointer register */
10377 type = operandType (result);
10378 etype = getSpec (type);
10379 /* if left is of type of pointer then it is simple */
10380 if (IS_PTR (type) && !IS_FUNC (type->next))
10382 p_type = DCL_TYPE (type);
10386 /* we have to go by the storage class */
10387 p_type = PTR_TYPE (SPEC_OCLS (etype));
10390 /* special case when cast remat */
10391 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10392 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10393 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10394 type = operandType (result);
10395 p_type = DCL_TYPE (type);
10397 /* now that we have the pointer type we assign
10398 the pointer values */
10404 genNearPointerSet (right, result, ic, pi);
10408 genPagedPointerSet (right, result, ic, pi);
10412 genFarPointerSet (right, result, ic, pi);
10416 genGenPointerSet (right, result, ic, pi);
10420 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10421 "genPointerSet: illegal pointer type");
10426 /*-----------------------------------------------------------------*/
10427 /* genIfx - generate code for Ifx statement */
10428 /*-----------------------------------------------------------------*/
10430 genIfx (iCode * ic, iCode * popIc)
10432 operand *cond = IC_COND (ic);
10436 D(emitcode ("; genIfx",""));
10438 aopOp (cond, ic, FALSE);
10440 /* get the value into acc */
10441 if (AOP_TYPE (cond) != AOP_CRY)
10446 if (AOP(cond)->aopu.aop_dir)
10447 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10449 /* the result is now in the accumulator or a directly addressable bit */
10450 freeAsmop (cond, NULL, ic, TRUE);
10452 /* if there was something to be popped then do it */
10456 /* if the condition is a bit variable */
10458 genIfxJump(ic, dup, NULL, NULL, NULL);
10459 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10460 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10461 else if (isbit && !IS_ITEMP (cond))
10462 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10464 genIfxJump (ic, "a", NULL, NULL, NULL);
10469 /*-----------------------------------------------------------------*/
10470 /* genAddrOf - generates code for address of */
10471 /*-----------------------------------------------------------------*/
10473 genAddrOf (iCode * ic)
10475 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10478 D(emitcode ("; genAddrOf",""));
10480 aopOp (IC_RESULT (ic), ic, FALSE);
10482 /* if the operand is on the stack then we
10483 need to get the stack offset of this
10487 /* if it has an offset then we need to compute
10491 emitcode ("mov", "a,%s", SYM_BP (sym));
10492 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10493 ((char) (sym->stack - _G.nRegsSaved)) :
10494 ((char) sym->stack)) & 0xff);
10495 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10499 /* we can just move _bp */
10500 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10502 /* fill the result with zero */
10503 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10508 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10514 /* object not on stack then we need the name */
10515 size = AOP_SIZE (IC_RESULT (ic));
10520 char s[SDCC_NAME_MAX];
10522 sprintf (s, "#(%s >> %d)",
10526 sprintf (s, "#%s", sym->rname);
10527 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10531 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10535 /*-----------------------------------------------------------------*/
10536 /* genFarFarAssign - assignment when both are in far space */
10537 /*-----------------------------------------------------------------*/
10539 genFarFarAssign (operand * result, operand * right, iCode * ic)
10541 int size = AOP_SIZE (right);
10545 D(emitcode ("; genFarFarAssign",""));
10547 /* first push the right side on to the stack */
10550 l = aopGet (right, offset++, FALSE, FALSE);
10552 emitcode ("push", "acc");
10555 freeAsmop (right, NULL, ic, FALSE);
10556 /* now assign DPTR to result */
10557 aopOp (result, ic, FALSE);
10558 size = AOP_SIZE (result);
10561 emitcode ("pop", "acc");
10562 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10564 freeAsmop (result, NULL, ic, FALSE);
10568 /*-----------------------------------------------------------------*/
10569 /* genAssign - generate code for assignment */
10570 /*-----------------------------------------------------------------*/
10572 genAssign (iCode * ic)
10574 operand *result, *right;
10576 unsigned long lit = 0L;
10578 D(emitcode("; genAssign",""));
10580 result = IC_RESULT (ic);
10581 right = IC_RIGHT (ic);
10583 /* if they are the same */
10584 if (operandsEqu (result, right) &&
10585 !isOperandVolatile (result, FALSE) &&
10586 !isOperandVolatile (right, FALSE))
10589 aopOp (right, ic, FALSE);
10591 /* special case both in far space */
10592 if (AOP_TYPE (right) == AOP_DPTR &&
10593 IS_TRUE_SYMOP (result) &&
10594 isOperandInFarSpace (result))
10597 genFarFarAssign (result, right, ic);
10601 aopOp (result, ic, TRUE);
10603 /* if they are the same registers */
10604 if (sameRegs (AOP (right), AOP (result)) &&
10605 !isOperandVolatile (result, FALSE) &&
10606 !isOperandVolatile (right, FALSE))
10609 /* if the result is a bit */
10610 if (AOP_TYPE (result) == AOP_CRY)
10613 /* if the right size is a literal then
10614 we know what the value is */
10615 if (AOP_TYPE (right) == AOP_LIT)
10617 if (((int) operandLitValue (right)))
10618 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10620 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10624 /* the right is also a bit variable */
10625 if (AOP_TYPE (right) == AOP_CRY)
10627 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10628 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10632 /* we need to or */
10634 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10638 /* bit variables done */
10640 size = AOP_SIZE (result);
10642 if (AOP_TYPE (right) == AOP_LIT)
10643 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10645 (AOP_TYPE (result) != AOP_REG) &&
10646 (AOP_TYPE (right) == AOP_LIT) &&
10647 !IS_FLOAT (operandType (right)) &&
10650 while ((size) && (lit))
10653 aopGet (right, offset, FALSE, FALSE),
10655 isOperandVolatile (result, FALSE));
10660 emitcode ("clr", "a");
10663 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10672 aopGet (right, offset, FALSE, FALSE),
10674 isOperandVolatile (result, FALSE));
10680 freeAsmop (right, NULL, ic, TRUE);
10681 freeAsmop (result, NULL, ic, TRUE);
10684 /*-----------------------------------------------------------------*/
10685 /* genJumpTab - generates code for jump table */
10686 /*-----------------------------------------------------------------*/
10688 genJumpTab (iCode * ic)
10690 symbol *jtab,*jtablo,*jtabhi;
10692 unsigned int count;
10694 D(emitcode ("; genJumpTab",""));
10696 count = elementsInSet( IC_JTLABELS (ic) );
10700 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10701 if the switch argument is in a register.
10702 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10703 /* (MB) What if peephole converts ljmp to sjmp or ret ???
10704 How will multiply by three be updated ???*/
10705 aopOp (IC_JTCOND (ic), ic, FALSE);
10706 /* get the condition into accumulator */
10707 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10709 /* multiply by three */
10710 emitcode ("add", "a,acc");
10711 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10712 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10714 jtab = newiTempLabel (NULL);
10715 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10716 emitcode ("jmp", "@a+dptr");
10717 emitcode ("", "%05d$:", jtab->key + 100);
10718 /* now generate the jump labels */
10719 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10720 jtab = setNextItem (IC_JTLABELS (ic)))
10721 emitcode ("ljmp", "%05d$", jtab->key + 100);
10725 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10726 if the switch argument is in a register.
10727 For n>6 this algorithm may be more compact */
10728 jtablo = newiTempLabel (NULL);
10729 jtabhi = newiTempLabel (NULL);
10731 /* get the condition into accumulator.
10732 Using b as temporary storage, if register push/pop is needed */
10733 aopOp (IC_JTCOND (ic), ic, FALSE);
10734 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10735 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10736 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10738 // (MB) what if B is in use???
10739 wassertl(!BINUSE, "B was in use");
10740 emitcode ("mov", "b,%s", l);
10743 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10747 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10748 emitcode ("movc", "a,@a+pc");
10749 emitcode ("push", "acc");
10752 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10753 emitcode ("movc", "a,@a+pc");
10754 emitcode ("push", "acc");
10758 /* this scales up to n<=255, but needs two more bytes
10759 and changes dptr */
10760 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10761 emitcode ("movc", "a,@a+dptr");
10762 emitcode ("push", "acc");
10765 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10766 emitcode ("movc", "a,@a+dptr");
10767 emitcode ("push", "acc");
10770 emitcode ("ret", "");
10772 /* now generate jump table, LSB */
10773 emitcode ("", "%05d$:", jtablo->key + 100);
10774 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10775 jtab = setNextItem (IC_JTLABELS (ic)))
10776 emitcode (".db", "%05d$", jtab->key + 100);
10778 /* now generate jump table, MSB */
10779 emitcode ("", "%05d$:", jtabhi->key + 100);
10780 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10781 jtab = setNextItem (IC_JTLABELS (ic)))
10782 emitcode (".db", "%05d$>>8", jtab->key + 100);
10786 /*-----------------------------------------------------------------*/
10787 /* genCast - gen code for casting */
10788 /*-----------------------------------------------------------------*/
10790 genCast (iCode * ic)
10792 operand *result = IC_RESULT (ic);
10793 sym_link *ctype = operandType (IC_LEFT (ic));
10794 sym_link *rtype = operandType (IC_RIGHT (ic));
10795 operand *right = IC_RIGHT (ic);
10798 D(emitcode("; genCast",""));
10800 /* if they are equivalent then do nothing */
10801 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10804 aopOp (right, ic, FALSE);
10805 aopOp (result, ic, FALSE);
10807 /* if the result is a bit (and not a bitfield) */
10808 // if (AOP_TYPE (result) == AOP_CRY)
10809 if (IS_BITVAR (OP_SYMBOL (result)->type)
10810 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10812 /* if the right size is a literal then
10813 we know what the value is */
10814 if (AOP_TYPE (right) == AOP_LIT)
10816 if (((int) operandLitValue (right)))
10817 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10819 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10824 /* the right is also a bit variable */
10825 if (AOP_TYPE (right) == AOP_CRY)
10827 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10828 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10832 /* we need to or */
10834 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10839 /* if they are the same size : or less */
10840 if (AOP_SIZE (result) <= AOP_SIZE (right))
10843 /* if they are in the same place */
10844 if (sameRegs (AOP (right), AOP (result)))
10847 /* if they in different places then copy */
10848 size = AOP_SIZE (result);
10853 aopGet (right, offset, FALSE, FALSE),
10855 isOperandVolatile (result, FALSE));
10862 /* if the result is of type pointer */
10863 if (IS_PTR (ctype))
10867 sym_link *type = operandType (right);
10868 sym_link *etype = getSpec (type);
10870 /* pointer to generic pointer */
10871 if (IS_GENPTR (ctype))
10874 p_type = DCL_TYPE (type);
10877 if (SPEC_SCLS(etype)==S_REGISTER) {
10878 // let's assume it is a generic pointer
10881 /* we have to go by the storage class */
10882 p_type = PTR_TYPE (SPEC_OCLS (etype));
10886 /* the first two bytes are known */
10887 size = GPTRSIZE - 1;
10892 aopGet (right, offset, FALSE, FALSE),
10894 isOperandVolatile (result, FALSE));
10897 /* the last byte depending on type */
10899 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10904 // pointerTypeToGPByte will have bitched.
10908 sprintf(gpValStr, "#0x%x", gpVal);
10909 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10914 /* just copy the pointers */
10915 size = AOP_SIZE (result);
10920 aopGet (right, offset, FALSE, FALSE),
10922 isOperandVolatile (result, FALSE));
10928 /* so we now know that the size of destination is greater
10929 than the size of the source */
10930 /* we move to result for the size of source */
10931 size = AOP_SIZE (right);
10936 aopGet (right, offset, FALSE, FALSE),
10938 isOperandVolatile (result, FALSE));
10942 /* now depending on the sign of the source && destination */
10943 size = AOP_SIZE (result) - AOP_SIZE (right);
10944 /* if unsigned or not an integral type */
10945 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10948 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10952 /* we need to extend the sign :{ */
10953 char *l = aopGet (right, AOP_SIZE (right) - 1,
10956 emitcode ("rlc", "a");
10957 emitcode ("subb", "a,acc");
10959 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10962 /* we are done hurray !!!! */
10965 freeAsmop (right, NULL, ic, TRUE);
10966 freeAsmop (result, NULL, ic, TRUE);
10970 /*-----------------------------------------------------------------*/
10971 /* genDjnz - generate decrement & jump if not zero instrucion */
10972 /*-----------------------------------------------------------------*/
10974 genDjnz (iCode * ic, iCode * ifx)
10976 symbol *lbl, *lbl1;
10980 D(emitcode ("; genDjnz",""));
10982 /* if the if condition has a false label
10983 then we cannot save */
10984 if (IC_FALSE (ifx))
10987 /* if the minus is not of the form
10989 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10990 !IS_OP_LITERAL (IC_RIGHT (ic)))
10993 if (operandLitValue (IC_RIGHT (ic)) != 1)
10996 /* if the size of this greater than one then no
10998 if (getSize (operandType (IC_RESULT (ic))) > 1)
11001 /* otherwise we can save BIG */
11002 lbl = newiTempLabel (NULL);
11003 lbl1 = newiTempLabel (NULL);
11005 aopOp (IC_RESULT (ic), ic, FALSE);
11007 if (AOP_NEEDSACC(IC_RESULT(ic)))
11009 /* If the result is accessed indirectly via
11010 * the accumulator, we must explicitly write
11011 * it back after the decrement.
11013 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
11015 if (strcmp(rByte, "a"))
11017 /* Something is hopelessly wrong */
11018 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11019 __FILE__, __LINE__);
11020 /* We can just give up; the generated code will be inefficient,
11021 * but what the hey.
11023 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11026 emitcode ("dec", "%s", rByte);
11027 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
11028 emitcode ("jnz", "%05d$", lbl->key + 100);
11030 else if (IS_AOP_PREG (IC_RESULT (ic)))
11032 emitcode ("dec", "%s",
11033 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11034 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11035 emitcode ("jnz", "%05d$", lbl->key + 100);
11039 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11042 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11043 emitcode ("", "%05d$:", lbl->key + 100);
11044 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11045 emitcode ("", "%05d$:", lbl1->key + 100);
11047 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11048 ifx->generated = 1;
11052 /*-----------------------------------------------------------------*/
11053 /* genReceive - generate code for a receive iCode */
11054 /*-----------------------------------------------------------------*/
11056 genReceive (iCode * ic)
11058 int size = getSize (operandType (IC_RESULT (ic)));
11061 D(emitcode ("; genReceive",""));
11063 if (ic->argreg == 1)
11064 { /* first parameter */
11065 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11066 isOperandInPagedSpace (IC_RESULT (ic))) &&
11067 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11068 IS_TRUE_SYMOP (IC_RESULT (ic))))
11071 int receivingA = 0;
11074 for (offset = 0; offset<size; offset++)
11075 if (!strcmp (fReturn[offset], "a"))
11080 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11082 for (offset = size-1; offset>0; offset--)
11083 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11084 emitcode("mov","a,%s", fReturn[0]);
11086 aopOp (IC_RESULT (ic), ic, FALSE);
11088 aopPut (IC_RESULT (ic), "a", offset,
11089 isOperandVolatile (IC_RESULT (ic), FALSE));
11090 for (offset = 1; offset<size; offset++)
11091 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
11092 isOperandVolatile (IC_RESULT (ic), FALSE));
11098 if (getTempRegs(tempRegs, size, ic))
11100 for (offset = 0; offset<size; offset++)
11101 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11102 aopOp (IC_RESULT (ic), ic, FALSE);
11103 for (offset = 0; offset<size; offset++)
11104 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
11105 isOperandVolatile (IC_RESULT (ic), FALSE));
11110 offset = fReturnSizeMCS51 - size;
11113 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11114 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11117 aopOp (IC_RESULT (ic), ic, FALSE);
11118 size = AOP_SIZE (IC_RESULT (ic));
11122 emitcode ("pop", "acc");
11123 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11129 aopOp (IC_RESULT (ic), ic, FALSE);
11131 assignResultValue (IC_RESULT (ic), NULL);
11134 else if (ic->argreg > 12)
11135 { /* bit parameters */
11136 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11138 aopOp (IC_RESULT (ic), ic, FALSE);
11139 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11140 outBitC(IC_RESULT (ic));
11144 { /* other parameters */
11146 aopOp (IC_RESULT (ic), ic, FALSE);
11147 rb1off = ic->argreg;
11150 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11155 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11158 /*-----------------------------------------------------------------*/
11159 /* genDummyRead - generate code for dummy read of volatiles */
11160 /*-----------------------------------------------------------------*/
11162 genDummyRead (iCode * ic)
11167 D(emitcode("; genDummyRead",""));
11169 op = IC_RIGHT (ic);
11170 if (op && IS_SYMOP (op))
11172 aopOp (op, ic, FALSE);
11174 /* if the result is a bit */
11175 if (AOP_TYPE (op) == AOP_CRY)
11176 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11179 /* bit variables done */
11181 size = AOP_SIZE (op);
11185 MOVA (aopGet (op, offset, FALSE, FALSE));
11190 freeAsmop (op, NULL, ic, TRUE);
11194 if (op && IS_SYMOP (op))
11196 aopOp (op, ic, FALSE);
11198 /* if the result is a bit */
11199 if (AOP_TYPE (op) == AOP_CRY)
11200 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11203 /* bit variables done */
11205 size = AOP_SIZE (op);
11209 MOVA (aopGet (op, offset, FALSE, FALSE));
11214 freeAsmop (op, NULL, ic, TRUE);
11218 /*-----------------------------------------------------------------*/
11219 /* genCritical - generate code for start of a critical sequence */
11220 /*-----------------------------------------------------------------*/
11222 genCritical (iCode *ic)
11224 symbol *tlbl = newiTempLabel (NULL);
11226 D(emitcode("; genCritical",""));
11228 if (IC_RESULT (ic))
11230 aopOp (IC_RESULT (ic), ic, TRUE);
11231 aopPut (IC_RESULT (ic), one, 0, 0);
11232 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11233 aopPut (IC_RESULT (ic), zero, 0, 0);
11234 emitcode ("", "%05d$:", (tlbl->key + 100));
11235 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11239 emitcode ("setb", "c");
11240 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11241 emitcode ("clr", "c");
11242 emitcode ("", "%05d$:", (tlbl->key + 100));
11243 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11247 /*-----------------------------------------------------------------*/
11248 /* genEndCritical - generate code for end of a critical sequence */
11249 /*-----------------------------------------------------------------*/
11251 genEndCritical (iCode *ic)
11253 D(emitcode("; genEndCritical",""));
11257 aopOp (IC_RIGHT (ic), ic, FALSE);
11258 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11260 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11261 emitcode ("mov", "ea,c");
11265 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11266 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11267 emitcode ("rrc", "a");
11268 emitcode ("mov", "ea,c");
11270 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11274 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11275 emitcode ("mov", "ea,c");
11279 /*-----------------------------------------------------------------*/
11280 /* gen51Code - generate code for 8051 based controllers */
11281 /*-----------------------------------------------------------------*/
11283 gen51Code (iCode * lic)
11287 /* int cseq = 0; */
11289 _G.currentFunc = NULL;
11290 lineHead = lineCurr = NULL;
11292 /* print the allocation information */
11293 if (allocInfo && currFunc)
11294 printAllocInfo (currFunc, codeOutFile);
11295 /* if debug information required */
11296 if (options.debug && currFunc)
11298 debugFile->writeFunction (currFunc, lic);
11300 /* stack pointer name */
11301 if (options.useXstack)
11307 for (ic = lic; ic; ic = ic->next)
11309 _G.current_iCode = ic;
11311 if (ic->lineno && cln != ic->lineno)
11315 debugFile->writeCLine (ic);
11317 if (!options.noCcodeInAsm) {
11318 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11319 printCLine(ic->filename, ic->lineno));
11324 if (ic->seqPoint && ic->seqPoint != cseq)
11326 emitcode ("", "; sequence point %d", ic->seqPoint);
11327 cseq = ic->seqPoint;
11330 if (options.iCodeInAsm) {
11331 char regsInUse[80];
11334 for (i=0; i<8; i++) {
11335 sprintf (®sInUse[i],
11336 "%c", ic->riu & (1<<i) ? i+'0' : '-');
11339 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11341 /* if the result is marked as
11342 spilt and rematerializable or code for
11343 this has already been generated then
11345 if (resultRemat (ic) || ic->generated)
11348 /* depending on the operation */
11368 /* IPOP happens only when trying to restore a
11369 spilt live range, if there is an ifx statement
11370 following this pop then the if statement might
11371 be using some of the registers being popped which
11372 would destory the contents of the register so
11373 we need to check for this condition and handle it */
11375 ic->next->op == IFX &&
11376 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11377 genIfx (ic->next, ic);
11395 genEndFunction (ic);
11415 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11432 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11436 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11443 /* note these two are xlated by algebraic equivalence
11444 during parsing SDCC.y */
11445 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11446 "got '>=' or '<=' shouldn't have come here");
11450 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11462 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11466 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11470 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11506 genRightShift (ic);
11509 case GET_VALUE_AT_ADDRESS:
11511 hasInc (IC_LEFT (ic), ic,
11512 getSize (operandType (IC_RESULT (ic)))),
11513 ifxForOp (IC_RESULT (ic), ic) );
11517 if (POINTER_SET (ic))
11518 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11544 addSet (&_G.sendSet, ic);
11547 case DUMMY_READ_VOLATILE:
11556 genEndCritical (ic);
11568 _G.current_iCode = NULL;
11570 /* now we are ready to call the
11571 peep hole optimizer */
11572 if (!options.nopeep)
11573 peepHole (&lineHead);
11575 /* now do the actual printing */
11576 printLine (lineHead, codeOutFile);