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 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4478 if (AOP_NEEDSACC (IC_RESULT (ic)))
4479 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4487 /*-----------------------------------------------------------------*/
4488 /* addSign - complete with sign */
4489 /*-----------------------------------------------------------------*/
4491 addSign (operand * result, int offset, int sign)
4493 int size = (getDataSize (result) - offset);
4498 emitcode ("rlc", "a");
4499 emitcode ("subb", "a,acc");
4501 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4505 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4509 /*-----------------------------------------------------------------*/
4510 /* genMinusBits - generates code for subtraction of two bits */
4511 /*-----------------------------------------------------------------*/
4513 genMinusBits (iCode * ic)
4515 symbol *lbl = newiTempLabel (NULL);
4517 D(emitcode ("; genMinusBits",""));
4519 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4521 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4522 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4523 emitcode ("cpl", "c");
4524 emitcode ("", "%05d$:", (lbl->key + 100));
4525 outBitC (IC_RESULT (ic));
4529 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4530 emitcode ("subb", "a,acc");
4531 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4532 emitcode ("inc", "a");
4533 emitcode ("", "%05d$:", (lbl->key + 100));
4534 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4535 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4539 /*-----------------------------------------------------------------*/
4540 /* genMinus - generates code for subtraction */
4541 /*-----------------------------------------------------------------*/
4543 genMinus (iCode * ic)
4545 int size, offset = 0;
4547 D(emitcode ("; genMinus",""));
4549 aopOp (IC_LEFT (ic), ic, FALSE);
4550 aopOp (IC_RIGHT (ic), ic, FALSE);
4551 aopOp (IC_RESULT (ic), ic, TRUE);
4553 /* special cases :- */
4554 /* if both left & right are in bit space */
4555 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4556 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4562 /* if I can do an decrement instead
4563 of subtract then GOOD for ME */
4564 if (genMinusDec (ic) == TRUE)
4567 size = getDataSize (IC_RESULT (ic));
4569 /* if literal, add a,#-lit, else normal subb */
4570 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4572 unsigned long lit = 0L;
4573 bool useCarry = FALSE;
4575 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4580 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4582 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4583 if (!offset && !size && lit== (unsigned long) -1)
4585 emitcode ("dec", "a");
4589 /* first add without previous c */
4590 emitcode ("add", "a,#0x%02x",
4591 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4596 emitcode ("addc", "a,#0x%02x",
4597 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4599 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4603 /* no need to add zeroes */
4604 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4606 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4607 offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4615 operand *leftOp, *rightOp;
4617 leftOp = IC_LEFT(ic);
4618 rightOp = IC_RIGHT(ic);
4622 if (aopGetUsesAcc(rightOp, offset)) {
4623 if (aopGetUsesAcc(leftOp, offset)) {
4626 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4628 emitcode ("mov", "b,a");
4631 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4632 emitcode ("subb", "a,b");
4635 /* reverse subtraction with 2's complement */
4637 emitcode( "setb", "c");
4639 emitcode( "cpl", "c");
4640 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4641 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4642 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4643 emitcode("cpl", "a");
4644 if (size) /* skip if last byte */
4645 emitcode( "cpl", "c");
4648 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4651 emitcode ("subb", "a,%s",
4652 aopGet(rightOp, offset, FALSE, TRUE));
4655 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4660 adjustArithmeticResult (ic);
4663 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4664 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4665 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4669 /*-----------------------------------------------------------------*/
4670 /* genMultbits :- multiplication of bits */
4671 /*-----------------------------------------------------------------*/
4673 genMultbits (operand * left,
4677 D(emitcode ("; genMultbits",""));
4679 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4680 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4684 /*-----------------------------------------------------------------*/
4685 /* genMultOneByte : 8*8=8/16 bit multiplication */
4686 /*-----------------------------------------------------------------*/
4688 genMultOneByte (operand * left,
4693 int size = AOP_SIZE (result);
4694 bool runtimeSign, compiletimeSign;
4695 bool lUnsigned, rUnsigned, pushedB;
4697 D(emitcode ("; genMultOneByte",""));
4699 if (size < 1 || size > 2)
4701 /* this should never happen */
4702 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4703 AOP_SIZE(result), __FILE__, lineno);
4707 /* (if two literals: the value is computed before) */
4708 /* if one literal, literal on the right */
4709 if (AOP_TYPE (left) == AOP_LIT)
4714 /* emitcode (";", "swapped left and right"); */
4716 /* if no literal, unsigned on the right: shorter code */
4717 if ( AOP_TYPE (right) != AOP_LIT
4718 && SPEC_USIGN (getSpec (operandType (left))))
4725 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4726 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4730 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4731 no need to take care about the signedness! */
4732 || (lUnsigned && rUnsigned))
4734 /* just an unsigned 8 * 8 = 8 multiply
4736 /* emitcode (";","unsigned"); */
4737 /* TODO: check for accumulator clash between left & right aops? */
4739 if (AOP_TYPE (right) == AOP_LIT)
4741 /* moving to accumulator first helps peepholes */
4742 MOVA (aopGet (left, 0, FALSE, FALSE));
4743 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4747 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4748 MOVA (aopGet (left, 0, FALSE, FALSE));
4751 emitcode ("mul", "ab");
4752 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4754 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4760 /* we have to do a signed multiply */
4761 /* emitcode (";", "signed"); */
4763 /* now sign adjust for both left & right */
4765 /* let's see what's needed: */
4766 /* apply negative sign during runtime */
4767 runtimeSign = FALSE;
4768 /* negative sign from literals */
4769 compiletimeSign = FALSE;
4773 if (AOP_TYPE(left) == AOP_LIT)
4775 /* signed literal */
4776 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4778 compiletimeSign = TRUE;
4781 /* signed but not literal */
4787 if (AOP_TYPE(right) == AOP_LIT)
4789 /* signed literal */
4790 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4792 compiletimeSign ^= TRUE;
4795 /* signed but not literal */
4799 /* initialize F0, which stores the runtime sign */
4802 if (compiletimeSign)
4803 emitcode ("setb", "F0"); /* set sign flag */
4805 emitcode ("clr", "F0"); /* reset sign flag */
4808 /* save the signs of the operands */
4809 if (AOP_TYPE(right) == AOP_LIT)
4811 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4813 if (!rUnsigned && val < 0)
4814 emitcode ("mov", "b,#0x%02x", -val);
4816 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4818 else /* ! literal */
4820 if (rUnsigned) /* emitcode (";", "signed"); */
4822 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4825 MOVA (aopGet (right, 0, FALSE, FALSE));
4826 lbl = newiTempLabel (NULL);
4827 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4828 emitcode ("cpl", "F0"); /* complement sign flag */
4829 emitcode ("cpl", "a"); /* 2's complement */
4830 emitcode ("inc", "a");
4831 emitcode ("", "%05d$:", (lbl->key + 100));
4832 emitcode ("mov", "b,a");
4836 if (AOP_TYPE(left) == AOP_LIT)
4838 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4840 if (!lUnsigned && val < 0)
4841 emitcode ("mov", "a,#0x%02x", -val);
4843 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4845 else /* ! literal */
4847 MOVA (aopGet (left, 0, FALSE, FALSE));
4851 lbl = newiTempLabel (NULL);
4852 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4853 emitcode ("cpl", "F0"); /* complement sign flag */
4854 emitcode ("cpl", "a"); /* 2's complement */
4855 emitcode ("inc", "a");
4856 emitcode ("", "%05d$:", (lbl->key + 100));
4860 /* now the multiplication */
4861 emitcode ("mul", "ab");
4862 if (runtimeSign || compiletimeSign)
4864 lbl = newiTempLabel (NULL);
4866 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4867 emitcode ("cpl", "a"); /* lsb 2's complement */
4869 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4872 emitcode ("add", "a,#1"); /* this sets carry flag */
4873 emitcode ("xch", "a,b");
4874 emitcode ("cpl", "a"); /* msb 2's complement */
4875 emitcode ("addc", "a,#0");
4876 emitcode ("xch", "a,b");
4878 emitcode ("", "%05d$:", (lbl->key + 100));
4880 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4882 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4887 /*-----------------------------------------------------------------*/
4888 /* genMult - generates code for multiplication */
4889 /*-----------------------------------------------------------------*/
4891 genMult (iCode * ic)
4893 operand *left = IC_LEFT (ic);
4894 operand *right = IC_RIGHT (ic);
4895 operand *result = IC_RESULT (ic);
4897 D(emitcode ("; genMult",""));
4899 /* assign the asmops */
4900 aopOp (left, ic, FALSE);
4901 aopOp (right, ic, FALSE);
4902 aopOp (result, ic, TRUE);
4904 /* special cases first */
4906 if (AOP_TYPE (left) == AOP_CRY &&
4907 AOP_TYPE (right) == AOP_CRY)
4909 genMultbits (left, right, result);
4913 /* if both are of size == 1 */
4914 #if 0 // one of them can be a sloc shared with the result
4915 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4917 if (getSize(operandType(left)) == 1 &&
4918 getSize(operandType(right)) == 1)
4921 genMultOneByte (left, right, result);
4925 /* should have been converted to function call */
4926 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4927 getSize(OP_SYMBOL(right)->type));
4931 freeAsmop (result, NULL, ic, TRUE);
4932 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4933 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4936 /*-----------------------------------------------------------------*/
4937 /* genDivbits :- division of bits */
4938 /*-----------------------------------------------------------------*/
4940 genDivbits (operand * left,
4947 D(emitcode ("; genDivbits",""));
4951 /* the result must be bit */
4952 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4953 l = aopGet (left, 0, FALSE, FALSE);
4957 emitcode ("div", "ab");
4958 emitcode ("rrc", "a");
4962 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4965 /*-----------------------------------------------------------------*/
4966 /* genDivOneByte : 8 bit division */
4967 /*-----------------------------------------------------------------*/
4969 genDivOneByte (operand * left,
4973 bool lUnsigned, rUnsigned, pushedB;
4974 bool runtimeSign, compiletimeSign;
4975 bool accuse = FALSE;
4976 bool pushedA = FALSE;
4980 D(emitcode ("; genDivOneByte",""));
4982 /* Why is it necessary that genDivOneByte() can return an int result?
4985 volatile unsigned char uc;
4986 volatile signed char sc1, sc2;
4999 In all cases a one byte result would overflow, the following cast to int
5000 would return the wrong result.
5002 Two possible solution:
5003 a) cast operands to int, if ((unsigned) / (signed)) or
5004 ((signed) / (signed))
5005 b) return an 16 bit signed int; this is what we're doing here!
5008 size = AOP_SIZE (result) - 1;
5010 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5011 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5015 /* signed or unsigned */
5016 if (lUnsigned && rUnsigned)
5018 /* unsigned is easy */
5019 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5020 MOVA (aopGet (left, 0, FALSE, FALSE));
5021 emitcode ("div", "ab");
5022 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5024 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5030 /* signed is a little bit more difficult */
5032 /* now sign adjust for both left & right */
5034 /* let's see what's needed: */
5035 /* apply negative sign during runtime */
5036 runtimeSign = FALSE;
5037 /* negative sign from literals */
5038 compiletimeSign = FALSE;
5042 if (AOP_TYPE(left) == AOP_LIT)
5044 /* signed literal */
5045 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5047 compiletimeSign = TRUE;
5050 /* signed but not literal */
5056 if (AOP_TYPE(right) == AOP_LIT)
5058 /* signed literal */
5059 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5061 compiletimeSign ^= TRUE;
5064 /* signed but not literal */
5068 /* initialize F0, which stores the runtime sign */
5071 if (compiletimeSign)
5072 emitcode ("setb", "F0"); /* set sign flag */
5074 emitcode ("clr", "F0"); /* reset sign flag */
5077 /* save the signs of the operands */
5078 if (AOP_TYPE(right) == AOP_LIT)
5080 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5082 if (!rUnsigned && val < 0)
5083 emitcode ("mov", "b,#0x%02x", -val);
5085 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5087 else /* ! literal */
5090 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5093 MOVA (aopGet (right, 0, FALSE, FALSE));
5094 lbl = newiTempLabel (NULL);
5095 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5096 emitcode ("cpl", "F0"); /* complement sign flag */
5097 emitcode ("cpl", "a"); /* 2's complement */
5098 emitcode ("inc", "a");
5099 emitcode ("", "%05d$:", (lbl->key + 100));
5100 emitcode ("mov", "b,a");
5104 if (AOP_TYPE(left) == AOP_LIT)
5106 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5108 if (!lUnsigned && val < 0)
5109 emitcode ("mov", "a,#0x%02x", -val);
5111 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5113 else /* ! literal */
5115 MOVA (aopGet (left, 0, FALSE, FALSE));
5119 lbl = newiTempLabel (NULL);
5120 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5121 emitcode ("cpl", "F0"); /* complement sign flag */
5122 emitcode ("cpl", "a"); /* 2's complement */
5123 emitcode ("inc", "a");
5124 emitcode ("", "%05d$:", (lbl->key + 100));
5128 /* now the division */
5129 emitcode ("div", "ab");
5131 if (runtimeSign || compiletimeSign)
5133 lbl = newiTempLabel (NULL);
5135 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5136 emitcode ("cpl", "a"); /* lsb 2's complement */
5137 emitcode ("inc", "a");
5138 emitcode ("", "%05d$:", (lbl->key + 100));
5140 accuse = aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5143 /* msb is 0x00 or 0xff depending on the sign */
5148 emitcode ("push", "acc");
5151 emitcode ("mov", "c,F0");
5152 emitcode ("subb", "a,acc");
5154 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5156 else /* compiletimeSign */
5158 if (aopPutUsesAcc (result, "#0xFF", offset))
5160 emitcode ("push", "acc");
5164 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5170 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5172 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5176 emitcode ("pop", "acc");
5180 /*-----------------------------------------------------------------*/
5181 /* genDiv - generates code for division */
5182 /*-----------------------------------------------------------------*/
5186 operand *left = IC_LEFT (ic);
5187 operand *right = IC_RIGHT (ic);
5188 operand *result = IC_RESULT (ic);
5190 D(emitcode ("; genDiv",""));
5192 /* assign the amsops */
5193 aopOp (left, ic, FALSE);
5194 aopOp (right, ic, FALSE);
5195 aopOp (result, ic, TRUE);
5197 /* special cases first */
5199 if (AOP_TYPE (left) == AOP_CRY &&
5200 AOP_TYPE (right) == AOP_CRY)
5202 genDivbits (left, right, result);
5206 /* if both are of size == 1 */
5207 if (AOP_SIZE (left) == 1 &&
5208 AOP_SIZE (right) == 1)
5210 genDivOneByte (left, right, result);
5214 /* should have been converted to function call */
5217 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5218 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5219 freeAsmop (result, NULL, ic, TRUE);
5222 /*-----------------------------------------------------------------*/
5223 /* genModbits :- modulus of bits */
5224 /*-----------------------------------------------------------------*/
5226 genModbits (operand * left,
5233 D(emitcode ("; genModbits",""));
5237 /* the result must be bit */
5238 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5239 l = aopGet (left, 0, FALSE, FALSE);
5243 emitcode ("div", "ab");
5244 emitcode ("mov", "a,b");
5245 emitcode ("rrc", "a");
5249 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5252 /*-----------------------------------------------------------------*/
5253 /* genModOneByte : 8 bit modulus */
5254 /*-----------------------------------------------------------------*/
5256 genModOneByte (operand * left,
5260 bool lUnsigned, rUnsigned, pushedB;
5261 bool runtimeSign, compiletimeSign;
5265 D(emitcode ("; genModOneByte",""));
5267 size = AOP_SIZE (result) - 1;
5269 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5270 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5272 /* if right is a literal, check it for 2^n */
5273 if (AOP_TYPE(right) == AOP_LIT)
5275 unsigned char val = abs((int) operandLitValue(right));
5276 symbol *lbl2 = NULL;
5280 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5289 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5290 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5291 /* because iCode should have been changed to genAnd */
5292 /* see file "SDCCopt.c", function "convertToFcall()" */
5294 MOVA (aopGet (left, 0, FALSE, FALSE));
5295 emitcode ("mov", "c,acc.7");
5296 emitcode ("anl", "a,#0x%02x", val - 1);
5297 lbl = newiTempLabel (NULL);
5298 emitcode ("jz", "%05d$", (lbl->key + 100));
5299 emitcode ("jnc", "%05d$", (lbl->key + 100));
5300 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5306 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5308 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5309 lbl2 = newiTempLabel (NULL);
5310 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5312 emitcode ("", "%05d$:", (lbl->key + 100));
5313 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5315 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5318 emitcode ("", "%05d$:", (lbl2->key + 100));
5329 /* signed or unsigned */
5330 if (lUnsigned && rUnsigned)
5332 /* unsigned is easy */
5333 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5334 MOVA (aopGet (left, 0, FALSE, FALSE));
5335 emitcode ("div", "ab");
5336 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5338 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5344 /* signed is a little bit more difficult */
5346 /* now sign adjust for both left & right */
5348 /* modulus: sign of the right operand has no influence on the result! */
5349 if (AOP_TYPE(right) == AOP_LIT)
5351 signed char val = (char) operandLitValue(right);
5353 if (!rUnsigned && val < 0)
5354 emitcode ("mov", "b,#0x%02x", -val);
5356 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5358 else /* not literal */
5361 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5364 MOVA (aopGet (right, 0, FALSE, FALSE));
5365 lbl = newiTempLabel (NULL);
5366 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5367 emitcode ("cpl", "a"); /* 2's complement */
5368 emitcode ("inc", "a");
5369 emitcode ("", "%05d$:", (lbl->key + 100));
5370 emitcode ("mov", "b,a");
5374 /* let's see what's needed: */
5375 /* apply negative sign during runtime */
5376 runtimeSign = FALSE;
5377 /* negative sign from literals */
5378 compiletimeSign = FALSE;
5380 /* sign adjust left side */
5381 if (AOP_TYPE(left) == AOP_LIT)
5383 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5385 if (!lUnsigned && val < 0)
5387 compiletimeSign = TRUE; /* set sign flag */
5388 emitcode ("mov", "a,#0x%02x", -val);
5391 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5393 else /* ! literal */
5395 MOVA (aopGet (left, 0, FALSE, FALSE));
5400 emitcode ("clr", "F0"); /* clear sign flag */
5402 lbl = newiTempLabel (NULL);
5403 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5404 emitcode ("setb", "F0"); /* set sign flag */
5405 emitcode ("cpl", "a"); /* 2's complement */
5406 emitcode ("inc", "a");
5407 emitcode ("", "%05d$:", (lbl->key + 100));
5411 /* now the modulus */
5412 emitcode ("div", "ab");
5414 if (runtimeSign || compiletimeSign)
5416 emitcode ("mov", "a,b");
5417 lbl = newiTempLabel (NULL);
5419 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5420 emitcode ("cpl", "a"); /* 2's complement */
5421 emitcode ("inc", "a");
5422 emitcode ("", "%05d$:", (lbl->key + 100));
5424 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5427 /* msb is 0x00 or 0xff depending on the sign */
5430 emitcode ("mov", "c,F0");
5431 emitcode ("subb", "a,acc");
5433 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5435 else /* compiletimeSign */
5437 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5442 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5444 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5450 /*-----------------------------------------------------------------*/
5451 /* genMod - generates code for division */
5452 /*-----------------------------------------------------------------*/
5456 operand *left = IC_LEFT (ic);
5457 operand *right = IC_RIGHT (ic);
5458 operand *result = IC_RESULT (ic);
5460 D(emitcode ("; genMod",""));
5462 /* assign the asmops */
5463 aopOp (left, ic, FALSE);
5464 aopOp (right, ic, FALSE);
5465 aopOp (result, ic, TRUE);
5467 /* special cases first */
5469 if (AOP_TYPE (left) == AOP_CRY &&
5470 AOP_TYPE (right) == AOP_CRY)
5472 genModbits (left, right, result);
5476 /* if both are of size == 1 */
5477 if (AOP_SIZE (left) == 1 &&
5478 AOP_SIZE (right) == 1)
5480 genModOneByte (left, right, result);
5484 /* should have been converted to function call */
5488 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5489 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5490 freeAsmop (result, NULL, ic, TRUE);
5493 /*-----------------------------------------------------------------*/
5494 /* genIfxJump :- will create a jump depending on the ifx */
5495 /*-----------------------------------------------------------------*/
5497 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5500 symbol *tlbl = newiTempLabel (NULL);
5503 D(emitcode ("; genIfxJump",""));
5505 /* if true label then we jump if condition
5509 jlbl = IC_TRUE (ic);
5510 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5511 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5515 /* false label is present */
5516 jlbl = IC_FALSE (ic);
5517 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5518 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5520 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5521 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5523 emitcode (inst, "%05d$", tlbl->key + 100);
5524 freeForBranchAsmop (result);
5525 freeForBranchAsmop (right);
5526 freeForBranchAsmop (left);
5527 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5528 emitcode ("", "%05d$:", tlbl->key + 100);
5530 /* mark the icode as generated */
5534 /*-----------------------------------------------------------------*/
5535 /* genCmp :- greater or less than comparison */
5536 /*-----------------------------------------------------------------*/
5538 genCmp (operand * left, operand * right,
5539 operand * result, iCode * ifx, int sign, iCode *ic)
5541 int size, offset = 0;
5542 unsigned long lit = 0L;
5545 D(emitcode ("; genCmp",""));
5547 /* if left & right are bit variables */
5548 if (AOP_TYPE (left) == AOP_CRY &&
5549 AOP_TYPE (right) == AOP_CRY)
5551 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5552 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5556 /* subtract right from left if at the
5557 end the carry flag is set then we know that
5558 left is greater than right */
5559 size = max (AOP_SIZE (left), AOP_SIZE (right));
5561 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5562 if ((size == 1) && !sign &&
5563 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5565 symbol *lbl = newiTempLabel (NULL);
5566 emitcode ("cjne", "%s,%s,%05d$",
5567 aopGet (left, offset, FALSE, FALSE),
5568 aopGet (right, offset, FALSE, FALSE),
5570 emitcode ("", "%05d$:", lbl->key + 100);
5574 if (AOP_TYPE (right) == AOP_LIT)
5576 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5577 /* optimize if(x < 0) or if(x >= 0) */
5586 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5587 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5589 genIfxJump (ifx, "acc.7", left, right, result);
5590 freeAsmop (right, NULL, ic, TRUE);
5591 freeAsmop (left, NULL, ic, TRUE);
5596 emitcode ("rlc", "a");
5604 bool pushedB = FALSE;
5605 rightInB = aopGetUsesAcc(right, offset);
5609 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5611 MOVA (aopGet (left, offset, FALSE, FALSE));
5612 if (sign && size == 0)
5614 emitcode ("xrl", "a,#0x80");
5615 if (AOP_TYPE (right) == AOP_LIT)
5617 unsigned long lit = (unsigned long)
5618 floatFromVal (AOP (right)->aopu.aop_lit);
5619 emitcode ("subb", "a,#0x%02x",
5620 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5628 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5630 emitcode ("xrl", "b,#0x80");
5631 emitcode ("subb", "a,b");
5637 emitcode ("subb", "a,b");
5639 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5649 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5650 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5651 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5657 /* if the result is used in the next
5658 ifx conditional branch then generate
5659 code a little differently */
5661 genIfxJump (ifx, "c", NULL, NULL, result);
5664 /* leave the result in acc */
5668 /*-----------------------------------------------------------------*/
5669 /* genCmpGt :- greater than comparison */
5670 /*-----------------------------------------------------------------*/
5672 genCmpGt (iCode * ic, iCode * ifx)
5674 operand *left, *right, *result;
5675 sym_link *letype, *retype;
5678 D(emitcode ("; genCmpGt",""));
5680 left = IC_LEFT (ic);
5681 right = IC_RIGHT (ic);
5682 result = IC_RESULT (ic);
5684 letype = getSpec (operandType (left));
5685 retype = getSpec (operandType (right));
5686 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5687 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5688 /* assign the amsops */
5689 aopOp (left, ic, FALSE);
5690 aopOp (right, ic, FALSE);
5691 aopOp (result, ic, TRUE);
5693 genCmp (right, left, result, ifx, sign, ic);
5695 freeAsmop (result, NULL, ic, TRUE);
5698 /*-----------------------------------------------------------------*/
5699 /* genCmpLt - less than comparisons */
5700 /*-----------------------------------------------------------------*/
5702 genCmpLt (iCode * ic, iCode * ifx)
5704 operand *left, *right, *result;
5705 sym_link *letype, *retype;
5708 D(emitcode ("; genCmpLt",""));
5710 left = IC_LEFT (ic);
5711 right = IC_RIGHT (ic);
5712 result = IC_RESULT (ic);
5714 letype = getSpec (operandType (left));
5715 retype = getSpec (operandType (right));
5716 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5717 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5718 /* assign the amsops */
5719 aopOp (left, ic, FALSE);
5720 aopOp (right, ic, FALSE);
5721 aopOp (result, ic, TRUE);
5723 genCmp (left, right, result, ifx, sign, ic);
5725 freeAsmop (result, NULL, ic, TRUE);
5728 /*-----------------------------------------------------------------*/
5729 /* gencjneshort - compare and jump if not equal */
5730 /*-----------------------------------------------------------------*/
5732 gencjneshort (operand * left, operand * right, symbol * lbl)
5734 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5736 unsigned long lit = 0L;
5738 /* if the left side is a literal or
5739 if the right is in a pointer register and left
5741 if ((AOP_TYPE (left) == AOP_LIT) ||
5742 (AOP_TYPE (left) == AOP_IMMD) ||
5743 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5750 if (AOP_TYPE (right) == AOP_LIT)
5751 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5753 /* if the right side is a literal then anything goes */
5754 if (AOP_TYPE (right) == AOP_LIT &&
5755 AOP_TYPE (left) != AOP_DIR &&
5756 AOP_TYPE (left) != AOP_IMMD)
5760 emitcode ("cjne", "%s,%s,%05d$",
5761 aopGet (left, offset, FALSE, FALSE),
5762 aopGet (right, offset, FALSE, FALSE),
5768 /* if the right side is in a register or in direct space or
5769 if the left is a pointer register & right is not */
5770 else if (AOP_TYPE (right) == AOP_REG ||
5771 AOP_TYPE (right) == AOP_DIR ||
5772 AOP_TYPE (right) == AOP_LIT ||
5773 AOP_TYPE (right) == AOP_IMMD ||
5774 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5775 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5779 MOVA (aopGet (left, offset, FALSE, FALSE));
5780 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5781 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5782 emitcode ("jnz", "%05d$", lbl->key + 100);
5784 emitcode ("cjne", "a,%s,%05d$",
5785 aopGet (right, offset, FALSE, TRUE),
5792 /* right is a pointer reg need both a & b */
5796 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5797 wassertl(!BINUSE, "B was in use");
5798 l = aopGet (left, offset, FALSE, FALSE);
5799 if (strcmp (l, "b"))
5800 emitcode ("mov", "b,%s", l);
5801 MOVA (aopGet (right, offset, FALSE, FALSE));
5802 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5808 /*-----------------------------------------------------------------*/
5809 /* gencjne - compare and jump if not equal */
5810 /*-----------------------------------------------------------------*/
5812 gencjne (operand * left, operand * right, symbol * lbl)
5814 symbol *tlbl = newiTempLabel (NULL);
5816 gencjneshort (left, right, lbl);
5818 emitcode ("mov", "a,%s", one);
5819 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5820 emitcode ("", "%05d$:", lbl->key + 100);
5821 emitcode ("clr", "a");
5822 emitcode ("", "%05d$:", tlbl->key + 100);
5825 /*-----------------------------------------------------------------*/
5826 /* genCmpEq - generates code for equal to */
5827 /*-----------------------------------------------------------------*/
5829 genCmpEq (iCode * ic, iCode * ifx)
5831 operand *left, *right, *result;
5833 D(emitcode ("; genCmpEq",""));
5835 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5836 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5837 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5839 /* if literal, literal on the right or
5840 if the right is in a pointer register and left
5842 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5843 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5845 operand *t = IC_RIGHT (ic);
5846 IC_RIGHT (ic) = IC_LEFT (ic);
5850 if (ifx && !AOP_SIZE (result))
5853 /* if they are both bit variables */
5854 if (AOP_TYPE (left) == AOP_CRY &&
5855 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5857 if (AOP_TYPE (right) == AOP_LIT)
5859 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5862 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5863 emitcode ("cpl", "c");
5867 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5871 emitcode ("clr", "c");
5873 /* AOP_TYPE(right) == AOP_CRY */
5877 symbol *lbl = newiTempLabel (NULL);
5878 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5879 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5880 emitcode ("cpl", "c");
5881 emitcode ("", "%05d$:", (lbl->key + 100));
5883 /* if true label then we jump if condition
5885 tlbl = newiTempLabel (NULL);
5888 emitcode ("jnc", "%05d$", tlbl->key + 100);
5889 freeForBranchAsmop (result);
5890 freeForBranchAsmop (right);
5891 freeForBranchAsmop (left);
5892 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5896 emitcode ("jc", "%05d$", tlbl->key + 100);
5897 freeForBranchAsmop (result);
5898 freeForBranchAsmop (right);
5899 freeForBranchAsmop (left);
5900 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5902 emitcode ("", "%05d$:", tlbl->key + 100);
5906 tlbl = newiTempLabel (NULL);
5907 gencjneshort (left, right, tlbl);
5910 freeForBranchAsmop (result);
5911 freeForBranchAsmop (right);
5912 freeForBranchAsmop (left);
5913 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5914 emitcode ("", "%05d$:", tlbl->key + 100);
5918 symbol *lbl = newiTempLabel (NULL);
5919 emitcode ("sjmp", "%05d$", lbl->key + 100);
5920 emitcode ("", "%05d$:", tlbl->key + 100);
5921 freeForBranchAsmop (result);
5922 freeForBranchAsmop (right);
5923 freeForBranchAsmop (left);
5924 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5925 emitcode ("", "%05d$:", lbl->key + 100);
5928 /* mark the icode as generated */
5933 /* if they are both bit variables */
5934 if (AOP_TYPE (left) == AOP_CRY &&
5935 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5937 if (AOP_TYPE (right) == AOP_LIT)
5939 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5942 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5943 emitcode ("cpl", "c");
5947 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5951 emitcode ("clr", "c");
5953 /* AOP_TYPE(right) == AOP_CRY */
5957 symbol *lbl = newiTempLabel (NULL);
5958 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5959 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5960 emitcode ("cpl", "c");
5961 emitcode ("", "%05d$:", (lbl->key + 100));
5964 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5971 genIfxJump (ifx, "c", left, right, result);
5974 /* if the result is used in an arithmetic operation
5975 then put the result in place */
5980 gencjne (left, right, newiTempLabel (NULL));
5981 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5983 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5988 genIfxJump (ifx, "a", left, right, result);
5991 /* if the result is used in an arithmetic operation
5992 then put the result in place */
5993 if (AOP_TYPE (result) != AOP_CRY)
5995 /* leave the result in acc */
5999 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6000 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6001 freeAsmop (result, NULL, ic, TRUE);
6004 /*-----------------------------------------------------------------*/
6005 /* ifxForOp - returns the icode containing the ifx for operand */
6006 /*-----------------------------------------------------------------*/
6008 ifxForOp (operand * op, iCode * ic)
6010 /* if true symbol then needs to be assigned */
6011 if (IS_TRUE_SYMOP (op))
6014 /* if this has register type condition and
6015 the next instruction is ifx with the same operand
6016 and live to of the operand is upto the ifx only then */
6018 ic->next->op == IFX &&
6019 IC_COND (ic->next)->key == op->key &&
6020 OP_SYMBOL (op)->liveTo <= ic->next->seq)
6026 /*-----------------------------------------------------------------*/
6027 /* hasInc - operand is incremented before any other use */
6028 /*-----------------------------------------------------------------*/
6030 hasInc (operand *op, iCode *ic,int osize)
6032 sym_link *type = operandType(op);
6033 sym_link *retype = getSpec (type);
6034 iCode *lic = ic->next;
6037 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
6038 if (!IS_SYMOP(op)) return NULL;
6040 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
6041 if (IS_AGGREGATE(type->next)) return NULL;
6042 if (osize != (isize = getSize(type->next))) return NULL;
6045 /* if operand of the form op = op + <sizeof *op> */
6046 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
6047 isOperandEqual(IC_RESULT(lic),op) &&
6048 isOperandLiteral(IC_RIGHT(lic)) &&
6049 operandLitValue(IC_RIGHT(lic)) == isize) {
6052 /* if the operand used or deffed */
6053 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
6056 /* if GOTO or IFX */
6057 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
6063 /*-----------------------------------------------------------------*/
6064 /* genAndOp - for && operation */
6065 /*-----------------------------------------------------------------*/
6067 genAndOp (iCode * ic)
6069 operand *left, *right, *result;
6072 D(emitcode ("; genAndOp",""));
6074 /* note here that && operations that are in an
6075 if statement are taken away by backPatchLabels
6076 only those used in arthmetic operations remain */
6077 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6078 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6079 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6081 /* if both are bit variables */
6082 if (AOP_TYPE (left) == AOP_CRY &&
6083 AOP_TYPE (right) == AOP_CRY)
6085 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6086 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6091 tlbl = newiTempLabel (NULL);
6093 emitcode ("jz", "%05d$", tlbl->key + 100);
6095 emitcode ("", "%05d$:", tlbl->key + 100);
6099 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6100 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6101 freeAsmop (result, NULL, ic, TRUE);
6105 /*-----------------------------------------------------------------*/
6106 /* genOrOp - for || operation */
6107 /*-----------------------------------------------------------------*/
6109 genOrOp (iCode * ic)
6111 operand *left, *right, *result;
6114 D(emitcode ("; genOrOp",""));
6116 /* note here that || operations that are in an
6117 if statement are taken away by backPatchLabels
6118 only those used in arthmetic operations remain */
6119 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6120 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6121 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6123 /* if both are bit variables */
6124 if (AOP_TYPE (left) == AOP_CRY &&
6125 AOP_TYPE (right) == AOP_CRY)
6127 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6128 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6133 tlbl = newiTempLabel (NULL);
6135 emitcode ("jnz", "%05d$", tlbl->key + 100);
6137 emitcode ("", "%05d$:", tlbl->key + 100);
6141 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6142 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6143 freeAsmop (result, NULL, ic, TRUE);
6146 /*-----------------------------------------------------------------*/
6147 /* isLiteralBit - test if lit == 2^n */
6148 /*-----------------------------------------------------------------*/
6150 isLiteralBit (unsigned long lit)
6152 unsigned long pw[32] =
6153 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6154 0x100L, 0x200L, 0x400L, 0x800L,
6155 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6156 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6157 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6158 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6159 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6162 for (idx = 0; idx < 32; idx++)
6168 /*-----------------------------------------------------------------*/
6169 /* continueIfTrue - */
6170 /*-----------------------------------------------------------------*/
6172 continueIfTrue (iCode * ic)
6175 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6179 /*-----------------------------------------------------------------*/
6181 /*-----------------------------------------------------------------*/
6183 jumpIfTrue (iCode * ic)
6186 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6190 /*-----------------------------------------------------------------*/
6191 /* jmpTrueOrFalse - */
6192 /*-----------------------------------------------------------------*/
6194 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6196 // ugly but optimized by peephole
6199 symbol *nlbl = newiTempLabel (NULL);
6200 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6201 emitcode ("", "%05d$:", tlbl->key + 100);
6202 freeForBranchAsmop (result);
6203 freeForBranchAsmop (right);
6204 freeForBranchAsmop (left);
6205 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6206 emitcode ("", "%05d$:", nlbl->key + 100);
6210 freeForBranchAsmop (result);
6211 freeForBranchAsmop (right);
6212 freeForBranchAsmop (left);
6213 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6214 emitcode ("", "%05d$:", tlbl->key + 100);
6219 /*-----------------------------------------------------------------*/
6220 /* genAnd - code for and */
6221 /*-----------------------------------------------------------------*/
6223 genAnd (iCode * ic, iCode * ifx)
6225 operand *left, *right, *result;
6226 int size, offset = 0;
6227 unsigned long lit = 0L;
6231 D(emitcode ("; genAnd",""));
6233 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6234 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6235 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6238 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6240 AOP_TYPE (left), AOP_TYPE (right));
6241 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6243 AOP_SIZE (left), AOP_SIZE (right));
6246 /* if left is a literal & right is not then exchange them */
6247 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6248 AOP_NEEDSACC (left))
6250 operand *tmp = right;
6255 /* if result = right then exchange left and right */
6256 if (sameRegs (AOP (result), AOP (right)))
6258 operand *tmp = right;
6263 /* if right is bit then exchange them */
6264 if (AOP_TYPE (right) == AOP_CRY &&
6265 AOP_TYPE (left) != AOP_CRY)
6267 operand *tmp = right;
6271 if (AOP_TYPE (right) == AOP_LIT)
6272 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6274 size = AOP_SIZE (result);
6277 // result = bit & yy;
6278 if (AOP_TYPE (left) == AOP_CRY)
6280 // c = bit & literal;
6281 if (AOP_TYPE (right) == AOP_LIT)
6285 if (size && sameRegs (AOP (result), AOP (left)))
6288 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6293 if (size && (AOP_TYPE (result) == AOP_CRY))
6295 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6298 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6303 emitcode ("clr", "c");
6308 if (AOP_TYPE (right) == AOP_CRY)
6311 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6312 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6317 MOVA (aopGet (right, 0, FALSE, FALSE));
6319 emitcode ("rrc", "a");
6320 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6328 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6329 genIfxJump (ifx, "c", left, right, result);
6333 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6334 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6335 if ((AOP_TYPE (right) == AOP_LIT) &&
6336 (AOP_TYPE (result) == AOP_CRY) &&
6337 (AOP_TYPE (left) != AOP_CRY))
6339 int posbit = isLiteralBit (lit);
6344 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6348 switch (posbit & 0x07)
6350 case 0: emitcode ("rrc", "a");
6352 case 7: emitcode ("rlc", "a");
6354 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6363 SNPRINTF (buffer, sizeof(buffer),
6364 "acc.%d", posbit & 0x07);
6365 genIfxJump (ifx, buffer, left, right, result);
6368 {// what is this case? just found it in ds390/gen.c
6369 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6376 symbol *tlbl = newiTempLabel (NULL);
6377 int sizel = AOP_SIZE (left);
6379 emitcode ("setb", "c");
6382 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6384 MOVA (aopGet (left, offset, FALSE, FALSE));
6386 if ((posbit = isLiteralBit (bytelit)) != 0)
6387 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6390 if (bytelit != 0x0FFL)
6391 emitcode ("anl", "a,%s",
6392 aopGet (right, offset, FALSE, TRUE));
6393 emitcode ("jnz", "%05d$", tlbl->key + 100);
6398 // bit = left & literal
6401 emitcode ("clr", "c");
6402 emitcode ("", "%05d$:", tlbl->key + 100);
6404 // if(left & literal)
6408 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6410 emitcode ("", "%05d$:", tlbl->key + 100);
6418 /* if left is same as result */
6419 if (sameRegs (AOP (result), AOP (left)))
6421 for (; size--; offset++)
6423 if (AOP_TYPE (right) == AOP_LIT)
6425 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6426 if (bytelit == 0x0FF)
6428 /* dummy read of volatile operand */
6429 if (isOperandVolatile (left, FALSE))
6430 MOVA (aopGet (left, offset, FALSE, FALSE));
6434 else if (bytelit == 0)
6436 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6438 else if (IS_AOP_PREG (result))
6440 MOVA (aopGet (left, offset, FALSE, TRUE));
6441 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6442 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6445 emitcode ("anl", "%s,%s",
6446 aopGet (left, offset, FALSE, TRUE),
6447 aopGet (right, offset, FALSE, FALSE));
6451 if (AOP_TYPE (left) == AOP_ACC)
6454 emitcode("mov", "a,b");
6455 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6457 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6459 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6460 MOVA (aopGet (right, offset, FALSE, FALSE));
6461 emitcode ("anl", "a,b");
6462 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6464 else if (aopGetUsesAcc (left, offset))
6466 MOVA (aopGet (left, offset, FALSE, FALSE));
6467 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6468 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6472 MOVA (aopGet (right, offset, FALSE, FALSE));
6473 if (IS_AOP_PREG (result))
6475 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6476 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6479 emitcode ("anl", "%s,a",
6480 aopGet (left, offset, FALSE, TRUE));
6487 // left & result in different registers
6488 if (AOP_TYPE (result) == AOP_CRY)
6491 // if(size), result in bit
6492 // if(!size && ifx), conditional oper: if(left & right)
6493 symbol *tlbl = newiTempLabel (NULL);
6494 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6496 emitcode ("setb", "c");
6499 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6500 && AOP_TYPE(left)==AOP_ACC)
6503 emitcode("mov", "a,b");
6504 emitcode ("anl", "a,%s",
6505 aopGet (right, offset, FALSE, FALSE));
6507 if (AOP_TYPE(left)==AOP_ACC)
6511 bool pushedB = pushB ();
6512 emitcode("mov", "b,a");
6513 MOVA (aopGet (right, offset, FALSE, FALSE));
6514 emitcode("anl", "a,b");
6519 MOVA (aopGet (right, offset, FALSE, FALSE));
6520 emitcode("anl", "a,b");
6523 MOVA (aopGet (right, offset, FALSE, FALSE));
6524 emitcode ("anl", "a,%s",
6525 aopGet (left, offset, FALSE, FALSE));
6528 emitcode ("jnz", "%05d$", tlbl->key + 100);
6534 emitcode ("", "%05d$:", tlbl->key + 100);
6538 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6540 emitcode ("", "%05d$:", tlbl->key + 100);
6544 for (; (size--); offset++)
6547 // result = left & right
6548 if (AOP_TYPE (right) == AOP_LIT)
6550 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6551 if (bytelit == 0x0FF)
6554 aopGet (left, offset, FALSE, FALSE),
6556 isOperandVolatile (result, FALSE));
6559 else if (bytelit == 0)
6561 /* dummy read of volatile operand */
6562 if (isOperandVolatile (left, FALSE))
6563 MOVA (aopGet (left, offset, FALSE, FALSE));
6564 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6567 else if (AOP_TYPE (left) == AOP_ACC)
6571 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6572 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6577 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6578 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6583 // faster than result <- left, anl result,right
6584 // and better if result is SFR
6585 if (AOP_TYPE (left) == AOP_ACC)
6588 emitcode("mov", "a,b");
6589 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6591 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6593 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6594 MOVA (aopGet (right, offset, FALSE, FALSE));
6595 emitcode ("anl", "a,b");
6597 else if (aopGetUsesAcc (left, offset))
6599 MOVA (aopGet (left, offset, FALSE, FALSE));
6600 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6604 MOVA (aopGet (right, offset, FALSE, FALSE));
6605 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6607 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6613 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6614 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6615 freeAsmop (result, NULL, ic, TRUE);
6618 /*-----------------------------------------------------------------*/
6619 /* genOr - code for or */
6620 /*-----------------------------------------------------------------*/
6622 genOr (iCode * ic, iCode * ifx)
6624 operand *left, *right, *result;
6625 int size, offset = 0;
6626 unsigned long lit = 0L;
6629 D(emitcode ("; genOr",""));
6631 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6632 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6633 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6636 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6638 AOP_TYPE (left), AOP_TYPE (right));
6639 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6641 AOP_SIZE (left), AOP_SIZE (right));
6644 /* if left is a literal & right is not then exchange them */
6645 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6646 AOP_NEEDSACC (left))
6648 operand *tmp = right;
6653 /* if result = right then exchange them */
6654 if (sameRegs (AOP (result), AOP (right)))
6656 operand *tmp = right;
6661 /* if right is bit then exchange them */
6662 if (AOP_TYPE (right) == AOP_CRY &&
6663 AOP_TYPE (left) != AOP_CRY)
6665 operand *tmp = right;
6669 if (AOP_TYPE (right) == AOP_LIT)
6670 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6672 size = AOP_SIZE (result);
6676 if (AOP_TYPE (left) == AOP_CRY)
6678 if (AOP_TYPE (right) == AOP_LIT)
6680 // c = bit | literal;
6683 // lit != 0 => result = 1
6684 if (AOP_TYPE (result) == AOP_CRY)
6687 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6689 continueIfTrue (ifx);
6692 emitcode ("setb", "c");
6696 // lit == 0 => result = left
6697 if (size && sameRegs (AOP (result), AOP (left)))
6699 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6704 if (AOP_TYPE (right) == AOP_CRY)
6707 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6708 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6713 symbol *tlbl = newiTempLabel (NULL);
6714 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6715 emitcode ("setb", "c");
6716 emitcode ("jb", "%s,%05d$",
6717 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6719 emitcode ("jnz", "%05d$", tlbl->key + 100);
6720 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6722 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6728 emitcode ("", "%05d$:", tlbl->key + 100);
6737 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6738 genIfxJump (ifx, "c", left, right, result);
6742 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6743 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6744 if ((AOP_TYPE (right) == AOP_LIT) &&
6745 (AOP_TYPE (result) == AOP_CRY) &&
6746 (AOP_TYPE (left) != AOP_CRY))
6752 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6754 continueIfTrue (ifx);
6759 // lit = 0, result = boolean(left)
6761 emitcode ("setb", "c");
6765 symbol *tlbl = newiTempLabel (NULL);
6766 emitcode ("jnz", "%05d$", tlbl->key + 100);
6768 emitcode ("", "%05d$:", tlbl->key + 100);
6772 genIfxJump (ifx, "a", left, right, result);
6780 /* if left is same as result */
6781 if (sameRegs (AOP (result), AOP (left)))
6783 for (; size--; offset++)
6785 if (AOP_TYPE (right) == AOP_LIT)
6787 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6790 /* dummy read of volatile operand */
6791 if (isOperandVolatile (left, FALSE))
6792 MOVA (aopGet (left, offset, FALSE, FALSE));
6796 else if (bytelit == 0x0FF)
6798 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6800 else if (IS_AOP_PREG (left))
6802 MOVA (aopGet (left, offset, FALSE, TRUE));
6803 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6804 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6808 emitcode ("orl", "%s,%s",
6809 aopGet (left, offset, FALSE, TRUE),
6810 aopGet (right, offset, FALSE, FALSE));
6815 if (AOP_TYPE (left) == AOP_ACC)
6818 emitcode("mov", "a,b");
6819 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6821 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6823 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6824 MOVA (aopGet (right, offset, FALSE, FALSE));
6825 emitcode ("orl", "a,b");
6826 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6828 else if (aopGetUsesAcc (left, offset))
6830 MOVA (aopGet (left, offset, FALSE, FALSE));
6831 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6832 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6836 MOVA (aopGet (right, offset, FALSE, FALSE));
6837 if (IS_AOP_PREG (left))
6839 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6840 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6844 emitcode ("orl", "%s,a",
6845 aopGet (left, offset, FALSE, TRUE));
6853 // left & result in different registers
6854 if (AOP_TYPE (result) == AOP_CRY)
6857 // if(size), result in bit
6858 // if(!size && ifx), conditional oper: if(left | right)
6859 symbol *tlbl = newiTempLabel (NULL);
6860 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6862 emitcode ("setb", "c");
6865 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6867 emitcode("mov", "a,b");
6868 emitcode ("orl", "a,%s",
6869 aopGet (right, offset, FALSE, FALSE));
6871 MOVA (aopGet (right, offset, FALSE, FALSE));
6872 emitcode ("orl", "a,%s",
6873 aopGet (left, offset, FALSE, FALSE));
6875 emitcode ("jnz", "%05d$", tlbl->key + 100);
6881 emitcode ("", "%05d$:", tlbl->key + 100);
6885 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6887 emitcode ("", "%05d$:", tlbl->key + 100);
6891 for (; (size--); offset++)
6894 // result = left | right
6895 if (AOP_TYPE (right) == AOP_LIT)
6897 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6901 aopGet (left, offset, FALSE, FALSE),
6903 isOperandVolatile (result, FALSE));
6906 else if (bytelit == 0x0FF)
6908 /* dummy read of volatile operand */
6909 if (isOperandVolatile (left, FALSE))
6910 MOVA (aopGet (left, offset, FALSE, FALSE));
6911 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6915 // faster than result <- left, anl result,right
6916 // and better if result is SFR
6917 if (AOP_TYPE (left) == AOP_ACC)
6920 emitcode("mov", "a,b");
6921 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6923 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
6925 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
6926 MOVA (aopGet (right, offset, FALSE, FALSE));
6927 emitcode ("orl", "a,b");
6929 else if (aopGetUsesAcc (left, offset))
6931 MOVA (aopGet (left, offset, FALSE, FALSE));
6932 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6936 MOVA (aopGet (right, offset, FALSE, FALSE));
6937 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, FALSE));
6939 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6945 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6946 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6947 freeAsmop (result, NULL, ic, TRUE);
6950 /*-----------------------------------------------------------------*/
6951 /* genXor - code for xclusive or */
6952 /*-----------------------------------------------------------------*/
6954 genXor (iCode * ic, iCode * ifx)
6956 operand *left, *right, *result;
6957 int size, offset = 0;
6958 unsigned long lit = 0L;
6961 D(emitcode ("; genXor",""));
6963 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6964 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6965 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6968 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6970 AOP_TYPE (left), AOP_TYPE (right));
6971 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6973 AOP_SIZE (left), AOP_SIZE (right));
6976 /* if left is a literal & right is not ||
6977 if left needs acc & right does not */
6978 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6979 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6981 operand *tmp = right;
6986 /* if result = right then exchange them */
6987 if (sameRegs (AOP (result), AOP (right)))
6989 operand *tmp = right;
6994 /* if right is bit then exchange them */
6995 if (AOP_TYPE (right) == AOP_CRY &&
6996 AOP_TYPE (left) != AOP_CRY)
6998 operand *tmp = right;
7002 if (AOP_TYPE (right) == AOP_LIT)
7003 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
7005 size = AOP_SIZE (result);
7009 if (AOP_TYPE (left) == AOP_CRY)
7011 if (AOP_TYPE (right) == AOP_LIT)
7013 // c = bit & literal;
7016 // lit>>1 != 0 => result = 1
7017 if (AOP_TYPE (result) == AOP_CRY)
7020 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
7022 continueIfTrue (ifx);
7025 emitcode ("setb", "c");
7032 // lit == 0, result = left
7033 if (size && sameRegs (AOP (result), AOP (left)))
7035 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7039 // lit == 1, result = not(left)
7040 if (size && sameRegs (AOP (result), AOP (left)))
7042 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
7047 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
7048 emitcode ("cpl", "c");
7057 symbol *tlbl = newiTempLabel (NULL);
7058 if (AOP_TYPE (right) == AOP_CRY)
7061 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
7065 int sizer = AOP_SIZE (right);
7067 // if val>>1 != 0, result = 1
7068 emitcode ("setb", "c");
7071 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
7073 // test the msb of the lsb
7074 emitcode ("anl", "a,#0xfe");
7075 emitcode ("jnz", "%05d$", tlbl->key + 100);
7079 emitcode ("rrc", "a");
7081 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
7082 emitcode ("cpl", "c");
7083 emitcode ("", "%05d$:", (tlbl->key + 100));
7090 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
7091 genIfxJump (ifx, "c", left, right, result);
7095 /* if left is same as result */
7096 if (sameRegs (AOP (result), AOP (left)))
7098 for (; size--; offset++)
7100 if (AOP_TYPE (right) == AOP_LIT)
7102 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7105 /* dummy read of volatile operand */
7106 if (isOperandVolatile (left, FALSE))
7107 MOVA (aopGet (left, offset, FALSE, FALSE));
7111 else if (IS_AOP_PREG (left))
7113 MOVA (aopGet (left, offset, FALSE, TRUE));
7114 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7115 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7119 emitcode ("xrl", "%s,%s",
7120 aopGet (left, offset, FALSE, TRUE),
7121 aopGet (right, offset, FALSE, FALSE));
7126 if (AOP_TYPE (left) == AOP_ACC)
7129 emitcode("mov", "a,b");
7130 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7132 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7134 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7135 MOVA (aopGet (right, offset, FALSE, FALSE));
7136 emitcode ("xrl", "a,b");
7137 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7139 else if (aopGetUsesAcc (left, offset))
7141 MOVA (aopGet (left, offset, FALSE, FALSE));
7142 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7143 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7147 MOVA (aopGet (right, offset, FALSE, FALSE));
7148 if (IS_AOP_PREG (left))
7150 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7151 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7154 emitcode ("xrl", "%s,a",
7155 aopGet (left, offset, FALSE, TRUE));
7162 // left & result in different registers
7163 if (AOP_TYPE (result) == AOP_CRY)
7166 // if(size), result in bit
7167 // if(!size && ifx), conditional oper: if(left ^ right)
7168 symbol *tlbl = newiTempLabel (NULL);
7169 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7171 emitcode ("setb", "c");
7174 if ((AOP_TYPE (right) == AOP_LIT) &&
7175 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7177 MOVA (aopGet (left, offset, FALSE, FALSE));
7181 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7183 emitcode("mov", "a,b");
7184 emitcode ("xrl", "a,%s",
7185 aopGet (right, offset, FALSE, FALSE));
7187 MOVA (aopGet (right, offset, FALSE, FALSE));
7188 emitcode ("xrl", "a,%s",
7189 aopGet (left, offset, FALSE, FALSE));
7192 emitcode ("jnz", "%05d$", tlbl->key + 100);
7198 emitcode ("", "%05d$:", tlbl->key + 100);
7202 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7206 for (; (size--); offset++)
7209 // result = left & right
7210 if (AOP_TYPE (right) == AOP_LIT)
7212 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7216 aopGet (left, offset, FALSE, FALSE),
7218 isOperandVolatile (result, FALSE));
7222 // faster than result <- left, anl result,right
7223 // and better if result is SFR
7224 if (AOP_TYPE (left) == AOP_ACC)
7227 emitcode("mov", "a,b");
7228 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7230 else if (aopGetUsesAcc (left, offset) && aopGetUsesAcc (right, offset))
7232 emitcode ("mov", "b,%s", aopGet (left, offset, FALSE, FALSE));
7233 MOVA (aopGet (right, offset, FALSE, FALSE));
7234 emitcode ("xrl", "a,b");
7236 else if (aopGetUsesAcc (left, offset))
7238 MOVA (aopGet (left, offset, FALSE, FALSE));
7239 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7243 MOVA (aopGet (right, offset, FALSE, FALSE));
7244 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7246 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7252 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7253 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7254 freeAsmop (result, NULL, ic, TRUE);
7257 /*-----------------------------------------------------------------*/
7258 /* genInline - write the inline code out */
7259 /*-----------------------------------------------------------------*/
7261 genInline (iCode * ic)
7263 char *buffer, *bp, *bp1;
7265 D(emitcode ("; genInline",""));
7267 _G.inLine += (!options.asmpeep);
7269 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7270 strcpy (buffer, IC_INLINE (ic));
7272 /* emit each line as a code */
7283 /* Add \n for labels, not dirs such as c:\mydir */
7284 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7298 /* emitcode("",buffer); */
7299 _G.inLine -= (!options.asmpeep);
7302 /*-----------------------------------------------------------------*/
7303 /* genRRC - rotate right with carry */
7304 /*-----------------------------------------------------------------*/
7308 operand *left, *result;
7309 int size, offset = 0;
7312 D(emitcode ("; genRRC",""));
7314 /* rotate right with carry */
7315 left = IC_LEFT (ic);
7316 result = IC_RESULT (ic);
7317 aopOp (left, ic, FALSE);
7318 aopOp (result, ic, FALSE);
7320 /* move it to the result */
7321 size = AOP_SIZE (result);
7323 if (size == 1) { /* special case for 1 byte */
7324 l = aopGet (left, offset, FALSE, FALSE);
7326 emitcode ("rr", "a");
7329 /* no need to clear carry, bit7 will be written later */
7332 l = aopGet (left, offset, FALSE, FALSE);
7334 emitcode ("rrc", "a");
7335 if (AOP_SIZE (result) > 1)
7336 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7338 /* now we need to put the carry into the
7339 highest order byte of the result */
7340 if (AOP_SIZE (result) > 1)
7342 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7345 emitcode ("mov", "acc.7,c");
7347 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7348 freeAsmop (left, NULL, ic, TRUE);
7349 freeAsmop (result, NULL, ic, TRUE);
7352 /*-----------------------------------------------------------------*/
7353 /* genRLC - generate code for rotate left with carry */
7354 /*-----------------------------------------------------------------*/
7358 operand *left, *result;
7359 int size, offset = 0;
7362 D(emitcode ("; genRLC",""));
7364 /* rotate right with carry */
7365 left = IC_LEFT (ic);
7366 result = IC_RESULT (ic);
7367 aopOp (left, ic, FALSE);
7368 aopOp (result, ic, FALSE);
7370 /* move it to the result */
7371 size = AOP_SIZE (result);
7375 l = aopGet (left, offset, FALSE, FALSE);
7377 if (size == 0) { /* special case for 1 byte */
7381 emitcode("rlc","a"); /* bit0 will be written later */
7382 if (AOP_SIZE (result) > 1)
7383 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7386 l = aopGet (left, offset, FALSE, FALSE);
7388 emitcode ("rlc", "a");
7389 if (AOP_SIZE (result) > 1)
7390 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7393 /* now we need to put the carry into the
7394 highest order byte of the result */
7395 if (AOP_SIZE (result) > 1)
7397 l = aopGet (result, 0, FALSE, FALSE);
7400 emitcode ("mov", "acc.0,c");
7402 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7403 freeAsmop (left, NULL, ic, TRUE);
7404 freeAsmop (result, NULL, ic, TRUE);
7407 /*-----------------------------------------------------------------*/
7408 /* genGetHbit - generates code get highest order bit */
7409 /*-----------------------------------------------------------------*/
7411 genGetHbit (iCode * ic)
7413 operand *left, *result;
7415 D(emitcode ("; genGetHbit",""));
7417 left = IC_LEFT (ic);
7418 result = IC_RESULT (ic);
7419 aopOp (left, ic, FALSE);
7420 aopOp (result, ic, FALSE);
7422 /* get the highest order byte into a */
7423 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7424 if (AOP_TYPE (result) == AOP_CRY)
7426 emitcode ("rlc", "a");
7431 emitcode ("rl", "a");
7432 emitcode ("anl", "a,#0x01");
7437 freeAsmop (left, NULL, ic, TRUE);
7438 freeAsmop (result, NULL, ic, TRUE);
7441 /*-----------------------------------------------------------------*/
7442 /* genGetAbit - generates code get a single bit */
7443 /*-----------------------------------------------------------------*/
7445 genGetAbit (iCode * ic)
7447 operand *left, *right, *result;
7450 D(emitcode ("; genGetAbit",""));
7452 left = IC_LEFT (ic);
7453 right = IC_RIGHT (ic);
7454 result = IC_RESULT (ic);
7455 aopOp (left, ic, FALSE);
7456 aopOp (right, ic, FALSE);
7457 aopOp (result, ic, FALSE);
7459 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7461 /* get the needed byte into a */
7462 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7464 if (AOP_TYPE (result) == AOP_CRY)
7467 emitcode ("rlc", "a");
7468 else if ((shCount) == 0)
7469 emitcode ("rrc", "a");
7471 emitcode ("mov", "c,acc[%d]", shCount);
7479 emitcode ("rr", "a");
7482 emitcode ("rr", "a");
7485 emitcode ("anl", "a,#0x01");
7489 emitcode ("mov", "c,acc[%d]", shCount);
7490 emitcode ("clr", "a");
7491 emitcode ("rlc", "a");
7494 emitcode ("swap", "a");
7495 emitcode ("anl", "a,#0x01");
7498 emitcode ("rl", "a");
7501 emitcode ("rl", "a");
7502 emitcode ("anl", "a,#0x01");
7508 freeAsmop (left, NULL, ic, TRUE);
7509 freeAsmop (right, NULL, ic, TRUE);
7510 freeAsmop (result, NULL, ic, TRUE);
7513 /*-----------------------------------------------------------------*/
7514 /* genGetByte - generates code get a single byte */
7515 /*-----------------------------------------------------------------*/
7517 genGetByte (iCode * ic)
7519 operand *left, *right, *result;
7522 D(emitcode ("; genGetByte",""));
7524 left = IC_LEFT (ic);
7525 right = IC_RIGHT (ic);
7526 result = IC_RESULT (ic);
7527 aopOp (left, ic, FALSE);
7528 aopOp (right, ic, FALSE);
7529 aopOp (result, ic, FALSE);
7531 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7533 aopGet (left, offset, FALSE, FALSE),
7535 isOperandVolatile (result, FALSE));
7537 freeAsmop (left, NULL, ic, TRUE);
7538 freeAsmop (right, NULL, ic, TRUE);
7539 freeAsmop (result, NULL, ic, TRUE);
7542 /*-----------------------------------------------------------------*/
7543 /* genGetWord - generates code get two bytes */
7544 /*-----------------------------------------------------------------*/
7546 genGetWord (iCode * ic)
7548 operand *left, *right, *result;
7551 D(emitcode ("; genGetWord",""));
7553 left = IC_LEFT (ic);
7554 right = IC_RIGHT (ic);
7555 result = IC_RESULT (ic);
7556 aopOp (left, ic, FALSE);
7557 aopOp (right, ic, FALSE);
7558 aopOp (result, ic, FALSE);
7560 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7562 aopGet (left, offset, FALSE, FALSE),
7564 isOperandVolatile (result, FALSE));
7566 aopGet (left, offset+1, FALSE, FALSE),
7568 isOperandVolatile (result, FALSE));
7570 freeAsmop (left, NULL, ic, TRUE);
7571 freeAsmop (right, NULL, ic, TRUE);
7572 freeAsmop (result, NULL, ic, TRUE);
7575 /*-----------------------------------------------------------------*/
7576 /* genSwap - generates code to swap nibbles or bytes */
7577 /*-----------------------------------------------------------------*/
7579 genSwap (iCode * ic)
7581 operand *left, *result;
7583 D(emitcode ("; genSwap",""));
7585 left = IC_LEFT (ic);
7586 result = IC_RESULT (ic);
7587 aopOp (left, ic, FALSE);
7588 aopOp (result, ic, FALSE);
7590 switch (AOP_SIZE (left))
7592 case 1: /* swap nibbles in byte */
7593 MOVA (aopGet (left, 0, FALSE, FALSE));
7594 emitcode ("swap", "a");
7595 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7597 case 2: /* swap bytes in word */
7598 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7600 MOVA (aopGet (left, 0, FALSE, FALSE));
7601 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7602 0, isOperandVolatile (result, FALSE));
7603 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7605 else if (operandsEqu (left, result))
7608 bool pushedB = FALSE, leftInB = FALSE;
7610 MOVA (aopGet (left, 0, FALSE, FALSE));
7611 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7614 emitcode ("mov", "b,a");
7618 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7619 0, isOperandVolatile (result, FALSE));
7620 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7627 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7628 0, isOperandVolatile (result, FALSE));
7629 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7630 1, isOperandVolatile (result, FALSE));
7634 wassertl(FALSE, "unsupported SWAP operand size");
7637 freeAsmop (left, NULL, ic, TRUE);
7638 freeAsmop (result, NULL, ic, TRUE);
7642 /*-----------------------------------------------------------------*/
7643 /* AccRol - rotate left accumulator by known count */
7644 /*-----------------------------------------------------------------*/
7646 AccRol (int shCount)
7648 shCount &= 0x0007; // shCount : 0..7
7655 emitcode ("rl", "a");
7658 emitcode ("rl", "a");
7659 emitcode ("rl", "a");
7662 emitcode ("swap", "a");
7663 emitcode ("rr", "a");
7666 emitcode ("swap", "a");
7669 emitcode ("swap", "a");
7670 emitcode ("rl", "a");
7673 emitcode ("rr", "a");
7674 emitcode ("rr", "a");
7677 emitcode ("rr", "a");
7682 /*-----------------------------------------------------------------*/
7683 /* AccLsh - left shift accumulator by known count */
7684 /*-----------------------------------------------------------------*/
7686 AccLsh (int shCount)
7691 emitcode ("add", "a,acc");
7692 else if (shCount == 2)
7694 emitcode ("add", "a,acc");
7695 emitcode ("add", "a,acc");
7699 /* rotate left accumulator */
7701 /* and kill the lower order bits */
7702 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7707 /*-----------------------------------------------------------------*/
7708 /* AccRsh - right shift accumulator by known count */
7709 /*-----------------------------------------------------------------*/
7711 AccRsh (int shCount)
7718 emitcode ("rrc", "a");
7722 /* rotate right accumulator */
7723 AccRol (8 - shCount);
7724 /* and kill the higher order bits */
7725 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7730 /*-----------------------------------------------------------------*/
7731 /* AccSRsh - signed right shift accumulator by known count */
7732 /*-----------------------------------------------------------------*/
7734 AccSRsh (int shCount)
7741 emitcode ("mov", "c,acc.7");
7742 emitcode ("rrc", "a");
7744 else if (shCount == 2)
7746 emitcode ("mov", "c,acc.7");
7747 emitcode ("rrc", "a");
7748 emitcode ("mov", "c,acc.7");
7749 emitcode ("rrc", "a");
7753 tlbl = newiTempLabel (NULL);
7754 /* rotate right accumulator */
7755 AccRol (8 - shCount);
7756 /* and kill the higher order bits */
7757 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7758 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7759 emitcode ("orl", "a,#0x%02x",
7760 (unsigned char) ~SRMask[shCount]);
7761 emitcode ("", "%05d$:", tlbl->key + 100);
7766 /*-----------------------------------------------------------------*/
7767 /* shiftR1Left2Result - shift right one byte from left to result */
7768 /*-----------------------------------------------------------------*/
7770 shiftR1Left2Result (operand * left, int offl,
7771 operand * result, int offr,
7772 int shCount, int sign)
7774 MOVA (aopGet (left, offl, FALSE, FALSE));
7775 /* shift right accumulator */
7780 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7783 /*-----------------------------------------------------------------*/
7784 /* shiftL1Left2Result - shift left one byte from left to result */
7785 /*-----------------------------------------------------------------*/
7787 shiftL1Left2Result (operand * left, int offl,
7788 operand * result, int offr, int shCount)
7791 l = aopGet (left, offl, FALSE, FALSE);
7793 /* shift left accumulator */
7795 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7798 /*-----------------------------------------------------------------*/
7799 /* movLeft2Result - move byte from left to result */
7800 /*-----------------------------------------------------------------*/
7802 movLeft2Result (operand * left, int offl,
7803 operand * result, int offr, int sign)
7806 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7808 l = aopGet (left, offl, FALSE, FALSE);
7810 if (*l == '@' && (IS_AOP_PREG (result)))
7812 emitcode ("mov", "a,%s", l);
7813 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7818 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7821 /* MSB sign in acc.7 ! */
7822 if (getDataSize (left) == offl + 1)
7825 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7832 /*-----------------------------------------------------------------*/
7833 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7834 /*-----------------------------------------------------------------*/
7838 emitcode ("rrc", "a");
7839 emitcode ("xch", "a,%s", x);
7840 emitcode ("rrc", "a");
7841 emitcode ("xch", "a,%s", x);
7844 /*-----------------------------------------------------------------*/
7845 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7846 /*-----------------------------------------------------------------*/
7850 emitcode ("xch", "a,%s", x);
7851 emitcode ("rlc", "a");
7852 emitcode ("xch", "a,%s", x);
7853 emitcode ("rlc", "a");
7856 /*-----------------------------------------------------------------*/
7857 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7858 /*-----------------------------------------------------------------*/
7862 emitcode ("xch", "a,%s", x);
7863 emitcode ("add", "a,acc");
7864 emitcode ("xch", "a,%s", x);
7865 emitcode ("rlc", "a");
7868 /*-----------------------------------------------------------------*/
7869 /* AccAXLsh - left shift a:x by known count (0..7) */
7870 /*-----------------------------------------------------------------*/
7872 AccAXLsh (char *x, int shCount)
7887 case 5: // AAAAABBB:CCCCCDDD
7889 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7891 emitcode ("anl", "a,#0x%02x",
7892 SLMask[shCount]); // BBB00000:CCCCCDDD
7894 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7896 AccRol (shCount); // DDDCCCCC:BBB00000
7898 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7900 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7902 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7904 emitcode ("anl", "a,#0x%02x",
7905 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7907 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7909 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7912 case 6: // AAAAAABB:CCCCCCDD
7913 emitcode ("anl", "a,#0x%02x",
7914 SRMask[shCount]); // 000000BB:CCCCCCDD
7915 emitcode ("mov", "c,acc.0"); // c = B
7916 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7918 AccAXRrl1 (x); // BCCCCCCD:D000000B
7919 AccAXRrl1 (x); // BBCCCCCC:DD000000
7921 emitcode("rrc","a");
7922 emitcode("xch","a,%s", x);
7923 emitcode("rrc","a");
7924 emitcode("mov","c,acc.0"); //<< get correct bit
7925 emitcode("xch","a,%s", x);
7927 emitcode("rrc","a");
7928 emitcode("xch","a,%s", x);
7929 emitcode("rrc","a");
7930 emitcode("xch","a,%s", x);
7933 case 7: // a:x <<= 7
7935 emitcode ("anl", "a,#0x%02x",
7936 SRMask[shCount]); // 0000000B:CCCCCCCD
7938 emitcode ("mov", "c,acc.0"); // c = B
7940 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7942 AccAXRrl1 (x); // BCCCCCCC:D0000000
7950 /*-----------------------------------------------------------------*/
7951 /* AccAXRsh - right shift a:x known count (0..7) */
7952 /*-----------------------------------------------------------------*/
7954 AccAXRsh (char *x, int shCount)
7962 AccAXRrl1 (x); // 0->a:x
7967 AccAXRrl1 (x); // 0->a:x
7970 AccAXRrl1 (x); // 0->a:x
7975 case 5: // AAAAABBB:CCCCCDDD = a:x
7977 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7979 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7981 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7983 emitcode ("anl", "a,#0x%02x",
7984 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7986 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7988 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7990 emitcode ("anl", "a,#0x%02x",
7991 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7993 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7995 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7997 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
8000 case 6: // AABBBBBB:CCDDDDDD
8002 emitcode ("mov", "c,acc.7");
8003 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8005 emitcode ("mov", "c,acc.7");
8006 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8008 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8010 emitcode ("anl", "a,#0x%02x",
8011 SRMask[shCount]); // 000000AA:BBBBBBCC
8014 case 7: // ABBBBBBB:CDDDDDDD
8016 emitcode ("mov", "c,acc.7"); // c = A
8018 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8020 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8022 emitcode ("anl", "a,#0x%02x",
8023 SRMask[shCount]); // 0000000A:BBBBBBBC
8031 /*-----------------------------------------------------------------*/
8032 /* AccAXRshS - right shift signed a:x known count (0..7) */
8033 /*-----------------------------------------------------------------*/
8035 AccAXRshS (char *x, int shCount)
8043 emitcode ("mov", "c,acc.7");
8044 AccAXRrl1 (x); // s->a:x
8048 emitcode ("mov", "c,acc.7");
8049 AccAXRrl1 (x); // s->a:x
8051 emitcode ("mov", "c,acc.7");
8052 AccAXRrl1 (x); // s->a:x
8057 case 5: // AAAAABBB:CCCCCDDD = a:x
8059 tlbl = newiTempLabel (NULL);
8060 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
8062 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
8064 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
8066 emitcode ("anl", "a,#0x%02x",
8067 SRMask[shCount]); // 000CCCCC:BBBAAAAA
8069 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
8071 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
8073 emitcode ("anl", "a,#0x%02x",
8074 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
8076 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
8078 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
8080 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
8082 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8083 emitcode ("orl", "a,#0x%02x",
8084 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
8086 emitcode ("", "%05d$:", tlbl->key + 100);
8087 break; // SSSSAAAA:BBBCCCCC
8089 case 6: // AABBBBBB:CCDDDDDD
8091 tlbl = newiTempLabel (NULL);
8092 emitcode ("mov", "c,acc.7");
8093 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
8095 emitcode ("mov", "c,acc.7");
8096 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
8098 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
8100 emitcode ("anl", "a,#0x%02x",
8101 SRMask[shCount]); // 000000AA:BBBBBBCC
8103 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8104 emitcode ("orl", "a,#0x%02x",
8105 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
8107 emitcode ("", "%05d$:", tlbl->key + 100);
8109 case 7: // ABBBBBBB:CDDDDDDD
8111 tlbl = newiTempLabel (NULL);
8112 emitcode ("mov", "c,acc.7"); // c = A
8114 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
8116 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
8118 emitcode ("anl", "a,#0x%02x",
8119 SRMask[shCount]); // 0000000A:BBBBBBBC
8121 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
8122 emitcode ("orl", "a,#0x%02x",
8123 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
8125 emitcode ("", "%05d$:", tlbl->key + 100);
8132 /*-----------------------------------------------------------------*/
8133 /* shiftL2Left2Result - shift left two bytes from left to result */
8134 /*-----------------------------------------------------------------*/
8136 shiftL2Left2Result (operand * left, int offl,
8137 operand * result, int offr, int shCount)
8140 bool pushedB = FALSE;
8143 if (sameRegs (AOP (result), AOP (left)) &&
8144 ((offl + MSB16) == offr))
8146 /* don't crash result[offr] */
8147 MOVA (aopGet (left, offl, FALSE, FALSE));
8148 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8149 x = aopGet (result, offr, FALSE, FALSE);
8151 else if (aopGetUsesAcc (result, offr))
8153 movLeft2Result (left, offl, result, offr, 0);
8156 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8157 MOVA (aopGet (result, offr, FALSE, FALSE));
8158 emitcode ("xch", "a,b");
8163 movLeft2Result (left, offl, result, offr, 0);
8164 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8165 x = aopGet (result, offr, FALSE, FALSE);
8167 /* ax << shCount (x = lsb(result)) */
8168 AccAXLsh (x, shCount);
8171 emitcode ("xch", "a,b");
8172 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8173 aopPut (result, "b", offr + MSB16, isOperandVolatile (result, FALSE));
8178 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8183 /*-----------------------------------------------------------------*/
8184 /* shiftR2Left2Result - shift right two bytes from left to result */
8185 /*-----------------------------------------------------------------*/
8187 shiftR2Left2Result (operand * left, int offl,
8188 operand * result, int offr,
8189 int shCount, int sign)
8192 bool pushedB = FALSE;
8195 if (sameRegs (AOP (result), AOP (left)) &&
8196 ((offl + MSB16) == offr))
8198 /* don't crash result[offr] */
8199 MOVA (aopGet (left, offl, FALSE, FALSE));
8200 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8201 x = aopGet (result, offr, FALSE, FALSE);
8203 else if (aopGetUsesAcc (result, offr))
8205 movLeft2Result (left, offl, result, offr, 0);
8208 emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8209 MOVA (aopGet (result, offr, FALSE, FALSE));
8210 emitcode ("xch", "a,b");
8215 movLeft2Result (left, offl, result, offr, 0);
8216 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8217 x = aopGet (result, offr, FALSE, FALSE);
8219 /* a:x >> shCount (x = lsb(result)) */
8221 AccAXRshS (x, shCount);
8223 AccAXRsh (x, shCount);
8226 aopPut (result, "b", offr, isOperandVolatile (result, FALSE));
8229 if (getDataSize (result) > 1)
8230 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8233 /*-----------------------------------------------------------------*/
8234 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8235 /*-----------------------------------------------------------------*/
8237 shiftLLeftOrResult (operand * left, int offl,
8238 operand * result, int offr, int shCount)
8240 MOVA (aopGet (left, offl, FALSE, FALSE));
8241 /* shift left accumulator */
8243 /* or with result */
8244 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8245 /* back to result */
8246 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8249 /*-----------------------------------------------------------------*/
8250 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8251 /*-----------------------------------------------------------------*/
8253 shiftRLeftOrResult (operand * left, int offl,
8254 operand * result, int offr, int shCount)
8256 MOVA (aopGet (left, offl, FALSE, FALSE));
8257 /* shift right accumulator */
8259 /* or with result */
8260 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8261 /* back to result */
8262 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8265 /*-----------------------------------------------------------------*/
8266 /* genlshOne - left shift a one byte quantity by known count */
8267 /*-----------------------------------------------------------------*/
8269 genlshOne (operand * result, operand * left, int shCount)
8271 D(emitcode ("; genlshOne",""));
8273 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8276 /*-----------------------------------------------------------------*/
8277 /* genlshTwo - left shift two bytes by known amount != 0 */
8278 /*-----------------------------------------------------------------*/
8280 genlshTwo (operand * result, operand * left, int shCount)
8284 D(emitcode ("; genlshTwo",""));
8286 size = getDataSize (result);
8288 /* if shCount >= 8 */
8296 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8298 movLeft2Result (left, LSB, result, MSB16, 0);
8300 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8303 /* 1 <= shCount <= 7 */
8307 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8309 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8313 /*-----------------------------------------------------------------*/
8314 /* shiftLLong - shift left one long from left to result */
8315 /* offl = LSB or MSB16 */
8316 /*-----------------------------------------------------------------*/
8318 shiftLLong (operand * left, operand * result, int offr)
8321 int size = AOP_SIZE (result);
8323 if (size >= LSB + offr)
8325 l = aopGet (left, LSB, FALSE, FALSE);
8327 emitcode ("add", "a,acc");
8328 if (sameRegs (AOP (left), AOP (result)) &&
8329 size >= MSB16 + offr && offr != LSB)
8330 emitcode ("xch", "a,%s",
8331 aopGet (left, LSB + offr, FALSE, FALSE));
8333 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8336 if (size >= MSB16 + offr)
8338 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8340 l = aopGet (left, MSB16, FALSE, FALSE);
8343 emitcode ("rlc", "a");
8344 if (sameRegs (AOP (left), AOP (result)) &&
8345 size >= MSB24 + offr && offr != LSB)
8346 emitcode ("xch", "a,%s",
8347 aopGet (left, MSB16 + offr, FALSE, FALSE));
8349 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8352 if (size >= MSB24 + offr)
8354 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8356 l = aopGet (left, MSB24, FALSE, FALSE);
8359 emitcode ("rlc", "a");
8360 if (sameRegs (AOP (left), AOP (result)) &&
8361 size >= MSB32 + offr && offr != LSB)
8362 emitcode ("xch", "a,%s",
8363 aopGet (left, MSB24 + offr, FALSE, FALSE));
8365 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8368 if (size > MSB32 + offr)
8370 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8372 l = aopGet (left, MSB32, FALSE, FALSE);
8375 emitcode ("rlc", "a");
8376 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8379 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8382 /*-----------------------------------------------------------------*/
8383 /* genlshFour - shift four byte by a known amount != 0 */
8384 /*-----------------------------------------------------------------*/
8386 genlshFour (operand * result, operand * left, int shCount)
8390 D(emitcode ("; genlshFour",""));
8392 size = AOP_SIZE (result);
8394 /* if shifting more that 3 bytes */
8399 /* lowest order of left goes to the highest
8400 order of the destination */
8401 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8403 movLeft2Result (left, LSB, result, MSB32, 0);
8404 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8405 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8406 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8410 /* more than two bytes */
8411 else if (shCount >= 16)
8413 /* lower order two bytes goes to higher order two bytes */
8415 /* if some more remaining */
8417 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8420 movLeft2Result (left, MSB16, result, MSB32, 0);
8421 movLeft2Result (left, LSB, result, MSB24, 0);
8423 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8424 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8428 /* if more than 1 byte */
8429 else if (shCount >= 8)
8431 /* lower order three bytes goes to higher order three bytes */
8436 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8438 movLeft2Result (left, LSB, result, MSB16, 0);
8444 movLeft2Result (left, MSB24, result, MSB32, 0);
8445 movLeft2Result (left, MSB16, result, MSB24, 0);
8446 movLeft2Result (left, LSB, result, MSB16, 0);
8447 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8449 else if (shCount == 1)
8450 shiftLLong (left, result, MSB16);
8453 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8454 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8455 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8456 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8461 /* 1 <= shCount <= 7 */
8462 else if (shCount <= 2)
8464 shiftLLong (left, result, LSB);
8466 shiftLLong (result, result, LSB);
8468 /* 3 <= shCount <= 7, optimize */
8471 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8472 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8473 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8477 /*-----------------------------------------------------------------*/
8478 /* genLeftShiftLiteral - left shifting by known count */
8479 /*-----------------------------------------------------------------*/
8481 genLeftShiftLiteral (operand * left,
8486 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8489 D(emitcode ("; genLeftShiftLiteral",""));
8491 freeAsmop (right, NULL, ic, TRUE);
8493 aopOp (left, ic, FALSE);
8494 aopOp (result, ic, FALSE);
8496 size = getSize (operandType (result));
8499 emitcode ("; shift left ", "result %d, left %d", size,
8503 /* I suppose that the left size >= result size */
8508 movLeft2Result (left, size, result, size, 0);
8512 else if (shCount >= (size * 8))
8514 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8520 genlshOne (result, left, shCount);
8524 genlshTwo (result, left, shCount);
8528 genlshFour (result, left, shCount);
8531 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8532 "*** ack! mystery literal shift!\n");
8536 freeAsmop (left, NULL, ic, TRUE);
8537 freeAsmop (result, NULL, ic, TRUE);
8540 /*-----------------------------------------------------------------*/
8541 /* genLeftShift - generates code for left shifting */
8542 /*-----------------------------------------------------------------*/
8544 genLeftShift (iCode * ic)
8546 operand *left, *right, *result;
8549 symbol *tlbl, *tlbl1;
8552 D(emitcode ("; genLeftShift",""));
8554 right = IC_RIGHT (ic);
8555 left = IC_LEFT (ic);
8556 result = IC_RESULT (ic);
8558 aopOp (right, ic, FALSE);
8560 /* if the shift count is known then do it
8561 as efficiently as possible */
8562 if (AOP_TYPE (right) == AOP_LIT)
8564 genLeftShiftLiteral (left, right, result, ic);
8568 /* shift count is unknown then we have to form
8569 a loop get the loop count in B : Note: we take
8570 only the lower order byte since shifting
8571 more that 32 bits make no sense anyway, ( the
8572 largest size of an object can be only 32 bits ) */
8575 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8576 emitcode ("inc", "b");
8577 freeAsmop (right, NULL, ic, TRUE);
8578 aopOp (left, ic, FALSE);
8579 aopOp (result, ic, FALSE);
8581 /* now move the left to the result if they are not the same */
8582 if (!sameRegs (AOP (left), AOP (result)) &&
8583 AOP_SIZE (result) > 1)
8586 size = AOP_SIZE (result);
8590 l = aopGet (left, offset, FALSE, TRUE);
8591 if (*l == '@' && (IS_AOP_PREG (result)))
8594 emitcode ("mov", "a,%s", l);
8595 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8598 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8603 tlbl = newiTempLabel (NULL);
8604 size = AOP_SIZE (result);
8606 tlbl1 = newiTempLabel (NULL);
8608 /* if it is only one byte then */
8611 symbol *tlbl1 = newiTempLabel (NULL);
8613 l = aopGet (left, 0, FALSE, FALSE);
8615 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8616 emitcode ("", "%05d$:", tlbl->key + 100);
8617 emitcode ("add", "a,acc");
8618 emitcode ("", "%05d$:", tlbl1->key + 100);
8619 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8621 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8625 reAdjustPreg (AOP (result));
8627 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8628 emitcode ("", "%05d$:", tlbl->key + 100);
8629 l = aopGet (result, offset, FALSE, FALSE);
8631 emitcode ("add", "a,acc");
8632 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8635 l = aopGet (result, offset, FALSE, FALSE);
8637 emitcode ("rlc", "a");
8638 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8640 reAdjustPreg (AOP (result));
8642 emitcode ("", "%05d$:", tlbl1->key + 100);
8643 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8646 freeAsmop (left, NULL, ic, TRUE);
8647 freeAsmop (result, NULL, ic, TRUE);
8650 /*-----------------------------------------------------------------*/
8651 /* genrshOne - right shift a one byte quantity by known count */
8652 /*-----------------------------------------------------------------*/
8654 genrshOne (operand * result, operand * left,
8655 int shCount, int sign)
8657 D(emitcode ("; genrshOne",""));
8659 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8662 /*-----------------------------------------------------------------*/
8663 /* genrshTwo - right shift two bytes by known amount != 0 */
8664 /*-----------------------------------------------------------------*/
8666 genrshTwo (operand * result, operand * left,
8667 int shCount, int sign)
8669 D(emitcode ("; genrshTwo",""));
8671 /* if shCount >= 8 */
8676 shiftR1Left2Result (left, MSB16, result, LSB,
8679 movLeft2Result (left, MSB16, result, LSB, sign);
8680 addSign (result, MSB16, sign);
8683 /* 1 <= shCount <= 7 */
8685 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8688 /*-----------------------------------------------------------------*/
8689 /* shiftRLong - shift right one long from left to result */
8690 /* offl = LSB or MSB16 */
8691 /*-----------------------------------------------------------------*/
8693 shiftRLong (operand * left, int offl,
8694 operand * result, int sign)
8696 int isSameRegs=sameRegs(AOP(left),AOP(result));
8698 if (isSameRegs && offl>1) {
8699 // we are in big trouble, but this shouldn't happen
8700 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8703 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8708 emitcode ("rlc", "a");
8709 emitcode ("subb", "a,acc");
8711 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8713 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8714 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8717 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8722 emitcode ("clr", "c");
8724 emitcode ("mov", "c,acc.7");
8727 emitcode ("rrc", "a");
8729 if (isSameRegs && offl==MSB16) {
8730 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8732 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8733 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8736 emitcode ("rrc", "a");
8737 if (isSameRegs && offl==1) {
8738 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8740 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8741 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8743 emitcode ("rrc", "a");
8744 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8748 MOVA (aopGet (left, LSB, FALSE, FALSE));
8749 emitcode ("rrc", "a");
8750 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8754 /*-----------------------------------------------------------------*/
8755 /* genrshFour - shift four byte by a known amount != 0 */
8756 /*-----------------------------------------------------------------*/
8758 genrshFour (operand * result, operand * left,
8759 int shCount, int sign)
8761 D(emitcode ("; genrshFour",""));
8763 /* if shifting more that 3 bytes */
8768 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8770 movLeft2Result (left, MSB32, result, LSB, sign);
8771 addSign (result, MSB16, sign);
8773 else if (shCount >= 16)
8777 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8780 movLeft2Result (left, MSB24, result, LSB, 0);
8781 movLeft2Result (left, MSB32, result, MSB16, sign);
8783 addSign (result, MSB24, sign);
8785 else if (shCount >= 8)
8789 shiftRLong (left, MSB16, result, sign);
8790 else if (shCount == 0)
8792 movLeft2Result (left, MSB16, result, LSB, 0);
8793 movLeft2Result (left, MSB24, result, MSB16, 0);
8794 movLeft2Result (left, MSB32, result, MSB24, sign);
8795 addSign (result, MSB32, sign);
8799 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8800 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8801 /* the last shift is signed */
8802 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8803 addSign (result, MSB32, sign);
8807 { /* 1 <= shCount <= 7 */
8810 shiftRLong (left, LSB, result, sign);
8812 shiftRLong (result, LSB, result, sign);
8816 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8817 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8818 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8823 /*-----------------------------------------------------------------*/
8824 /* genRightShiftLiteral - right shifting by known count */
8825 /*-----------------------------------------------------------------*/
8827 genRightShiftLiteral (operand * left,
8833 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8836 D(emitcode ("; genRightShiftLiteral",""));
8838 freeAsmop (right, NULL, ic, TRUE);
8840 aopOp (left, ic, FALSE);
8841 aopOp (result, ic, FALSE);
8844 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8848 size = getDataSize (left);
8849 /* test the LEFT size !!! */
8851 /* I suppose that the left size >= result size */
8854 size = getDataSize (result);
8856 movLeft2Result (left, size, result, size, 0);
8859 else if (shCount >= (size * 8))
8862 /* get sign in acc.7 */
8863 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8865 addSign (result, LSB, sign);
8872 genrshOne (result, left, shCount, sign);
8876 genrshTwo (result, left, shCount, sign);
8880 genrshFour (result, left, shCount, sign);
8886 freeAsmop (left, NULL, ic, TRUE);
8887 freeAsmop (result, NULL, ic, TRUE);
8890 /*-----------------------------------------------------------------*/
8891 /* genSignedRightShift - right shift of signed number */
8892 /*-----------------------------------------------------------------*/
8894 genSignedRightShift (iCode * ic)
8896 operand *right, *left, *result;
8899 symbol *tlbl, *tlbl1;
8902 D(emitcode ("; genSignedRightShift",""));
8904 /* we do it the hard way put the shift count in b
8905 and loop thru preserving the sign */
8907 right = IC_RIGHT (ic);
8908 left = IC_LEFT (ic);
8909 result = IC_RESULT (ic);
8911 aopOp (right, ic, FALSE);
8914 if (AOP_TYPE (right) == AOP_LIT)
8916 genRightShiftLiteral (left, right, result, ic, 1);
8919 /* shift count is unknown then we have to form
8920 a loop get the loop count in B : Note: we take
8921 only the lower order byte since shifting
8922 more that 32 bits make no sense anyway, ( the
8923 largest size of an object can be only 32 bits ) */
8926 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8927 emitcode ("inc", "b");
8928 freeAsmop (right, NULL, ic, TRUE);
8929 aopOp (left, ic, FALSE);
8930 aopOp (result, ic, FALSE);
8932 /* now move the left to the result if they are not the
8934 if (!sameRegs (AOP (left), AOP (result)) &&
8935 AOP_SIZE (result) > 1)
8938 size = AOP_SIZE (result);
8942 l = aopGet (left, offset, FALSE, TRUE);
8943 if (*l == '@' && IS_AOP_PREG (result))
8946 emitcode ("mov", "a,%s", l);
8947 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8950 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8955 /* mov the highest order bit to OVR */
8956 tlbl = newiTempLabel (NULL);
8957 tlbl1 = newiTempLabel (NULL);
8959 size = AOP_SIZE (result);
8961 MOVA (aopGet (left, offset, FALSE, FALSE));
8962 emitcode ("rlc", "a");
8963 emitcode ("mov", "ov,c");
8964 /* if it is only one byte then */
8967 l = aopGet (left, 0, FALSE, FALSE);
8969 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8970 emitcode ("", "%05d$:", tlbl->key + 100);
8971 emitcode ("mov", "c,ov");
8972 emitcode ("rrc", "a");
8973 emitcode ("", "%05d$:", tlbl1->key + 100);
8974 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8976 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8980 reAdjustPreg (AOP (result));
8981 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8982 emitcode ("", "%05d$:", tlbl->key + 100);
8983 emitcode ("mov", "c,ov");
8986 l = aopGet (result, offset, FALSE, FALSE);
8988 emitcode ("rrc", "a");
8989 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8991 reAdjustPreg (AOP (result));
8992 emitcode ("", "%05d$:", tlbl1->key + 100);
8993 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8997 freeAsmop (left, NULL, ic, TRUE);
8998 freeAsmop (result, NULL, ic, TRUE);
9001 /*-----------------------------------------------------------------*/
9002 /* genRightShift - generate code for right shifting */
9003 /*-----------------------------------------------------------------*/
9005 genRightShift (iCode * ic)
9007 operand *right, *left, *result;
9011 symbol *tlbl, *tlbl1;
9014 D(emitcode ("; genRightShift",""));
9016 /* if signed then we do it the hard way preserve the
9017 sign bit moving it inwards */
9018 letype = getSpec (operandType (IC_LEFT (ic)));
9020 if (!SPEC_USIGN (letype))
9022 genSignedRightShift (ic);
9026 /* signed & unsigned types are treated the same : i.e. the
9027 signed is NOT propagated inwards : quoting from the
9028 ANSI - standard : "for E1 >> E2, is equivalent to division
9029 by 2**E2 if unsigned or if it has a non-negative value,
9030 otherwise the result is implementation defined ", MY definition
9031 is that the sign does not get propagated */
9033 right = IC_RIGHT (ic);
9034 left = IC_LEFT (ic);
9035 result = IC_RESULT (ic);
9037 aopOp (right, ic, FALSE);
9039 /* if the shift count is known then do it
9040 as efficiently as possible */
9041 if (AOP_TYPE (right) == AOP_LIT)
9043 genRightShiftLiteral (left, right, result, ic, 0);
9047 /* shift count is unknown then we have to form
9048 a loop get the loop count in B : Note: we take
9049 only the lower order byte since shifting
9050 more that 32 bits make no sense anyway, ( the
9051 largest size of an object can be only 32 bits ) */
9054 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
9055 emitcode ("inc", "b");
9056 freeAsmop (right, NULL, ic, TRUE);
9057 aopOp (left, ic, FALSE);
9058 aopOp (result, ic, FALSE);
9060 /* now move the left to the result if they are not the
9062 if (!sameRegs (AOP (left), AOP (result)) &&
9063 AOP_SIZE (result) > 1)
9066 size = AOP_SIZE (result);
9070 l = aopGet (left, offset, FALSE, TRUE);
9071 if (*l == '@' && IS_AOP_PREG (result))
9074 emitcode ("mov", "a,%s", l);
9075 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9078 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
9083 tlbl = newiTempLabel (NULL);
9084 tlbl1 = newiTempLabel (NULL);
9085 size = AOP_SIZE (result);
9088 /* if it is only one byte then */
9091 l = aopGet (left, 0, FALSE, FALSE);
9093 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9094 emitcode ("", "%05d$:", tlbl->key + 100);
9096 emitcode ("rrc", "a");
9097 emitcode ("", "%05d$:", tlbl1->key + 100);
9098 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9100 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
9104 reAdjustPreg (AOP (result));
9105 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
9106 emitcode ("", "%05d$:", tlbl->key + 100);
9110 l = aopGet (result, offset, FALSE, FALSE);
9112 emitcode ("rrc", "a");
9113 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
9115 reAdjustPreg (AOP (result));
9117 emitcode ("", "%05d$:", tlbl1->key + 100);
9118 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
9122 freeAsmop (left, NULL, ic, TRUE);
9123 freeAsmop (result, NULL, ic, TRUE);
9126 /*-----------------------------------------------------------------*/
9127 /* emitPtrByteGet - emits code to get a byte into A through a */
9128 /* pointer register (R0, R1, or DPTR). The */
9129 /* original value of A can be preserved in B. */
9130 /*-----------------------------------------------------------------*/
9132 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9139 emitcode ("mov", "b,a");
9140 emitcode ("mov", "a,@%s", rname);
9145 emitcode ("mov", "b,a");
9146 emitcode ("movx", "a,@%s", rname);
9151 emitcode ("mov", "b,a");
9152 emitcode ("movx", "a,@dptr");
9157 emitcode ("mov", "b,a");
9158 emitcode ("clr", "a");
9159 emitcode ("movc", "a,@a+dptr");
9165 emitcode ("push", "b");
9166 emitcode ("push", "acc");
9168 emitcode ("lcall", "__gptrget");
9170 emitcode ("pop", "b");
9175 /*-----------------------------------------------------------------*/
9176 /* emitPtrByteSet - emits code to set a byte from src through a */
9177 /* pointer register (R0, R1, or DPTR). */
9178 /*-----------------------------------------------------------------*/
9180 emitPtrByteSet (char *rname, int p_type, char *src)
9189 emitcode ("mov", "@%s,a", rname);
9192 emitcode ("mov", "@%s,%s", rname, src);
9197 emitcode ("movx", "@%s,a", rname);
9202 emitcode ("movx", "@dptr,a");
9207 emitcode ("lcall", "__gptrput");
9212 /*-----------------------------------------------------------------*/
9213 /* genUnpackBits - generates code for unpacking bits */
9214 /*-----------------------------------------------------------------*/
9216 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9218 int offset = 0; /* result byte offset */
9219 int rsize; /* result size */
9220 int rlen = 0; /* remaining bitfield length */
9221 sym_link *etype; /* bitfield type information */
9222 int blen; /* bitfield length */
9223 int bstr; /* bitfield starting bit within byte */
9226 D(emitcode ("; genUnpackBits",""));
9228 etype = getSpec (operandType (result));
9229 rsize = getSize (operandType (result));
9230 blen = SPEC_BLEN (etype);
9231 bstr = SPEC_BSTR (etype);
9233 if (ifx && blen <= 8)
9235 emitPtrByteGet (rname, ptype, FALSE);
9238 SNPRINTF (buffer, sizeof(buffer),
9240 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9245 emitcode ("anl", "a,#0x%02x",
9246 (((unsigned char) -1) >> (8 - blen)) << bstr);
9247 genIfxJump (ifx, "a", NULL, NULL, NULL);
9253 /* If the bitfield length is less than a byte */
9256 emitPtrByteGet (rname, ptype, FALSE);
9258 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9259 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9263 /* Bit field did not fit in a byte. Copy all
9264 but the partial byte at the end. */
9265 for (rlen=blen;rlen>=8;rlen-=8)
9267 emitPtrByteGet (rname, ptype, FALSE);
9268 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9270 emitcode ("inc", "%s", rname);
9273 /* Handle the partial byte at the end */
9276 emitPtrByteGet (rname, ptype, FALSE);
9277 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9278 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9286 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
9291 /*-----------------------------------------------------------------*/
9292 /* genDataPointerGet - generates code when ptr offset is known */
9293 /*-----------------------------------------------------------------*/
9295 genDataPointerGet (operand * left,
9301 int size, offset = 0;
9303 D(emitcode ("; genDataPointerGet",""));
9305 aopOp (result, ic, TRUE);
9307 /* get the string representation of the name */
9308 l = aopGet (left, 0, FALSE, TRUE);
9309 size = AOP_SIZE (result);
9313 sprintf (buffer, "(%s + %d)", l + 1, offset);
9315 sprintf (buffer, "%s", l + 1);
9316 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9319 freeAsmop (left, NULL, ic, TRUE);
9320 freeAsmop (result, NULL, ic, TRUE);
9323 /*-----------------------------------------------------------------*/
9324 /* genNearPointerGet - emitcode for near pointer fetch */
9325 /*-----------------------------------------------------------------*/
9327 genNearPointerGet (operand * left,
9336 sym_link *rtype, *retype;
9337 sym_link *ltype = operandType (left);
9340 D(emitcode ("; genNearPointerGet",""));
9342 rtype = operandType (result);
9343 retype = getSpec (rtype);
9345 aopOp (left, ic, FALSE);
9347 /* if left is rematerialisable and
9348 result is not bitfield variable type and
9349 the left is pointer to data space i.e
9350 lower 128 bytes of space */
9351 if (AOP_TYPE (left) == AOP_IMMD &&
9352 !IS_BITFIELD (retype) &&
9353 DCL_TYPE (ltype) == POINTER)
9355 genDataPointerGet (left, result, ic);
9359 /* if the value is already in a pointer register
9360 then don't need anything more */
9361 if (!AOP_INPREG (AOP (left)))
9363 if (IS_AOP_PREG (left))
9365 // Aha, it is a pointer, just in disguise.
9366 rname = aopGet (left, 0, FALSE, FALSE);
9369 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9370 __FILE__, __LINE__);
9375 emitcode ("mov", "a%s,%s", rname + 1, rname);
9376 rname++; // skip the '@'.
9381 /* otherwise get a free pointer register */
9383 preg = getFreePtr (ic, &aop, FALSE);
9384 emitcode ("mov", "%s,%s",
9386 aopGet (left, 0, FALSE, TRUE));
9391 rname = aopGet (left, 0, FALSE, FALSE);
9393 //aopOp (result, ic, FALSE);
9394 aopOp (result, ic, result?TRUE:FALSE);
9396 /* if bitfield then unpack the bits */
9397 if (IS_BITFIELD (retype))
9398 genUnpackBits (result, rname, POINTER, ifx);
9401 /* we have can just get the values */
9402 int size = AOP_SIZE (result);
9407 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9410 emitcode ("mov", "a,@%s", rname);
9412 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9416 sprintf (buffer, "@%s", rname);
9417 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9421 emitcode ("inc", "%s", rname);
9425 /* now some housekeeping stuff */
9426 if (aop) /* we had to allocate for this iCode */
9428 if (pi) { /* post increment present */
9429 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9431 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9435 /* we did not allocate which means left
9436 already in a pointer register, then
9437 if size > 0 && this could be used again
9438 we have to point it back to where it
9440 if ((AOP_SIZE (result) > 1 &&
9441 !OP_SYMBOL (left)->remat &&
9442 (OP_SYMBOL (left)->liveTo > ic->seq ||
9446 int size = AOP_SIZE (result) - 1;
9448 emitcode ("dec", "%s", rname);
9452 if (ifx && !ifx->generated)
9454 genIfxJump (ifx, "a", left, NULL, result);
9458 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9459 freeAsmop (left, NULL, ic, TRUE);
9460 if (pi) pi->generated = 1;
9463 /*-----------------------------------------------------------------*/
9464 /* genPagedPointerGet - emitcode for paged pointer fetch */
9465 /*-----------------------------------------------------------------*/
9467 genPagedPointerGet (operand * left,
9476 sym_link *rtype, *retype;
9478 D(emitcode ("; genPagedPointerGet",""));
9480 rtype = operandType (result);
9481 retype = getSpec (rtype);
9483 aopOp (left, ic, FALSE);
9485 /* if the value is already in a pointer register
9486 then don't need anything more */
9487 if (!AOP_INPREG (AOP (left)))
9489 /* otherwise get a free pointer register */
9491 preg = getFreePtr (ic, &aop, FALSE);
9492 emitcode ("mov", "%s,%s",
9494 aopGet (left, 0, FALSE, TRUE));
9498 rname = aopGet (left, 0, FALSE, FALSE);
9500 aopOp (result, ic, FALSE);
9502 /* if bitfield then unpack the bits */
9503 if (IS_BITFIELD (retype))
9504 genUnpackBits (result, rname, PPOINTER, ifx);
9507 /* we have can just get the values */
9508 int size = AOP_SIZE (result);
9514 emitcode ("movx", "a,@%s", rname);
9516 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9521 emitcode ("inc", "%s", rname);
9525 /* now some housekeeping stuff */
9526 if (aop) /* we had to allocate for this iCode */
9528 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9529 freeAsmop (NULL, aop, ic, TRUE);
9533 /* we did not allocate which means left
9534 already in a pointer register, then
9535 if size > 0 && this could be used again
9536 we have to point it back to where it
9538 if ((AOP_SIZE (result) > 1 &&
9539 !OP_SYMBOL (left)->remat &&
9540 (OP_SYMBOL (left)->liveTo > ic->seq ||
9544 int size = AOP_SIZE (result) - 1;
9546 emitcode ("dec", "%s", rname);
9550 if (ifx && !ifx->generated)
9552 genIfxJump (ifx, "a", left, NULL, result);
9556 freeAsmop (left, NULL, ic, TRUE);
9557 freeAsmop (result, NULL, ic, TRUE);
9558 if (pi) pi->generated = 1;
9562 /*--------------------------------------------------------------------*/
9563 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9564 /*--------------------------------------------------------------------*/
9566 loadDptrFromOperand (operand *op, bool loadBToo)
9568 if (AOP_TYPE (op) != AOP_STR)
9570 /* if this is rematerializable */
9571 if (AOP_TYPE (op) == AOP_IMMD)
9573 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9576 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9577 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9580 wassertl(FALSE, "need pointerCode");
9581 emitcode ("", "; mov b,???");
9582 /* genPointerGet and genPointerSet originally did different
9583 ** things for this case. Both seem wrong.
9584 ** from genPointerGet:
9585 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9586 ** from genPointerSet:
9587 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9592 else if (AOP_TYPE (op) == AOP_DPTR)
9596 MOVA (aopGet (op, 0, FALSE, FALSE));
9597 emitcode ("push", "acc");
9598 MOVA (aopGet (op, 1, FALSE, FALSE));
9599 emitcode ("push", "acc");
9600 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9601 emitcode ("pop", "dph");
9602 emitcode ("pop", "dpl");
9606 MOVA (aopGet (op, 0, FALSE, FALSE));
9607 emitcode ("push", "acc");
9608 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9609 emitcode ("pop", "dpl");
9613 { /* we need to get it byte by byte */
9614 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9615 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9617 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9622 /*-----------------------------------------------------------------*/
9623 /* genFarPointerGet - gget value from far space */
9624 /*-----------------------------------------------------------------*/
9626 genFarPointerGet (operand * left,
9627 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9630 sym_link *retype = getSpec (operandType (result));
9632 D(emitcode ("; genFarPointerGet",""));
9634 aopOp (left, ic, FALSE);
9635 loadDptrFromOperand (left, FALSE);
9637 /* so dptr now contains the address */
9638 aopOp (result, ic, FALSE);
9640 /* if bit then unpack */
9641 if (IS_BITFIELD (retype))
9642 genUnpackBits (result, "dptr", FPOINTER, ifx);
9645 size = AOP_SIZE (result);
9650 emitcode ("movx", "a,@dptr");
9652 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9654 emitcode ("inc", "dptr");
9658 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9660 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9661 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9665 if (ifx && !ifx->generated)
9667 genIfxJump (ifx, "a", left, NULL, result);
9670 freeAsmop (left, NULL, ic, TRUE);
9671 freeAsmop (result, NULL, ic, TRUE);
9674 /*-----------------------------------------------------------------*/
9675 /* genCodePointerGet - gget value from code space */
9676 /*-----------------------------------------------------------------*/
9678 genCodePointerGet (operand * left,
9679 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9682 sym_link *retype = getSpec (operandType (result));
9684 D(emitcode ("; genCodePointerGet",""));
9686 aopOp (left, ic, FALSE);
9687 loadDptrFromOperand (left, FALSE);
9689 /* so dptr now contains the address */
9690 aopOp (result, ic, FALSE);
9692 /* if bit then unpack */
9693 if (IS_BITFIELD (retype))
9694 genUnpackBits (result, "dptr", CPOINTER, ifx);
9697 size = AOP_SIZE (result);
9704 emitcode ("clr", "a");
9705 emitcode ("movc", "a,@a+dptr");
9707 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9708 emitcode ("inc", "dptr");
9712 emitcode ("mov", "a,#0x%02x", offset);
9713 emitcode ("movc", "a,@a+dptr");
9715 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9720 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9722 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9723 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9727 if (ifx && !ifx->generated)
9729 genIfxJump (ifx, "a", left, NULL, result);
9732 freeAsmop (left, NULL, ic, TRUE);
9733 freeAsmop (result, NULL, ic, TRUE);
9736 /*-----------------------------------------------------------------*/
9737 /* genGenPointerGet - gget value from generic pointer space */
9738 /*-----------------------------------------------------------------*/
9740 genGenPointerGet (operand * left,
9741 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9744 sym_link *retype = getSpec (operandType (result));
9746 D(emitcode ("; genGenPointerGet",""));
9748 aopOp (left, ic, FALSE);
9749 loadDptrFromOperand (left, TRUE);
9751 /* so dptr know contains the address */
9752 aopOp (result, ic, FALSE);
9754 /* if bit then unpack */
9755 if (IS_BITFIELD (retype))
9756 genUnpackBits (result, "dptr", GPOINTER, ifx);
9759 size = AOP_SIZE (result);
9764 emitcode ("lcall", "__gptrget");
9766 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9768 emitcode ("inc", "dptr");
9772 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9774 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9775 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9779 if (ifx && !ifx->generated)
9781 genIfxJump (ifx, "a", left, NULL, result);
9785 freeAsmop (left, NULL, ic, TRUE);
9786 freeAsmop (result, NULL, ic, TRUE);
9789 /*-----------------------------------------------------------------*/
9790 /* genPointerGet - generate code for pointer get */
9791 /*-----------------------------------------------------------------*/
9793 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9795 operand *left, *result;
9796 sym_link *type, *etype;
9799 D(emitcode ("; genPointerGet",""));
9801 left = IC_LEFT (ic);
9802 result = IC_RESULT (ic);
9804 if (getSize (operandType (result))>1)
9807 /* depending on the type of pointer we need to
9808 move it to the correct pointer register */
9809 type = operandType (left);
9810 etype = getSpec (type);
9811 /* if left is of type of pointer then it is simple */
9812 if (IS_PTR (type) && !IS_FUNC (type->next))
9813 p_type = DCL_TYPE (type);
9816 /* we have to go by the storage class */
9817 p_type = PTR_TYPE (SPEC_OCLS (etype));
9820 /* special case when cast remat */
9821 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9822 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9823 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9824 type = operandType (left);
9825 p_type = DCL_TYPE (type);
9827 /* now that we have the pointer type we assign
9828 the pointer values */
9834 genNearPointerGet (left, result, ic, pi, ifx);
9838 genPagedPointerGet (left, result, ic, pi, ifx);
9842 genFarPointerGet (left, result, ic, pi, ifx);
9846 genCodePointerGet (left, result, ic, pi, ifx);
9850 genGenPointerGet (left, result, ic, pi, ifx);
9858 /*-----------------------------------------------------------------*/
9859 /* genPackBits - generates code for packed bit storage */
9860 /*-----------------------------------------------------------------*/
9862 genPackBits (sym_link * etype,
9864 char *rname, int p_type)
9866 int offset = 0; /* source byte offset */
9867 int rlen = 0; /* remaining bitfield length */
9868 int blen; /* bitfield length */
9869 int bstr; /* bitfield starting bit within byte */
9870 int litval; /* source literal value (if AOP_LIT) */
9871 unsigned char mask; /* bitmask within current byte */
9873 D(emitcode ("; genPackBits",""));
9875 blen = SPEC_BLEN (etype);
9876 bstr = SPEC_BSTR (etype);
9878 /* If the bitfield length is less than a byte */
9881 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9882 (unsigned char) (0xFF >> (8 - bstr)));
9884 if (AOP_TYPE (right) == AOP_LIT)
9886 /* Case with a bitfield length <8 and literal source
9888 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9890 litval &= (~mask) & 0xff;
9891 emitPtrByteGet (rname, p_type, FALSE);
9892 if ((mask|litval)!=0xff)
9893 emitcode ("anl","a,#0x%02x", mask);
9895 emitcode ("orl","a,#0x%02x", litval);
9899 if ((blen==1) && (p_type!=GPOINTER))
9901 /* Case with a bitfield length == 1 and no generic pointer
9903 if (AOP_TYPE (right) == AOP_CRY)
9904 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9907 MOVA (aopGet (right, 0, FALSE, FALSE));
9908 emitcode ("rrc","a");
9910 emitPtrByteGet (rname, p_type, FALSE);
9911 emitcode ("mov","acc.%d,c",bstr);
9916 /* Case with a bitfield length < 8 and arbitrary source
9918 MOVA (aopGet (right, 0, FALSE, FALSE));
9919 /* shift and mask source value */
9921 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9924 /* transfer A to B and get next byte */
9925 emitPtrByteGet (rname, p_type, TRUE);
9927 emitcode ("anl", "a,#0x%02x", mask);
9928 emitcode ("orl", "a,b");
9929 if (p_type == GPOINTER)
9930 emitcode ("pop", "b");
9936 emitPtrByteSet (rname, p_type, "a");
9940 /* Bit length is greater than 7 bits. In this case, copy */
9941 /* all except the partial byte at the end */
9942 for (rlen=blen;rlen>=8;rlen-=8)
9944 emitPtrByteSet (rname, p_type,
9945 aopGet (right, offset++, FALSE, TRUE) );
9947 emitcode ("inc", "%s", rname);
9950 /* If there was a partial byte at the end */
9953 mask = (((unsigned char) -1 << rlen) & 0xff);
9955 if (AOP_TYPE (right) == AOP_LIT)
9957 /* Case with partial byte and literal source
9959 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9960 litval >>= (blen-rlen);
9961 litval &= (~mask) & 0xff;
9962 emitPtrByteGet (rname, p_type, FALSE);
9963 if ((mask|litval)!=0xff)
9964 emitcode ("anl","a,#0x%02x", mask);
9966 emitcode ("orl","a,#0x%02x", litval);
9971 /* Case with partial byte and arbitrary source
9973 MOVA (aopGet (right, offset++, FALSE, FALSE));
9974 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9977 /* transfer A to B and get next byte */
9978 emitPtrByteGet (rname, p_type, TRUE);
9980 emitcode ("anl", "a,#0x%02x", mask);
9981 emitcode ("orl", "a,b");
9982 if (p_type == GPOINTER)
9983 emitcode ("pop", "b");
9987 emitPtrByteSet (rname, p_type, "a");
9993 /*-----------------------------------------------------------------*/
9994 /* genDataPointerSet - remat pointer to data space */
9995 /*-----------------------------------------------------------------*/
9997 genDataPointerSet (operand * right,
10001 int size, offset = 0;
10002 char *l, buffer[256];
10004 D(emitcode ("; genDataPointerSet",""));
10006 aopOp (right, ic, FALSE);
10008 l = aopGet (result, 0, FALSE, TRUE);
10009 size = AOP_SIZE (right);
10013 sprintf (buffer, "(%s + %d)", l + 1, offset);
10015 sprintf (buffer, "%s", l + 1);
10016 emitcode ("mov", "%s,%s", buffer,
10017 aopGet (right, offset++, FALSE, FALSE));
10020 freeAsmop (right, NULL, ic, TRUE);
10021 freeAsmop (result, NULL, ic, TRUE);
10024 /*-----------------------------------------------------------------*/
10025 /* genNearPointerSet - emitcode for near pointer put */
10026 /*-----------------------------------------------------------------*/
10028 genNearPointerSet (operand * right,
10036 sym_link *retype, *letype;
10037 sym_link *ptype = operandType (result);
10039 D(emitcode ("; genNearPointerSet",""));
10041 retype = getSpec (operandType (right));
10042 letype = getSpec (ptype);
10043 aopOp (result, ic, FALSE);
10045 /* if the result is rematerializable &
10046 in data space & not a bit variable */
10047 if (AOP_TYPE (result) == AOP_IMMD &&
10048 DCL_TYPE (ptype) == POINTER &&
10049 !IS_BITVAR (retype) &&
10050 !IS_BITVAR (letype))
10052 genDataPointerSet (right, result, ic);
10056 /* if the value is already in a pointer register
10057 then don't need anything more */
10058 if (!AOP_INPREG (AOP (result)))
10061 //AOP_TYPE (result) == AOP_STK
10062 IS_AOP_PREG(result)
10065 // Aha, it is a pointer, just in disguise.
10066 rname = aopGet (result, 0, FALSE, FALSE);
10069 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
10070 __FILE__, __LINE__);
10075 emitcode ("mov", "a%s,%s", rname + 1, rname);
10076 rname++; // skip the '@'.
10081 /* otherwise get a free pointer register */
10082 aop = newAsmop (0);
10083 preg = getFreePtr (ic, &aop, FALSE);
10084 emitcode ("mov", "%s,%s",
10086 aopGet (result, 0, FALSE, TRUE));
10087 rname = preg->name;
10092 rname = aopGet (result, 0, FALSE, FALSE);
10095 aopOp (right, ic, FALSE);
10097 /* if bitfield then unpack the bits */
10098 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10099 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
10102 /* we have can just get the values */
10103 int size = AOP_SIZE (right);
10108 l = aopGet (right, offset, FALSE, TRUE);
10112 emitcode ("mov", "@%s,a", rname);
10115 emitcode ("mov", "@%s,%s", rname, l);
10117 emitcode ("inc", "%s", rname);
10122 /* now some housekeeping stuff */
10123 if (aop) /* we had to allocate for this iCode */
10126 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10127 freeAsmop (NULL, aop, ic, TRUE);
10131 /* we did not allocate which means left
10132 already in a pointer register, then
10133 if size > 0 && this could be used again
10134 we have to point it back to where it
10136 if ((AOP_SIZE (right) > 1 &&
10137 !OP_SYMBOL (result)->remat &&
10138 (OP_SYMBOL (result)->liveTo > ic->seq ||
10142 int size = AOP_SIZE (right) - 1;
10144 emitcode ("dec", "%s", rname);
10149 if (pi) pi->generated = 1;
10150 freeAsmop (result, NULL, ic, TRUE);
10151 freeAsmop (right, NULL, ic, TRUE);
10154 /*-----------------------------------------------------------------*/
10155 /* genPagedPointerSet - emitcode for Paged pointer put */
10156 /*-----------------------------------------------------------------*/
10158 genPagedPointerSet (operand * right,
10166 sym_link *retype, *letype;
10168 D(emitcode ("; genPagedPointerSet",""));
10170 retype = getSpec (operandType (right));
10171 letype = getSpec (operandType (result));
10173 aopOp (result, ic, FALSE);
10175 /* if the value is already in a pointer register
10176 then don't need anything more */
10177 if (!AOP_INPREG (AOP (result)))
10179 /* otherwise get a free pointer register */
10180 aop = newAsmop (0);
10181 preg = getFreePtr (ic, &aop, FALSE);
10182 emitcode ("mov", "%s,%s",
10184 aopGet (result, 0, FALSE, TRUE));
10185 rname = preg->name;
10188 rname = aopGet (result, 0, FALSE, FALSE);
10190 aopOp (right, ic, FALSE);
10192 /* if bitfield then unpack the bits */
10193 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10194 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10197 /* we have can just get the values */
10198 int size = AOP_SIZE (right);
10203 l = aopGet (right, offset, FALSE, TRUE);
10206 emitcode ("movx", "@%s,a", rname);
10209 emitcode ("inc", "%s", rname);
10215 /* now some housekeeping stuff */
10216 if (aop) /* we had to allocate for this iCode */
10219 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10220 freeAsmop (NULL, aop, ic, TRUE);
10224 /* we did not allocate which means left
10225 already in a pointer register, then
10226 if size > 0 && this could be used again
10227 we have to point it back to where it
10229 if (AOP_SIZE (right) > 1 &&
10230 !OP_SYMBOL (result)->remat &&
10231 (OP_SYMBOL (result)->liveTo > ic->seq ||
10234 int size = AOP_SIZE (right) - 1;
10236 emitcode ("dec", "%s", rname);
10241 if (pi) pi->generated = 1;
10242 freeAsmop (result, NULL, ic, TRUE);
10243 freeAsmop (right, NULL, ic, TRUE);
10248 /*-----------------------------------------------------------------*/
10249 /* genFarPointerSet - set value from far space */
10250 /*-----------------------------------------------------------------*/
10252 genFarPointerSet (operand * right,
10253 operand * result, iCode * ic, iCode * pi)
10256 sym_link *retype = getSpec (operandType (right));
10257 sym_link *letype = getSpec (operandType (result));
10259 D(emitcode ("; genFarPointerSet",""));
10261 aopOp (result, ic, FALSE);
10262 loadDptrFromOperand (result, FALSE);
10264 /* so dptr know contains the address */
10265 aopOp (right, ic, FALSE);
10267 /* if bit then unpack */
10268 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10269 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10272 size = AOP_SIZE (right);
10277 char *l = aopGet (right, offset++, FALSE, FALSE);
10279 emitcode ("movx", "@dptr,a");
10281 emitcode ("inc", "dptr");
10284 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10285 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10286 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10289 freeAsmop (result, NULL, ic, TRUE);
10290 freeAsmop (right, NULL, ic, TRUE);
10293 /*-----------------------------------------------------------------*/
10294 /* genGenPointerSet - set value from generic pointer space */
10295 /*-----------------------------------------------------------------*/
10297 genGenPointerSet (operand * right,
10298 operand * result, iCode * ic, iCode * pi)
10301 sym_link *retype = getSpec (operandType (right));
10302 sym_link *letype = getSpec (operandType (result));
10304 D(emitcode ("; genGenPointerSet",""));
10306 aopOp (result, ic, FALSE);
10307 loadDptrFromOperand (result, TRUE);
10309 /* so dptr know contains the address */
10310 aopOp (right, ic, FALSE);
10312 /* if bit then unpack */
10313 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10314 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10317 size = AOP_SIZE (right);
10322 char *l = aopGet (right, offset++, FALSE, FALSE);
10324 emitcode ("lcall", "__gptrput");
10326 emitcode ("inc", "dptr");
10330 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10331 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10332 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10335 freeAsmop (result, NULL, ic, TRUE);
10336 freeAsmop (right, NULL, ic, TRUE);
10339 /*-----------------------------------------------------------------*/
10340 /* genPointerSet - stores the value into a pointer location */
10341 /*-----------------------------------------------------------------*/
10343 genPointerSet (iCode * ic, iCode *pi)
10345 operand *right, *result;
10346 sym_link *type, *etype;
10349 D(emitcode ("; genPointerSet",""));
10351 right = IC_RIGHT (ic);
10352 result = IC_RESULT (ic);
10354 /* depending on the type of pointer we need to
10355 move it to the correct pointer register */
10356 type = operandType (result);
10357 etype = getSpec (type);
10358 /* if left is of type of pointer then it is simple */
10359 if (IS_PTR (type) && !IS_FUNC (type->next))
10361 p_type = DCL_TYPE (type);
10365 /* we have to go by the storage class */
10366 p_type = PTR_TYPE (SPEC_OCLS (etype));
10369 /* special case when cast remat */
10370 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10371 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10372 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10373 type = operandType (result);
10374 p_type = DCL_TYPE (type);
10376 /* now that we have the pointer type we assign
10377 the pointer values */
10383 genNearPointerSet (right, result, ic, pi);
10387 genPagedPointerSet (right, result, ic, pi);
10391 genFarPointerSet (right, result, ic, pi);
10395 genGenPointerSet (right, result, ic, pi);
10399 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10400 "genPointerSet: illegal pointer type");
10405 /*-----------------------------------------------------------------*/
10406 /* genIfx - generate code for Ifx statement */
10407 /*-----------------------------------------------------------------*/
10409 genIfx (iCode * ic, iCode * popIc)
10411 operand *cond = IC_COND (ic);
10415 D(emitcode ("; genIfx",""));
10417 aopOp (cond, ic, FALSE);
10419 /* get the value into acc */
10420 if (AOP_TYPE (cond) != AOP_CRY)
10425 if (AOP(cond)->aopu.aop_dir)
10426 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10428 /* the result is now in the accumulator or a directly addressable bit */
10429 freeAsmop (cond, NULL, ic, TRUE);
10431 /* if there was something to be popped then do it */
10435 /* if the condition is a bit variable */
10437 genIfxJump(ic, dup, NULL, NULL, NULL);
10438 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10439 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10440 else if (isbit && !IS_ITEMP (cond))
10441 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10443 genIfxJump (ic, "a", NULL, NULL, NULL);
10448 /*-----------------------------------------------------------------*/
10449 /* genAddrOf - generates code for address of */
10450 /*-----------------------------------------------------------------*/
10452 genAddrOf (iCode * ic)
10454 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10457 D(emitcode ("; genAddrOf",""));
10459 aopOp (IC_RESULT (ic), ic, FALSE);
10461 /* if the operand is on the stack then we
10462 need to get the stack offset of this
10466 /* if it has an offset then we need to compute
10470 emitcode ("mov", "a,%s", SYM_BP (sym));
10471 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10472 ((char) (sym->stack - _G.nRegsSaved)) :
10473 ((char) sym->stack)) & 0xff);
10474 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10478 /* we can just move _bp */
10479 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10481 /* fill the result with zero */
10482 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10487 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10493 /* object not on stack then we need the name */
10494 size = AOP_SIZE (IC_RESULT (ic));
10499 char s[SDCC_NAME_MAX];
10501 sprintf (s, "#(%s >> %d)",
10505 sprintf (s, "#%s", sym->rname);
10506 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10510 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10514 /*-----------------------------------------------------------------*/
10515 /* genFarFarAssign - assignment when both are in far space */
10516 /*-----------------------------------------------------------------*/
10518 genFarFarAssign (operand * result, operand * right, iCode * ic)
10520 int size = AOP_SIZE (right);
10524 D(emitcode ("; genFarFarAssign",""));
10526 /* first push the right side on to the stack */
10529 l = aopGet (right, offset++, FALSE, FALSE);
10531 emitcode ("push", "acc");
10534 freeAsmop (right, NULL, ic, FALSE);
10535 /* now assign DPTR to result */
10536 aopOp (result, ic, FALSE);
10537 size = AOP_SIZE (result);
10540 emitcode ("pop", "acc");
10541 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10543 freeAsmop (result, NULL, ic, FALSE);
10547 /*-----------------------------------------------------------------*/
10548 /* genAssign - generate code for assignment */
10549 /*-----------------------------------------------------------------*/
10551 genAssign (iCode * ic)
10553 operand *result, *right;
10555 unsigned long lit = 0L;
10557 D(emitcode("; genAssign",""));
10559 result = IC_RESULT (ic);
10560 right = IC_RIGHT (ic);
10562 /* if they are the same */
10563 if (operandsEqu (result, right) &&
10564 !isOperandVolatile (result, FALSE) &&
10565 !isOperandVolatile (right, FALSE))
10568 aopOp (right, ic, FALSE);
10570 /* special case both in far space */
10571 if (AOP_TYPE (right) == AOP_DPTR &&
10572 IS_TRUE_SYMOP (result) &&
10573 isOperandInFarSpace (result))
10576 genFarFarAssign (result, right, ic);
10580 aopOp (result, ic, TRUE);
10582 /* if they are the same registers */
10583 if (sameRegs (AOP (right), AOP (result)) &&
10584 !isOperandVolatile (result, FALSE) &&
10585 !isOperandVolatile (right, FALSE))
10588 /* if the result is a bit */
10589 if (AOP_TYPE (result) == AOP_CRY)
10592 /* if the right size is a literal then
10593 we know what the value is */
10594 if (AOP_TYPE (right) == AOP_LIT)
10596 if (((int) operandLitValue (right)))
10597 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10599 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10603 /* the right is also a bit variable */
10604 if (AOP_TYPE (right) == AOP_CRY)
10606 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10607 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10611 /* we need to or */
10613 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10617 /* bit variables done */
10619 size = AOP_SIZE (result);
10621 if (AOP_TYPE (right) == AOP_LIT)
10622 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10624 (AOP_TYPE (result) != AOP_REG) &&
10625 (AOP_TYPE (right) == AOP_LIT) &&
10626 !IS_FLOAT (operandType (right)) &&
10629 while ((size) && (lit))
10632 aopGet (right, offset, FALSE, FALSE),
10634 isOperandVolatile (result, FALSE));
10639 emitcode ("clr", "a");
10642 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10651 aopGet (right, offset, FALSE, FALSE),
10653 isOperandVolatile (result, FALSE));
10659 freeAsmop (right, NULL, ic, TRUE);
10660 freeAsmop (result, NULL, ic, TRUE);
10663 /*-----------------------------------------------------------------*/
10664 /* genJumpTab - generates code for jump table */
10665 /*-----------------------------------------------------------------*/
10667 genJumpTab (iCode * ic)
10669 symbol *jtab,*jtablo,*jtabhi;
10671 unsigned int count;
10673 D(emitcode ("; genJumpTab",""));
10675 count = elementsInSet( IC_JTLABELS (ic) );
10679 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10680 if the switch argument is in a register.
10681 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10682 /* (MB) What if peephole converts ljmp to sjmp or ret ???
10683 How will multiply by three be updated ???*/
10684 aopOp (IC_JTCOND (ic), ic, FALSE);
10685 /* get the condition into accumulator */
10686 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10688 /* multiply by three */
10689 emitcode ("add", "a,acc");
10690 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10691 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10693 jtab = newiTempLabel (NULL);
10694 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10695 emitcode ("jmp", "@a+dptr");
10696 emitcode ("", "%05d$:", jtab->key + 100);
10697 /* now generate the jump labels */
10698 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10699 jtab = setNextItem (IC_JTLABELS (ic)))
10700 emitcode ("ljmp", "%05d$", jtab->key + 100);
10704 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10705 if the switch argument is in a register.
10706 For n>6 this algorithm may be more compact */
10707 jtablo = newiTempLabel (NULL);
10708 jtabhi = newiTempLabel (NULL);
10710 /* get the condition into accumulator.
10711 Using b as temporary storage, if register push/pop is needed */
10712 aopOp (IC_JTCOND (ic), ic, FALSE);
10713 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10714 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10715 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10717 // (MB) what if B is in use???
10718 wassertl(!BINUSE, "B was in use");
10719 emitcode ("mov", "b,%s", l);
10722 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10726 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10727 emitcode ("movc", "a,@a+pc");
10728 emitcode ("push", "acc");
10731 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10732 emitcode ("movc", "a,@a+pc");
10733 emitcode ("push", "acc");
10737 /* this scales up to n<=255, but needs two more bytes
10738 and changes dptr */
10739 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10740 emitcode ("movc", "a,@a+dptr");
10741 emitcode ("push", "acc");
10744 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10745 emitcode ("movc", "a,@a+dptr");
10746 emitcode ("push", "acc");
10749 emitcode ("ret", "");
10751 /* now generate jump table, LSB */
10752 emitcode ("", "%05d$:", jtablo->key + 100);
10753 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10754 jtab = setNextItem (IC_JTLABELS (ic)))
10755 emitcode (".db", "%05d$", jtab->key + 100);
10757 /* now generate jump table, MSB */
10758 emitcode ("", "%05d$:", jtabhi->key + 100);
10759 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10760 jtab = setNextItem (IC_JTLABELS (ic)))
10761 emitcode (".db", "%05d$>>8", jtab->key + 100);
10765 /*-----------------------------------------------------------------*/
10766 /* genCast - gen code for casting */
10767 /*-----------------------------------------------------------------*/
10769 genCast (iCode * ic)
10771 operand *result = IC_RESULT (ic);
10772 sym_link *ctype = operandType (IC_LEFT (ic));
10773 sym_link *rtype = operandType (IC_RIGHT (ic));
10774 operand *right = IC_RIGHT (ic);
10777 D(emitcode("; genCast",""));
10779 /* if they are equivalent then do nothing */
10780 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10783 aopOp (right, ic, FALSE);
10784 aopOp (result, ic, FALSE);
10786 /* if the result is a bit (and not a bitfield) */
10787 // if (AOP_TYPE (result) == AOP_CRY)
10788 if (IS_BITVAR (OP_SYMBOL (result)->type)
10789 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10791 /* if the right size is a literal then
10792 we know what the value is */
10793 if (AOP_TYPE (right) == AOP_LIT)
10795 if (((int) operandLitValue (right)))
10796 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10798 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10803 /* the right is also a bit variable */
10804 if (AOP_TYPE (right) == AOP_CRY)
10806 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10807 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10811 /* we need to or */
10813 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10818 /* if they are the same size : or less */
10819 if (AOP_SIZE (result) <= AOP_SIZE (right))
10822 /* if they are in the same place */
10823 if (sameRegs (AOP (right), AOP (result)))
10826 /* if they in different places then copy */
10827 size = AOP_SIZE (result);
10832 aopGet (right, offset, FALSE, FALSE),
10834 isOperandVolatile (result, FALSE));
10841 /* if the result is of type pointer */
10842 if (IS_PTR (ctype))
10846 sym_link *type = operandType (right);
10847 sym_link *etype = getSpec (type);
10849 /* pointer to generic pointer */
10850 if (IS_GENPTR (ctype))
10853 p_type = DCL_TYPE (type);
10856 if (SPEC_SCLS(etype)==S_REGISTER) {
10857 // let's assume it is a generic pointer
10860 /* we have to go by the storage class */
10861 p_type = PTR_TYPE (SPEC_OCLS (etype));
10865 /* the first two bytes are known */
10866 size = GPTRSIZE - 1;
10871 aopGet (right, offset, FALSE, FALSE),
10873 isOperandVolatile (result, FALSE));
10876 /* the last byte depending on type */
10878 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10883 // pointerTypeToGPByte will have bitched.
10887 sprintf(gpValStr, "#0x%x", gpVal);
10888 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10893 /* just copy the pointers */
10894 size = AOP_SIZE (result);
10899 aopGet (right, offset, FALSE, FALSE),
10901 isOperandVolatile (result, FALSE));
10907 /* so we now know that the size of destination is greater
10908 than the size of the source */
10909 /* we move to result for the size of source */
10910 size = AOP_SIZE (right);
10915 aopGet (right, offset, FALSE, FALSE),
10917 isOperandVolatile (result, FALSE));
10921 /* now depending on the sign of the source && destination */
10922 size = AOP_SIZE (result) - AOP_SIZE (right);
10923 /* if unsigned or not an integral type */
10924 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10927 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10931 /* we need to extend the sign :{ */
10932 char *l = aopGet (right, AOP_SIZE (right) - 1,
10935 emitcode ("rlc", "a");
10936 emitcode ("subb", "a,acc");
10938 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10941 /* we are done hurray !!!! */
10944 freeAsmop (right, NULL, ic, TRUE);
10945 freeAsmop (result, NULL, ic, TRUE);
10949 /*-----------------------------------------------------------------*/
10950 /* genDjnz - generate decrement & jump if not zero instrucion */
10951 /*-----------------------------------------------------------------*/
10953 genDjnz (iCode * ic, iCode * ifx)
10955 symbol *lbl, *lbl1;
10959 D(emitcode ("; genDjnz",""));
10961 /* if the if condition has a false label
10962 then we cannot save */
10963 if (IC_FALSE (ifx))
10966 /* if the minus is not of the form
10968 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10969 !IS_OP_LITERAL (IC_RIGHT (ic)))
10972 if (operandLitValue (IC_RIGHT (ic)) != 1)
10975 /* if the size of this greater than one then no
10977 if (getSize (operandType (IC_RESULT (ic))) > 1)
10980 /* otherwise we can save BIG */
10981 lbl = newiTempLabel (NULL);
10982 lbl1 = newiTempLabel (NULL);
10984 aopOp (IC_RESULT (ic), ic, FALSE);
10986 if (AOP_NEEDSACC(IC_RESULT(ic)))
10988 /* If the result is accessed indirectly via
10989 * the accumulator, we must explicitly write
10990 * it back after the decrement.
10992 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
10994 if (strcmp(rByte, "a"))
10996 /* Something is hopelessly wrong */
10997 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10998 __FILE__, __LINE__);
10999 /* We can just give up; the generated code will be inefficient,
11000 * but what the hey.
11002 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11005 emitcode ("dec", "%s", rByte);
11006 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
11007 emitcode ("jnz", "%05d$", lbl->key + 100);
11009 else if (IS_AOP_PREG (IC_RESULT (ic)))
11011 emitcode ("dec", "%s",
11012 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11013 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
11014 emitcode ("jnz", "%05d$", lbl->key + 100);
11018 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
11021 emitcode ("sjmp", "%05d$", lbl1->key + 100);
11022 emitcode ("", "%05d$:", lbl->key + 100);
11023 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
11024 emitcode ("", "%05d$:", lbl1->key + 100);
11026 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11027 ifx->generated = 1;
11031 /*-----------------------------------------------------------------*/
11032 /* genReceive - generate code for a receive iCode */
11033 /*-----------------------------------------------------------------*/
11035 genReceive (iCode * ic)
11037 int size = getSize (operandType (IC_RESULT (ic)));
11040 D(emitcode ("; genReceive",""));
11042 if (ic->argreg == 1)
11043 { /* first parameter */
11044 if ((isOperandInFarSpace (IC_RESULT (ic)) ||
11045 isOperandInPagedSpace (IC_RESULT (ic))) &&
11046 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11047 IS_TRUE_SYMOP (IC_RESULT (ic))))
11050 int receivingA = 0;
11053 for (offset = 0; offset<size; offset++)
11054 if (!strcmp (fReturn[offset], "a"))
11059 if (size==1 || getTempRegs(tempRegs, size-1, ic))
11061 for (offset = size-1; offset>0; offset--)
11062 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
11063 emitcode("mov","a,%s", fReturn[0]);
11065 aopOp (IC_RESULT (ic), ic, FALSE);
11067 aopPut (IC_RESULT (ic), "a", offset,
11068 isOperandVolatile (IC_RESULT (ic), FALSE));
11069 for (offset = 1; offset<size; offset++)
11070 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
11071 isOperandVolatile (IC_RESULT (ic), FALSE));
11077 if (getTempRegs(tempRegs, size, ic))
11079 for (offset = 0; offset<size; offset++)
11080 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
11081 aopOp (IC_RESULT (ic), ic, FALSE);
11082 for (offset = 0; offset<size; offset++)
11083 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
11084 isOperandVolatile (IC_RESULT (ic), FALSE));
11089 offset = fReturnSizeMCS51 - size;
11092 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
11093 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
11096 aopOp (IC_RESULT (ic), ic, FALSE);
11097 size = AOP_SIZE (IC_RESULT (ic));
11101 emitcode ("pop", "acc");
11102 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11108 aopOp (IC_RESULT (ic), ic, FALSE);
11110 assignResultValue (IC_RESULT (ic), NULL);
11113 else if (ic->argreg > 12)
11114 { /* bit parameters */
11115 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
11117 aopOp (IC_RESULT (ic), ic, FALSE);
11118 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
11119 outBitC(IC_RESULT (ic));
11123 { /* other parameters */
11125 aopOp (IC_RESULT (ic), ic, FALSE);
11126 rb1off = ic->argreg;
11129 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
11134 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11137 /*-----------------------------------------------------------------*/
11138 /* genDummyRead - generate code for dummy read of volatiles */
11139 /*-----------------------------------------------------------------*/
11141 genDummyRead (iCode * ic)
11146 D(emitcode("; genDummyRead",""));
11148 op = IC_RIGHT (ic);
11149 if (op && IS_SYMOP (op))
11151 aopOp (op, ic, FALSE);
11153 /* if the result is a bit */
11154 if (AOP_TYPE (op) == AOP_CRY)
11155 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11158 /* bit variables done */
11160 size = AOP_SIZE (op);
11164 MOVA (aopGet (op, offset, FALSE, FALSE));
11169 freeAsmop (op, NULL, ic, TRUE);
11173 if (op && IS_SYMOP (op))
11175 aopOp (op, ic, FALSE);
11177 /* if the result is a bit */
11178 if (AOP_TYPE (op) == AOP_CRY)
11179 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
11182 /* bit variables done */
11184 size = AOP_SIZE (op);
11188 MOVA (aopGet (op, offset, FALSE, FALSE));
11193 freeAsmop (op, NULL, ic, TRUE);
11197 /*-----------------------------------------------------------------*/
11198 /* genCritical - generate code for start of a critical sequence */
11199 /*-----------------------------------------------------------------*/
11201 genCritical (iCode *ic)
11203 symbol *tlbl = newiTempLabel (NULL);
11205 D(emitcode("; genCritical",""));
11207 if (IC_RESULT (ic))
11209 aopOp (IC_RESULT (ic), ic, TRUE);
11210 aopPut (IC_RESULT (ic), one, 0, 0);
11211 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11212 aopPut (IC_RESULT (ic), zero, 0, 0);
11213 emitcode ("", "%05d$:", (tlbl->key + 100));
11214 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11218 emitcode ("setb", "c");
11219 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11220 emitcode ("clr", "c");
11221 emitcode ("", "%05d$:", (tlbl->key + 100));
11222 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11226 /*-----------------------------------------------------------------*/
11227 /* genEndCritical - generate code for end of a critical sequence */
11228 /*-----------------------------------------------------------------*/
11230 genEndCritical (iCode *ic)
11232 D(emitcode("; genEndCritical",""));
11236 aopOp (IC_RIGHT (ic), ic, FALSE);
11237 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11239 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11240 emitcode ("mov", "ea,c");
11244 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11245 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11246 emitcode ("rrc", "a");
11247 emitcode ("mov", "ea,c");
11249 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11253 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11254 emitcode ("mov", "ea,c");
11258 /*-----------------------------------------------------------------*/
11259 /* gen51Code - generate code for 8051 based controllers */
11260 /*-----------------------------------------------------------------*/
11262 gen51Code (iCode * lic)
11266 /* int cseq = 0; */
11268 _G.currentFunc = NULL;
11269 lineHead = lineCurr = NULL;
11271 /* print the allocation information */
11272 if (allocInfo && currFunc)
11273 printAllocInfo (currFunc, codeOutFile);
11274 /* if debug information required */
11275 if (options.debug && currFunc)
11277 debugFile->writeFunction (currFunc, lic);
11279 /* stack pointer name */
11280 if (options.useXstack)
11286 for (ic = lic; ic; ic = ic->next)
11288 _G.current_iCode = ic;
11290 if (ic->lineno && cln != ic->lineno)
11294 debugFile->writeCLine (ic);
11296 if (!options.noCcodeInAsm) {
11297 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11298 printCLine(ic->filename, ic->lineno));
11303 if (ic->seqPoint && ic->seqPoint != cseq)
11305 emitcode ("", "; sequence point %d", ic->seqPoint);
11306 cseq = ic->seqPoint;
11309 if (options.iCodeInAsm) {
11310 char regsInUse[80];
11313 for (i=0; i<8; i++) {
11314 sprintf (®sInUse[i],
11315 "%c", ic->riu & (1<<i) ? i+'0' : '-');
11318 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11320 /* if the result is marked as
11321 spilt and rematerializable or code for
11322 this has already been generated then
11324 if (resultRemat (ic) || ic->generated)
11327 /* depending on the operation */
11347 /* IPOP happens only when trying to restore a
11348 spilt live range, if there is an ifx statement
11349 following this pop then the if statement might
11350 be using some of the registers being popped which
11351 would destory the contents of the register so
11352 we need to check for this condition and handle it */
11354 ic->next->op == IFX &&
11355 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11356 genIfx (ic->next, ic);
11374 genEndFunction (ic);
11394 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11411 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11415 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11422 /* note these two are xlated by algebraic equivalence
11423 during parsing SDCC.y */
11424 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11425 "got '>=' or '<=' shouldn't have come here");
11429 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11441 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11445 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11449 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11485 genRightShift (ic);
11488 case GET_VALUE_AT_ADDRESS:
11490 hasInc (IC_LEFT (ic), ic,
11491 getSize (operandType (IC_RESULT (ic)))),
11492 ifxForOp (IC_RESULT (ic), ic) );
11496 if (POINTER_SET (ic))
11497 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11523 addSet (&_G.sendSet, ic);
11526 case DUMMY_READ_VOLATILE:
11535 genEndCritical (ic);
11547 _G.current_iCode = NULL;
11549 /* now we are ready to call the
11550 peep hole optimizer */
11551 if (!options.nopeep)
11552 peepHole (&lineHead);
11554 /* now do the actual printing */
11555 printLine (lineHead, codeOutFile);