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");
1353 /*-----------------------------------------------------------------*/
1354 /* aopPut - puts a string for a aop and indicates if acc is in use */
1355 /*-----------------------------------------------------------------*/
1357 aopPut (operand * result, const char *s, int offset, bool bvolatile)
1360 bool accuse = FALSE;
1361 asmop * aop = AOP (result);
1363 if (aop->size && offset > (aop->size - 1))
1365 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1366 "aopPut got offset > aop->size");
1370 /* will assign value to value */
1371 /* depending on where it is ofcourse */
1375 MOVA (s); /* read s in case it was volatile */
1380 if (SPEC_SCLS (getSpec (operandType (result))) == S_SFR && offset)
1381 sprintf (d, "(%s >> %d)",
1382 aop->aopu.aop_dir, offset * 8);
1384 sprintf (d, "(%s + %d)",
1385 aop->aopu.aop_dir, offset);
1387 sprintf (d, "%s", aop->aopu.aop_dir);
1389 if (strcmp (d, s) ||
1391 emitcode ("mov", "%s,%s", d, s);
1392 if (!strcmp (d, "acc"))
1398 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1399 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1402 strcmp (s, "r0") == 0 ||
1403 strcmp (s, "r1") == 0 ||
1404 strcmp (s, "r2") == 0 ||
1405 strcmp (s, "r3") == 0 ||
1406 strcmp (s, "r4") == 0 ||
1407 strcmp (s, "r5") == 0 ||
1408 strcmp (s, "r6") == 0 ||
1409 strcmp (s, "r7") == 0)
1410 emitcode ("mov", "%s,%s",
1411 aop->aopu.aop_reg[offset]->dname, s);
1413 emitcode ("mov", "%s,%s",
1414 aop->aopu.aop_reg[offset]->name, s);
1421 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1422 "aopPut writing to code space");
1426 while (offset > aop->coff)
1429 emitcode ("inc", "dptr");
1432 while (offset < aop->coff)
1435 emitcode ("lcall", "__decdptr");
1440 /* if not in accumulator */
1443 emitcode ("movx", "@dptr,a");
1448 while (offset > aop->coff)
1451 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1453 while (offset < aop->coff)
1456 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1463 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1469 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1471 else if (strcmp (s, "r0") == 0 ||
1472 strcmp (s, "r1") == 0 ||
1473 strcmp (s, "r2") == 0 ||
1474 strcmp (s, "r3") == 0 ||
1475 strcmp (s, "r4") == 0 ||
1476 strcmp (s, "r5") == 0 ||
1477 strcmp (s, "r6") == 0 ||
1478 strcmp (s, "r7") == 0)
1481 sprintf (buffer, "a%s", s);
1482 emitcode ("mov", "@%s,%s",
1483 aop->aopu.aop_ptr->name, buffer);
1486 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1491 if (strcmp (s, "a") == 0)
1492 emitcode ("push", "acc");
1496 emitcode ("push", "acc");
1498 emitcode ("push", s);
1504 /* if not bit variable */
1505 if (!aop->aopu.aop_dir)
1507 /* inefficient: move carry into A and use jz/jnz */
1508 emitcode ("clr", "a");
1509 emitcode ("rlc", "a");
1515 emitcode ("clr", "%s", aop->aopu.aop_dir);
1517 emitcode ("setb", "%s", aop->aopu.aop_dir);
1518 else if (!strcmp (s, "c"))
1519 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1520 else if (strcmp (s, aop->aopu.aop_dir))
1523 /* set C, if a >= 1 */
1524 emitcode ("add", "a,#0xff");
1525 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1532 if (strcmp (aop->aopu.aop_str[offset], s) ||
1534 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1540 if (!offset && (strcmp (s, "acc") == 0) &&
1544 if (strcmp (aop->aopu.aop_str[offset], s) &&
1546 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1550 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1551 "aopPut got unsupported aop->type");
1560 /*-----------------------------------------------------------------*/
1561 /* pointToEnd :- points to the last byte of the operand */
1562 /*-----------------------------------------------------------------*/
1564 pointToEnd (asmop * aop)
1570 aop->coff = count = (aop->size - 1);
1576 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1580 emitcode ("inc", "dptr");
1587 /*-----------------------------------------------------------------*/
1588 /* reAdjustPreg - points a register back to where it should */
1589 /*-----------------------------------------------------------------*/
1591 reAdjustPreg (asmop * aop)
1593 if ((aop->coff==0) || aop->size <= 1)
1601 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1606 emitcode ("lcall", "__decdptr");
1613 /*-----------------------------------------------------------------*/
1614 /* opIsGptr: returns non-zero if the passed operand is */
1615 /* a generic pointer type. */
1616 /*-----------------------------------------------------------------*/
1618 opIsGptr (operand * op)
1620 sym_link *type = operandType (op);
1622 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1629 /*-----------------------------------------------------------------*/
1630 /* getDataSize - get the operand data size */
1631 /*-----------------------------------------------------------------*/
1633 getDataSize (operand * op)
1636 size = AOP_SIZE (op);
1637 if (size == GPTRSIZE)
1639 sym_link *type = operandType (op);
1640 if (IS_GENPTR (type))
1642 /* generic pointer; arithmetic operations
1643 * should ignore the high byte (pointer type).
1651 /*-----------------------------------------------------------------*/
1652 /* outAcc - output Acc */
1653 /*-----------------------------------------------------------------*/
1655 outAcc (operand * result)
1658 size = getDataSize (result);
1661 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
1664 /* unsigned or positive */
1667 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
1672 /*-----------------------------------------------------------------*/
1673 /* outBitC - output a bit C */
1674 /*-----------------------------------------------------------------*/
1676 outBitC (operand * result)
1678 /* if the result is bit */
1679 if (AOP_TYPE (result) == AOP_CRY)
1680 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
1683 emitcode ("clr", "a");
1684 emitcode ("rlc", "a");
1689 /*-----------------------------------------------------------------*/
1690 /* toBoolean - emit code for orl a,operator(sizeop) */
1691 /*-----------------------------------------------------------------*/
1693 toBoolean (operand * oper)
1695 int size = AOP_SIZE (oper) - 1;
1697 bool AccUsed = FALSE;
1700 while (!AccUsed && size--)
1702 AccUsed |= aopGetUsesAcc(oper, offset++);
1705 size = AOP_SIZE (oper) - 1;
1707 MOVA (aopGet (oper, 0, FALSE, FALSE));
1708 if (size && AccUsed && (AOP (oper)->type != AOP_ACC))
1711 emitcode("mov", "b,a");
1714 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1715 emitcode ("orl", "b,a");
1717 MOVA (aopGet (oper, offset++, FALSE, FALSE));
1718 emitcode ("orl", "a,b");
1725 emitcode ("orl", "a,%s", aopGet (oper, offset++, FALSE, FALSE));
1731 /*-----------------------------------------------------------------*/
1732 /* genNot - generate code for ! operation */
1733 /*-----------------------------------------------------------------*/
1739 D(emitcode ("; genNot",""));
1741 /* assign asmOps to operand & result */
1742 aopOp (IC_LEFT (ic), ic, FALSE);
1743 aopOp (IC_RESULT (ic), ic, TRUE);
1745 /* if in bit space then a special case */
1746 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1748 /* if left==result then cpl bit */
1749 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
1751 emitcode ("cpl", "%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1755 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1756 emitcode ("cpl", "c");
1757 outBitC (IC_RESULT (ic));
1762 toBoolean (IC_LEFT (ic));
1764 /* set C, if a == 0 */
1765 tlbl = newiTempLabel (NULL);
1766 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1767 emitcode ("", "%05d$:", tlbl->key + 100);
1768 outBitC (IC_RESULT (ic));
1771 /* release the aops */
1772 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1773 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1777 /*-----------------------------------------------------------------*/
1778 /* genCpl - generate code for complement */
1779 /*-----------------------------------------------------------------*/
1786 sym_link *letype = getSpec (operandType (IC_LEFT (ic)));
1788 D(emitcode (";", "genCpl"));
1790 /* assign asmOps to operand & result */
1791 aopOp (IC_LEFT (ic), ic, FALSE);
1792 aopOp (IC_RESULT (ic), ic, TRUE);
1794 /* special case if in bit space */
1795 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
1799 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY ||
1800 (SPEC_USIGN (letype) && IS_CHAR (letype)))
1802 /* promotion rules are responsible for this strange result:
1803 bit -> int -> ~int -> bit
1804 uchar -> int -> ~int -> bit
1806 werror(W_COMPLEMENT);
1807 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1811 tlbl=newiTempLabel(NULL);
1812 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1813 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1814 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1815 IS_AOP_PREG (IC_LEFT (ic)))
1817 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1822 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1824 emitcode ("", "%05d$:", tlbl->key + 100);
1825 outBitC (IC_RESULT(ic));
1829 size = AOP_SIZE (IC_RESULT (ic));
1832 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1834 emitcode ("cpl", "a");
1835 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1840 /* release the aops */
1841 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1842 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1845 /*-----------------------------------------------------------------*/
1846 /* genUminusFloat - unary minus for floating points */
1847 /*-----------------------------------------------------------------*/
1849 genUminusFloat (operand * op, operand * result)
1851 int size, offset = 0;
1854 D(emitcode ("; genUminusFloat",""));
1856 /* for this we just copy and then flip the bit */
1858 size = AOP_SIZE (op) - 1;
1863 aopGet (op, offset, FALSE, FALSE),
1865 isOperandVolatile (result, FALSE));
1869 l = aopGet (op, offset, FALSE, FALSE);
1873 emitcode ("cpl", "acc.7");
1874 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1877 /*-----------------------------------------------------------------*/
1878 /* genUminus - unary minus code generation */
1879 /*-----------------------------------------------------------------*/
1881 genUminus (iCode * ic)
1884 sym_link *optype, *rtype;
1887 D(emitcode ("; genUminus",""));
1890 aopOp (IC_LEFT (ic), ic, FALSE);
1891 aopOp (IC_RESULT (ic), ic, TRUE);
1893 /* if both in bit space then special
1895 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1896 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1899 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1900 emitcode ("cpl", "c");
1901 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1905 optype = operandType (IC_LEFT (ic));
1906 rtype = operandType (IC_RESULT (ic));
1908 /* if float then do float stuff */
1909 if (IS_FLOAT (optype))
1911 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1915 /* otherwise subtract from zero */
1916 size = AOP_SIZE (IC_LEFT (ic));
1921 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1922 if (!strcmp (l, "a"))
1926 emitcode ("cpl", "a");
1927 emitcode ("addc", "a,#0");
1933 emitcode ("clr", "a");
1934 emitcode ("subb", "a,%s", l);
1936 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1939 /* if any remaining bytes in the result */
1940 /* we just need to propagate the sign */
1941 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1943 emitcode ("rlc", "a");
1944 emitcode ("subb", "a,acc");
1946 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1950 /* release the aops */
1951 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1952 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1955 /*-----------------------------------------------------------------*/
1956 /* saveRegisters - will look for a call and save the registers */
1957 /*-----------------------------------------------------------------*/
1959 saveRegisters (iCode * lic)
1966 for (ic = lic; ic; ic = ic->next)
1967 if (ic->op == CALL || ic->op == PCALL)
1972 fprintf (stderr, "found parameter push with no function call\n");
1976 /* if the registers have been saved already or don't need to be then
1980 if (IS_SYMOP(IC_LEFT(ic)) &&
1981 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1982 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1985 /* save the registers in use at this time but skip the
1986 ones for the result */
1987 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1988 mcs51_rUmaskForOp (IC_RESULT(ic)));
1991 if (options.useXstack)
1993 int count = bitVectnBitsOn (rsave);
1997 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
1998 if (reg->type == REG_BIT)
2000 emitcode ("mov", "a,%s", reg->base);
2004 emitcode ("mov", "a,%s", reg->name);
2006 emitcode ("mov", "r0,%s", spname);
2007 emitcode ("inc", "%s", spname);// allocate before use
2008 emitcode ("movx", "@r0,a");
2009 if (bitVectBitValue (rsave, R0_IDX))
2010 emitcode ("mov", "r0,a");
2012 else if (count != 0)
2014 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2015 int nBits = bitVectnBitsOn (rsavebits);
2019 count = count - nBits + 1;
2020 /* remove all but the first bits as they are pushed all at once */
2021 rsave = bitVectCplAnd (rsave, rsavebits);
2022 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2025 if (bitVectBitValue (rsave, R0_IDX))
2027 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2029 emitcode ("mov", "r0,%s", spname);
2031 emitcode ("add", "a,#%d", count);
2032 emitcode ("mov", "%s,a", spname);
2033 for (i = 0; i < mcs51_nRegs; i++)
2035 if (bitVectBitValue (rsave, i))
2037 regs * reg = mcs51_regWithIdx (i);
2040 emitcode ("pop", "acc");
2041 emitcode ("push", "acc");
2043 else if (reg->type == REG_BIT)
2045 emitcode ("mov", "a,%s", reg->base);
2049 emitcode ("mov", "a,%s", reg->name);
2051 emitcode ("movx", "@r0,a");
2054 emitcode ("inc", "r0");
2058 if (bitVectBitValue (rsave, R0_IDX))
2060 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2066 bool bits_pushed = FALSE;
2067 for (i = 0; i < mcs51_nRegs; i++)
2069 if (bitVectBitValue (rsave, i))
2071 bits_pushed = pushReg (i, bits_pushed);
2077 /*-----------------------------------------------------------------*/
2078 /* unsaveRegisters - pop the pushed registers */
2079 /*-----------------------------------------------------------------*/
2081 unsaveRegisters (iCode * ic)
2086 /* restore the registers in use at this time but skip the
2087 ones for the result */
2088 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2089 mcs51_rUmaskForOp (IC_RESULT(ic)));
2091 if (options.useXstack)
2093 int count = bitVectnBitsOn (rsave);
2097 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2098 emitcode ("mov", "r0,%s", spname);
2099 emitcode ("dec", "r0");
2100 emitcode ("movx", "a,@r0");
2101 if (reg->type == REG_BIT)
2103 emitcode ("mov", "%s,a", reg->base);
2107 emitcode ("mov", "%s,a", reg->name);
2109 emitcode ("dec", "%s", spname);
2111 else if (count != 0)
2113 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2114 int nBits = bitVectnBitsOn (rsavebits);
2118 count = count - nBits + 1;
2119 /* remove all but the first bits as they are popped all at once */
2120 rsave = bitVectCplAnd (rsave, rsavebits);
2121 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2124 emitcode ("mov", "r0,%s", spname);
2125 for (i = mcs51_nRegs; i >= 0; i--)
2127 if (bitVectBitValue (rsave, i))
2129 regs * reg = mcs51_regWithIdx (i);
2130 emitcode ("dec", "r0");
2131 emitcode ("movx", "a,@r0");
2134 emitcode ("push", "acc");
2136 else if (reg->type == REG_BIT)
2138 emitcode ("mov", "%s,a", reg->base);
2142 emitcode ("mov", "%s,a", reg->name);
2146 emitcode ("mov", "%s,r0", spname);
2147 if (bitVectBitValue (rsave, R0_IDX))
2149 emitcode ("pop", "ar0");
2155 bool bits_popped = FALSE;
2156 for (i = mcs51_nRegs; i >= 0; i--)
2158 if (bitVectBitValue (rsave, i))
2160 bits_popped = popReg (i, bits_popped);
2167 /*-----------------------------------------------------------------*/
2169 /*-----------------------------------------------------------------*/
2171 pushSide (operand * oper, int size)
2176 char *l = aopGet (oper, offset++, FALSE, TRUE);
2177 if (AOP_TYPE (oper) != AOP_REG &&
2178 AOP_TYPE (oper) != AOP_DIR &&
2182 emitcode ("push", "acc");
2186 emitcode ("push", "%s", l);
2191 /*-----------------------------------------------------------------*/
2192 /* assignResultValue - also indicates if acc is in use afterwards */
2193 /*-----------------------------------------------------------------*/
2195 assignResultValue (operand * oper, operand * func)
2198 int size = AOP_SIZE (oper);
2199 bool accuse = FALSE;
2201 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2209 accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2216 /*-----------------------------------------------------------------*/
2217 /* genXpush - pushes onto the external stack */
2218 /*-----------------------------------------------------------------*/
2220 genXpush (iCode * ic)
2222 asmop *aop = newAsmop (0);
2224 int size, offset = 0;
2226 D(emitcode ("; genXpush",""));
2228 aopOp (IC_LEFT (ic), ic, FALSE);
2229 r = getFreePtr (ic, &aop, FALSE);
2231 size = AOP_SIZE (IC_LEFT (ic));
2235 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2236 emitcode ("mov", "%s,%s", r->name, spname);
2237 emitcode ("inc", "%s", spname); // allocate space first
2238 emitcode ("movx", "@%s,a", r->name);
2242 // allocate space first
2243 emitcode ("mov", "%s,%s", r->name, spname);
2245 emitcode ("add", "a,#%d", size);
2246 emitcode ("mov", "%s,a", spname);
2250 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2251 emitcode ("movx", "@%s,a", r->name);
2252 emitcode ("inc", "%s", r->name);
2256 freeAsmop (NULL, aop, ic, TRUE);
2257 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2260 /*-----------------------------------------------------------------*/
2261 /* genIpush - generate code for pushing this gets a little complex */
2262 /*-----------------------------------------------------------------*/
2264 genIpush (iCode * ic)
2266 int size, offset = 0;
2270 D(emitcode ("; genIpush",""));
2272 /* if this is not a parm push : ie. it is spill push
2273 and spill push is always done on the local stack */
2277 /* and the item is spilt then do nothing */
2278 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2281 aopOp (IC_LEFT (ic), ic, FALSE);
2282 size = AOP_SIZE (IC_LEFT (ic));
2283 /* push it on the stack */
2286 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2292 emitcode ("push", "%s", l);
2297 /* this is a parameter push: in this case we call
2298 the routine to find the call and save those
2299 registers that need to be saved */
2302 /* if use external stack then call the external
2303 stack pushing routine */
2304 if (options.useXstack)
2310 /* then do the push */
2311 aopOp (IC_LEFT (ic), ic, FALSE);
2313 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2314 size = AOP_SIZE (IC_LEFT (ic));
2318 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2319 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2320 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2323 if (strcmp (l, prev) || *l == '@')
2325 emitcode ("push", "acc");
2329 emitcode ("push", "%s", l);
2334 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2337 /*-----------------------------------------------------------------*/
2338 /* genIpop - recover the registers: can happen only for spilling */
2339 /*-----------------------------------------------------------------*/
2341 genIpop (iCode * ic)
2345 D(emitcode ("; genIpop",""));
2347 /* if the temp was not pushed then */
2348 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2351 aopOp (IC_LEFT (ic), ic, FALSE);
2352 size = AOP_SIZE (IC_LEFT (ic));
2353 offset = (size - 1);
2355 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2358 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2361 /*-----------------------------------------------------------------*/
2362 /* saveRBank - saves an entire register bank on the stack */
2363 /*-----------------------------------------------------------------*/
2365 saveRBank (int bank, iCode * ic, bool pushPsw)
2368 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2372 if (options.useXstack)
2376 /* Assume r0 is available for use. */
2377 r = mcs51_regWithIdx (R0_IDX);;
2382 r = getFreePtr (ic, &aop, FALSE);
2384 // allocate space first
2385 emitcode ("mov", "%s,%s", r->name, spname);
2387 emitcode ("add", "a,#%d", count);
2388 emitcode ("mov", "%s,a", spname);
2391 for (i = 0; i < mcs51_nRegs; i++)
2393 if (options.useXstack)
2395 emitcode ("mov", "a,(%s+%d)",
2396 regs8051[i].base, 8 * bank + regs8051[i].offset);
2397 emitcode ("movx", "@%s,a", r->name);
2399 emitcode ("inc", "%s", r->name);
2402 emitcode ("push", "(%s+%d)",
2403 regs8051[i].base, 8 * bank + regs8051[i].offset);
2408 if (options.useXstack)
2410 emitcode ("mov", "a,psw");
2411 emitcode ("movx", "@%s,a", r->name);
2416 emitcode ("push", "psw");
2419 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2424 freeAsmop (NULL, aop, ic, TRUE);
2433 /*-----------------------------------------------------------------*/
2434 /* unsaveRBank - restores the register bank from stack */
2435 /*-----------------------------------------------------------------*/
2437 unsaveRBank (int bank, iCode * ic, bool popPsw)
2443 if (options.useXstack)
2447 /* Assume r0 is available for use. */
2448 r = mcs51_regWithIdx (R0_IDX);;
2453 r = getFreePtr (ic, &aop, FALSE);
2455 emitcode ("mov", "%s,%s", r->name, spname);
2460 if (options.useXstack)
2462 emitcode ("dec", "%s", r->name);
2463 emitcode ("movx", "a,@%s", r->name);
2464 emitcode ("mov", "psw,a");
2468 emitcode ("pop", "psw");
2472 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2474 if (options.useXstack)
2476 emitcode ("dec", "%s", r->name);
2477 emitcode ("movx", "a,@%s", r->name);
2478 emitcode ("mov", "(%s+%d),a",
2479 regs8051[i].base, 8 * bank + regs8051[i].offset);
2483 emitcode ("pop", "(%s+%d)",
2484 regs8051[i].base, 8 * bank + regs8051[i].offset);
2488 if (options.useXstack)
2490 emitcode ("mov", "%s,%s", spname, r->name);
2495 freeAsmop (NULL, aop, ic, TRUE);
2499 /*-----------------------------------------------------------------*/
2500 /* genSend - gen code for SEND */
2501 /*-----------------------------------------------------------------*/
2502 static void genSend(set *sendSet)
2507 /* first we do all bit parameters */
2508 for (sic = setFirstItem (sendSet); sic;
2509 sic = setNextItem (sendSet))
2511 aopOp (IC_LEFT (sic), sic, FALSE);
2513 if (sic->argreg > 12)
2515 int bit = sic->argreg-13;
2517 /* if left is a literal then
2518 we know what the value is */
2519 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2521 if (((int) operandLitValue (IC_LEFT (sic))))
2522 emitcode ("setb", "b[%d]", bit);
2524 emitcode ("clr", "b[%d]", bit);
2526 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2528 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2529 if (strcmp (l, "c"))
2530 emitcode ("mov", "c,%s", l);
2531 emitcode ("mov", "b[%d],c", bit);
2536 toBoolean (IC_LEFT (sic));
2537 /* set C, if a >= 1 */
2538 emitcode ("add", "a,#0xff");
2539 emitcode ("mov", "b[%d],c", bit);
2544 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2549 saveRegisters (setFirstItem (sendSet));
2550 emitcode ("mov", "bits,b");
2553 /* then we do all other parameters */
2554 for (sic = setFirstItem (sendSet); sic;
2555 sic = setNextItem (sendSet))
2557 int size, offset = 0;
2558 aopOp (IC_LEFT (sic), sic, FALSE);
2559 size = AOP_SIZE (IC_LEFT (sic));
2561 if (sic->argreg == 1)
2565 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2566 if (strcmp (l, fReturn[offset]))
2567 emitcode ("mov", "%s,%s", fReturn[offset], l);
2571 else if (sic->argreg <= 12)
2575 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2576 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2580 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2584 /*-----------------------------------------------------------------*/
2585 /* selectRegBank - emit code to select the register bank */
2586 /*-----------------------------------------------------------------*/
2588 selectRegBank (short bank, bool keepFlags)
2590 /* if f.e. result is in carry */
2593 emitcode ("anl", "psw,#0xE7");
2595 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2599 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2603 /*-----------------------------------------------------------------*/
2604 /* genCall - generates a call statement */
2605 /*-----------------------------------------------------------------*/
2607 genCall (iCode * ic)
2611 // bool restoreBank = FALSE;
2612 bool swapBanks = FALSE;
2613 bool accuse = FALSE;
2614 bool accPushed = FALSE;
2615 bool resultInF0 = FALSE;
2617 D(emitcode("; genCall",""));
2619 dtype = operandType (IC_LEFT (ic));
2620 etype = getSpec(dtype);
2621 /* if send set is not empty then assign */
2624 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2625 genSend(reverseSet(_G.sendSet));
2627 genSend(_G.sendSet);
2633 /* if we are calling a not _naked function that is not using
2634 the same register bank then we need to save the
2635 destination registers on the stack */
2636 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2637 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2638 !IFFUNC_ISISR (dtype))
2643 /* if caller saves & we have not saved then */
2649 emitcode ("mov", "psw,#0x%02x",
2650 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2654 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2656 if (IFFUNC_CALLEESAVES(dtype))
2658 werror (E_BANKED_WITH_CALLEESAVES);
2662 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2663 OP_SYMBOL (IC_LEFT (ic))->rname :
2664 OP_SYMBOL (IC_LEFT (ic))->name);
2666 emitcode ("mov", "r0,#%s", l);
2667 emitcode ("mov", "r1,#(%s >> 8)", l);
2668 emitcode ("mov", "r2,#(%s >> 16)", l);
2669 emitcode ("lcall", "__sdcc_banked_call");
2674 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2675 OP_SYMBOL (IC_LEFT (ic))->rname :
2676 OP_SYMBOL (IC_LEFT (ic))->name));
2681 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2684 /* if we need assign a result value */
2685 if ((IS_ITEMP (IC_RESULT (ic)) &&
2686 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2687 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2688 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2689 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2690 IS_TRUE_SYMOP (IC_RESULT (ic)))
2694 aopOp (IC_RESULT (ic), ic, FALSE);
2697 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2699 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2702 /* adjust the stack for parameters if required */
2706 if (ic->parmBytes > 3)
2710 emitcode ("push", "acc");
2713 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2714 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2716 emitcode ("mov", "F0,c");
2720 emitcode ("mov", "a,%s", spname);
2721 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2722 emitcode ("mov", "%s,a", spname);
2724 /* unsaveRegisters from xstack needs acc, but */
2725 /* unsaveRegisters from stack needs this popped */
2726 if (accPushed && !options.useXstack)
2728 emitcode ("pop", "acc");
2733 for (i = 0; i < ic->parmBytes; i++)
2734 emitcode ("dec", "%s", spname);
2737 /* if we had saved some registers then unsave them */
2738 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2740 if (accuse && !accPushed && options.useXstack)
2742 /* xstack needs acc, but doesn't touch normal stack */
2743 emitcode ("push", "acc");
2746 unsaveRegisters (ic);
2749 // /* if register bank was saved then pop them */
2751 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2753 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2756 emitcode ("mov", "c,F0");
2758 aopOp (IC_RESULT (ic), ic, FALSE);
2759 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2760 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2764 emitcode ("pop", "acc");
2767 /*-----------------------------------------------------------------*/
2768 /* -10l - generates a call by pointer statement */
2769 /*-----------------------------------------------------------------*/
2771 genPcall (iCode * ic)
2775 symbol *rlbl = newiTempLabel (NULL);
2776 // bool restoreBank=FALSE;
2777 bool swapBanks = FALSE;
2778 bool resultInF0 = FALSE;
2780 D(emitcode("; genPCall",""));
2782 dtype = operandType (IC_LEFT (ic))->next;
2783 etype = getSpec(dtype);
2784 /* if caller saves & we have not saved then */
2788 /* if we are calling a not _naked function that is not using
2789 the same register bank then we need to save the
2790 destination registers on the stack */
2791 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2792 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2793 !IFFUNC_ISISR (dtype))
2795 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2796 // restoreBank=TRUE;
2798 // need caution message to user here
2801 if (IS_LITERAL(etype))
2803 /* if send set is not empty then assign */
2806 genSend(reverseSet(_G.sendSet));
2812 emitcode ("mov", "psw,#0x%02x",
2813 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2816 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2818 if (IFFUNC_CALLEESAVES(dtype))
2820 werror (E_BANKED_WITH_CALLEESAVES);
2824 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2826 emitcode ("mov", "r0,#%s", l);
2827 emitcode ("mov", "r1,#(%s >> 8)", l);
2828 emitcode ("mov", "r2,#(%s >> 16)", l);
2829 emitcode ("lcall", "__sdcc_banked_call");
2834 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2839 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2841 if (IFFUNC_CALLEESAVES(dtype))
2843 werror (E_BANKED_WITH_CALLEESAVES);
2847 aopOp (IC_LEFT (ic), ic, FALSE);
2851 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2852 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2853 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2857 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2858 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2859 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2860 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2863 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2865 /* if send set is not empty then assign */
2868 genSend(reverseSet(_G.sendSet));
2874 emitcode ("mov", "psw,#0x%02x",
2875 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2879 emitcode ("lcall", "__sdcc_banked_call");
2884 /* push the return address on to the stack */
2885 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2886 emitcode ("push", "acc");
2887 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2888 emitcode ("push", "acc");
2890 /* now push the calling address */
2891 aopOp (IC_LEFT (ic), ic, FALSE);
2893 pushSide (IC_LEFT (ic), FPTRSIZE);
2895 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2897 /* if send set is not empty the assign */
2900 genSend(reverseSet(_G.sendSet));
2906 emitcode ("mov", "psw,#0x%02x",
2907 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2911 emitcode ("ret", "");
2912 emitcode ("", "%05d$:", (rlbl->key + 100));
2917 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2920 /* if we need assign a result value */
2921 if ((IS_ITEMP (IC_RESULT (ic)) &&
2922 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2923 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2924 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2925 IS_TRUE_SYMOP (IC_RESULT (ic)))
2929 aopOp (IC_RESULT (ic), ic, FALSE);
2932 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2934 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2937 /* adjust the stack for parameters if required */
2941 if (ic->parmBytes > 3)
2943 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2944 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2946 emitcode ("mov", "F0,c");
2950 emitcode ("mov", "a,%s", spname);
2951 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2952 emitcode ("mov", "%s,a", spname);
2955 for (i = 0; i < ic->parmBytes; i++)
2956 emitcode ("dec", "%s", spname);
2960 // /* if register bank was saved then unsave them */
2962 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2964 /* if we had saved some registers then unsave them */
2965 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2966 unsaveRegisters (ic);
2968 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2971 emitcode ("mov", "c,F0");
2973 aopOp (IC_RESULT (ic), ic, FALSE);
2974 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2975 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2979 /*-----------------------------------------------------------------*/
2980 /* resultRemat - result is rematerializable */
2981 /*-----------------------------------------------------------------*/
2983 resultRemat (iCode * ic)
2985 if (SKIP_IC (ic) || ic->op == IFX)
2988 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2990 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2991 if (sym->remat && !POINTER_SET (ic))
2998 #if defined(__BORLANDC__) || defined(_MSC_VER)
2999 #define STRCASECMP stricmp
3001 #define STRCASECMP strcasecmp
3004 /*-----------------------------------------------------------------*/
3005 /* inExcludeList - return 1 if the string is in exclude Reg list */
3006 /*-----------------------------------------------------------------*/
3008 regsCmp(void *p1, void *p2)
3010 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3014 inExcludeList (char *s)
3016 const char *p = setFirstItem(options.excludeRegsSet);
3018 if (p == NULL || STRCASECMP(p, "none") == 0)
3022 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3025 /*-----------------------------------------------------------------*/
3026 /* genFunction - generated code for function entry */
3027 /*-----------------------------------------------------------------*/
3029 genFunction (iCode * ic)
3031 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3033 bool switchedPSW = FALSE;
3034 int calleesaves_saved_register = -1;
3035 int stackAdjust = sym->stack;
3036 int accIsFree = sym->recvSize < 4;
3037 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3038 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3041 /* create the function header */
3042 emitcode (";", "-----------------------------------------");
3043 emitcode (";", " function %s", sym->name);
3044 emitcode (";", "-----------------------------------------");
3046 emitcode ("", "%s:", sym->rname);
3047 ftype = operandType (IC_LEFT (ic));
3048 _G.currentFunc = sym;
3050 if (IFFUNC_ISNAKED(ftype))
3052 emitcode(";", "naked function: no prologue.");
3056 /* here we need to generate the equates for the
3057 register bank if required */
3058 if (FUNC_REGBANK (ftype) != rbank)
3062 rbank = FUNC_REGBANK (ftype);
3063 for (i = 0; i < mcs51_nRegs; i++)
3065 if (regs8051[i].type != REG_BIT)
3067 if (strcmp (regs8051[i].base, "0") == 0)
3068 emitcode ("", "%s = 0x%02x",
3070 8 * rbank + regs8051[i].offset);
3072 emitcode ("", "%s = %s + 0x%02x",
3075 8 * rbank + regs8051[i].offset);
3080 /* if this is an interrupt service routine then
3081 save acc, b, dpl, dph */
3082 if (IFFUNC_ISISR (sym->type))
3085 if (!inExcludeList ("acc"))
3086 emitcode ("push", "acc");
3087 if (!inExcludeList ("b"))
3088 emitcode ("push", "b");
3089 if (!inExcludeList ("dpl"))
3090 emitcode ("push", "dpl");
3091 if (!inExcludeList ("dph"))
3092 emitcode ("push", "dph");
3093 /* if this isr has no bank i.e. is going to
3094 run with bank 0 , then we need to save more
3096 if (!FUNC_REGBANK (sym->type))
3099 /* if this function does not call any other
3100 function then we can be economical and
3101 save only those registers that are used */
3102 if (!IFFUNC_HASFCALL(sym->type))
3106 /* if any registers used */
3109 bool bits_pushed = FALSE;
3110 /* save the registers used */
3111 for (i = 0; i < sym->regsUsed->size; i++)
3113 if (bitVectBitValue (sym->regsUsed, i))
3114 bits_pushed = pushReg (i, bits_pushed);
3121 /* this function has a function call. We cannot
3122 determines register usage so we will have to push the
3124 saveRBank (0, ic, FALSE);
3125 if (options.parms_in_bank1) {
3127 for (i=0; i < 8 ; i++ ) {
3128 emitcode ("push","%s",rb1regs[i]);
3135 /* This ISR uses a non-zero bank.
3137 * We assume that the bank is available for our
3140 * However, if this ISR calls a function which uses some
3141 * other bank, we must save that bank entirely.
3143 unsigned long banksToSave = 0;
3145 if (IFFUNC_HASFCALL(sym->type))
3148 #define MAX_REGISTER_BANKS 4
3153 for (i = ic; i; i = i->next)
3155 if (i->op == ENDFUNCTION)
3157 /* we got to the end OK. */
3165 dtype = operandType (IC_LEFT(i));
3167 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3169 /* Mark this bank for saving. */
3170 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3172 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3176 banksToSave |= (1 << FUNC_REGBANK(dtype));
3179 /* And note that we don't need to do it in
3187 /* This is a mess; we have no idea what
3188 * register bank the called function might
3191 * The only thing I can think of to do is
3192 * throw a warning and hope.
3194 werror(W_FUNCPTR_IN_USING_ISR);
3198 if (banksToSave && options.useXstack)
3200 /* Since we aren't passing it an ic,
3201 * saveRBank will assume r0 is available to abuse.
3203 * So switch to our (trashable) bank now, so
3204 * the caller's R0 isn't trashed.
3206 emitcode ("push", "psw");
3207 emitcode ("mov", "psw,#0x%02x",
3208 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3212 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3214 if (banksToSave & (1 << ix))
3216 saveRBank(ix, NULL, FALSE);
3220 // TODO: this needs a closer look
3221 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3224 /* Set the register bank to the desired value if nothing else */
3225 /* has done so yet. */
3228 emitcode ("push", "psw");
3229 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3234 /* This is a non-ISR function. The caller has already switched register */
3235 /* banks, if necessary, so just handle the callee-saves option. */
3237 /* if callee-save to be used for this function
3238 then save the registers being used in this function */
3239 if (IFFUNC_CALLEESAVES(sym->type))
3243 /* if any registers used */
3246 bool bits_pushed = FALSE;
3247 /* save the registers used */
3248 for (i = 0; i < sym->regsUsed->size; i++)
3250 if (bitVectBitValue (sym->regsUsed, i))
3252 /* remember one saved register for later usage */
3253 if (calleesaves_saved_register < 0)
3254 calleesaves_saved_register = i;
3255 bits_pushed = pushReg (i, bits_pushed);
3266 if (options.useXstack)
3268 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3270 emitcode ("mov", "r0,%s", spname);
3271 emitcode ("inc", "%s", spname);
3272 emitcode ("xch", "a,_bpx");
3273 emitcode ("movx", "@r0,a");
3274 emitcode ("inc", "r0");
3275 emitcode ("mov", "a,r0");
3276 emitcode ("xch", "a,_bpx");
3280 emitcode ("push", "_bp"); /* save the callers stack */
3281 emitcode ("mov", "_bp,sp");
3286 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3288 /* set up the stack */
3289 emitcode ("push", "_bp"); /* save the callers stack */
3290 emitcode ("mov", "_bp,sp");
3295 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3296 /* before setting up the stack frame completely. */
3297 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3299 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3303 if (rsym && rsym->regType == REG_CND)
3305 if (rsym && (rsym->accuse || rsym->ruonly))
3307 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3308 rsym = rsym->usl.spillLoc;
3311 /* If the RECEIVE operand immediately spills to the first entry on the */
3312 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3313 /* rather than the usual @r0/r1 machinations. */
3314 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3318 _G.current_iCode = ric;
3319 D(emitcode ("; genReceive",""));
3320 for (ofs=0; ofs < sym->recvSize; ofs++)
3322 if (!strcmp (fReturn[ofs], "a"))
3323 emitcode ("push", "acc");
3325 emitcode ("push", fReturn[ofs]);
3327 stackAdjust -= sym->recvSize;
3330 assert (stackAdjust>=0);
3333 _G.current_iCode = ic;
3337 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3338 /* to free up the accumulator. */
3339 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3343 _G.current_iCode = ric;
3344 D(emitcode ("; genReceive",""));
3345 for (ofs=0; ofs < sym->recvSize; ofs++)
3347 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3349 _G.current_iCode = ic;
3355 /* adjust the stack for the function */
3358 int i = stackAdjust;
3360 werror (W_STACK_OVERFLOW, sym->name);
3362 if (i > 3 && accIsFree)
3364 emitcode ("mov", "a,sp");
3365 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3366 emitcode ("mov", "sp,a");
3370 /* The accumulator is not free, so we will need another register */
3371 /* to clobber. No need to worry about a possible conflict with */
3372 /* the above early RECEIVE optimizations since they would have */
3373 /* freed the accumulator if they were generated. */
3375 if (IFFUNC_CALLEESAVES(sym->type))
3377 /* if it's a callee-saves function we need a saved register */
3378 if (calleesaves_saved_register >= 0)
3380 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3381 emitcode ("mov", "a,sp");
3382 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3383 emitcode ("mov", "sp,a");
3384 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3387 /* do it the hard way */
3389 emitcode ("inc", "sp");
3393 /* not callee-saves, we can clobber r0 */
3394 emitcode ("mov", "r0,a");
3395 emitcode ("mov", "a,sp");
3396 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3397 emitcode ("mov", "sp,a");
3398 emitcode ("mov", "a,r0");
3403 emitcode ("inc", "sp");
3408 char i = ((char) sym->xstack & 0xff);
3410 if (i > 3 && accIsFree)
3412 emitcode ("mov", "a,_spx");
3413 emitcode ("add", "a,#0x%02x", i);
3414 emitcode ("mov", "_spx,a");
3418 emitcode ("push", "acc");
3419 emitcode ("mov", "a,_spx");
3420 emitcode ("add", "a,#0x%02x", i);
3421 emitcode ("mov", "_spx,a");
3422 emitcode ("pop", "acc");
3427 emitcode ("inc", "_spx");
3431 /* if critical function then turn interrupts off */
3432 if (IFFUNC_ISCRITICAL (ftype))
3434 symbol *tlbl = newiTempLabel (NULL);
3435 emitcode ("setb", "c");
3436 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3437 emitcode ("clr", "c");
3438 emitcode ("", "%05d$:", (tlbl->key + 100));
3439 emitcode ("push", "psw"); /* save old ea via c in psw */
3443 /*-----------------------------------------------------------------*/
3444 /* genEndFunction - generates epilogue for functions */
3445 /*-----------------------------------------------------------------*/
3447 genEndFunction (iCode * ic)
3449 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3450 lineNode *lnp = lineCurr;
3452 bitVect *regsUsedPrologue;
3453 bitVect *regsUnneeded;
3456 _G.currentFunc = NULL;
3457 if (IFFUNC_ISNAKED(sym->type))
3459 emitcode(";", "naked function: no epilogue.");
3460 if (options.debug && currFunc)
3461 debugFile->writeEndFunction (currFunc, ic, 0);
3465 if (IFFUNC_ISCRITICAL (sym->type))
3467 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3469 emitcode ("rlc", "a"); /* save c in a */
3470 emitcode ("pop", "psw"); /* restore ea via c in psw */
3471 emitcode ("mov", "ea,c");
3472 emitcode ("rrc", "a"); /* restore c from a */
3476 emitcode ("pop", "psw"); /* restore ea via c in psw */
3477 emitcode ("mov", "ea,c");
3481 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3483 if (options.useXstack)
3487 emitcode ("mov", "sp,_bp");
3488 emitcode ("pop", "_bp");
3490 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3492 emitcode ("xch", "a,_bpx");
3493 emitcode ("mov", "r0,a");
3494 emitcode ("dec", "r0");
3495 emitcode ("movx", "a,@r0");
3496 emitcode ("xch", "a,_bpx");
3497 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3500 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3502 emitcode ("mov", "sp,_bp");
3503 emitcode ("pop", "_bp");
3507 /* restore the register bank */
3508 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3510 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3511 || !options.useXstack)
3513 /* Special case of ISR using non-zero bank with useXstack
3516 emitcode ("pop", "psw");
3520 if (IFFUNC_ISISR (sym->type))
3523 /* now we need to restore the registers */
3524 /* if this isr has no bank i.e. is going to
3525 run with bank 0 , then we need to save more
3527 if (!FUNC_REGBANK (sym->type))
3529 /* if this function does not call any other
3530 function then we can be economical and
3531 save only those registers that are used */
3532 if (!IFFUNC_HASFCALL(sym->type))
3536 /* if any registers used */
3539 bool bits_popped = FALSE;
3540 /* save the registers used */
3541 for (i = sym->regsUsed->size; i >= 0; i--)
3543 if (bitVectBitValue (sym->regsUsed, i))
3544 bits_popped = popReg (i, bits_popped);
3550 if (options.parms_in_bank1) {
3552 for (i = 7 ; i >= 0 ; i-- ) {
3553 emitcode ("pop","%s",rb1regs[i]);
3556 /* this function has a function call cannot
3557 determines register usage so we will have to pop the
3559 unsaveRBank (0, ic, FALSE);
3564 /* This ISR uses a non-zero bank.
3566 * Restore any register banks saved by genFunction
3569 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3572 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3574 if (savedBanks & (1 << ix))
3576 unsaveRBank(ix, NULL, FALSE);
3580 if (options.useXstack)
3582 /* Restore bank AFTER calling unsaveRBank,
3583 * since it can trash r0.
3585 emitcode ("pop", "psw");
3589 if (!inExcludeList ("dph"))
3590 emitcode ("pop", "dph");
3591 if (!inExcludeList ("dpl"))
3592 emitcode ("pop", "dpl");
3593 if (!inExcludeList ("b"))
3594 emitcode ("pop", "b");
3595 if (!inExcludeList ("acc"))
3596 emitcode ("pop", "acc");
3598 /* if debug then send end of function */
3599 if (options.debug && currFunc)
3601 debugFile->writeEndFunction (currFunc, ic, 1);
3604 emitcode ("reti", "");
3608 if (IFFUNC_CALLEESAVES(sym->type))
3612 /* if any registers used */
3615 /* save the registers used */
3616 for (i = sym->regsUsed->size; i >= 0; i--)
3618 if (bitVectBitValue (sym->regsUsed, i) ||
3619 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3620 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3623 else if (mcs51_ptrRegReq)
3625 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3626 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3631 /* if debug then send end of function */
3632 if (options.debug && currFunc)
3634 debugFile->writeEndFunction (currFunc, ic, 1);
3637 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3639 emitcode ("ljmp", "__sdcc_banked_ret");
3643 emitcode ("ret", "");
3647 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3650 /* If this was an interrupt handler using bank 0 that called another */
3651 /* function, then all registers must be saved; nothing to optimized. */
3652 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3653 && !FUNC_REGBANK(sym->type))
3656 /* There are no push/pops to optimize if not callee-saves or ISR */
3657 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3660 /* If there were stack parameters, we cannot optimize without also */
3661 /* fixing all of the stack offsets; this is too dificult to consider. */
3662 if (FUNC_HASSTACKPARM(sym->type))
3665 /* Compute the registers actually used */
3666 regsUsed = newBitVect (mcs51_nRegs);
3667 regsUsedPrologue = newBitVect (mcs51_nRegs);
3670 if (lnp->ic && lnp->ic->op == FUNCTION)
3671 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3673 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3675 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3676 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3683 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3684 && !bitVectBitValue (regsUsed, CND_IDX))
3686 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3687 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3688 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3689 bitVectUnSetBit (regsUsed, CND_IDX);
3692 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3694 /* If this was an interrupt handler that called another function */
3695 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3696 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3698 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3699 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3700 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3701 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3702 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3705 /* Remove the unneeded push/pops */
3706 regsUnneeded = newBitVect (mcs51_nRegs);
3709 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3711 if (!strncmp(lnp->line, "push", 4))
3713 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3714 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3716 connectLine (lnp->prev, lnp->next);
3717 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3720 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3722 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3723 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3725 connectLine (lnp->prev, lnp->next);
3726 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3733 for (idx = 0; idx < regsUnneeded->size; idx++)
3734 if (bitVectBitValue (regsUnneeded, idx))
3735 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3737 freeBitVect (regsUnneeded);
3738 freeBitVect (regsUsed);
3739 freeBitVect (regsUsedPrologue);
3742 /*-----------------------------------------------------------------*/
3743 /* genRet - generate code for return statement */
3744 /*-----------------------------------------------------------------*/
3748 int size, offset = 0, pushed = 0;
3750 D(emitcode ("; genRet",""));
3752 /* if we have no return value then
3753 just generate the "ret" */
3757 /* we have something to return then
3758 move the return value into place */
3759 aopOp (IC_LEFT (ic), ic, FALSE);
3760 size = AOP_SIZE (IC_LEFT (ic));
3763 if (IS_BIT(_G.currentFunc->etype))
3765 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3772 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3775 l = aopGet (IC_LEFT (ic), offset++,
3777 emitcode ("push", "%s", l);
3782 l = aopGet (IC_LEFT (ic), offset,
3784 if (strcmp (fReturn[offset], l))
3785 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3792 if (strcmp (fReturn[pushed], "a"))
3793 emitcode ("pop", fReturn[pushed]);
3795 emitcode ("pop", "acc");
3797 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3800 /* generate a jump to the return label
3801 if the next is not the return statement */
3802 if (!(ic->next && ic->next->op == LABEL &&
3803 IC_LABEL (ic->next) == returnLabel))
3805 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3809 /*-----------------------------------------------------------------*/
3810 /* genLabel - generates a label */
3811 /*-----------------------------------------------------------------*/
3813 genLabel (iCode * ic)
3815 /* special case never generate */
3816 if (IC_LABEL (ic) == entryLabel)
3819 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3822 /*-----------------------------------------------------------------*/
3823 /* genGoto - generates a ljmp */
3824 /*-----------------------------------------------------------------*/
3826 genGoto (iCode * ic)
3828 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3831 /*-----------------------------------------------------------------*/
3832 /* findLabelBackwards: walks back through the iCode chain looking */
3833 /* for the given label. Returns number of iCode instructions */
3834 /* between that label and given ic. */
3835 /* Returns zero if label not found. */
3836 /*-----------------------------------------------------------------*/
3838 findLabelBackwards (iCode * ic, int key)
3847 /* If we have any pushes or pops, we cannot predict the distance.
3848 I don't like this at all, this should be dealt with in the
3850 if (ic->op == IPUSH || ic->op == IPOP) {
3854 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3863 /*-----------------------------------------------------------------*/
3864 /* genPlusIncr :- does addition with increment if possible */
3865 /*-----------------------------------------------------------------*/
3867 genPlusIncr (iCode * ic)
3869 unsigned int icount;
3870 unsigned int size = getDataSize (IC_RESULT (ic));
3872 /* will try to generate an increment */
3873 /* if the right side is not a literal
3875 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3878 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3880 D(emitcode ("; genPlusIncr",""));
3882 /* if increment >=16 bits in register or direct space */
3883 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3884 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3885 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3893 /* If the next instruction is a goto and the goto target
3894 * is < 10 instructions previous to this, we can generate
3895 * jumps straight to that target.
3897 if (ic->next && ic->next->op == GOTO
3898 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3899 && labelRange <= 10)
3901 emitcode (";", "tail increment optimized");
3902 tlbl = IC_LABEL (ic->next);
3907 tlbl = newiTempLabel (NULL);
3910 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3911 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3912 IS_AOP_PREG (IC_RESULT (ic)))
3913 emitcode ("cjne", "%s,#0x00,%05d$",
3914 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3918 emitcode ("clr", "a");
3919 emitcode ("cjne", "a,%s,%05d$",
3920 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3924 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3927 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3928 IS_AOP_PREG (IC_RESULT (ic)))
3929 emitcode ("cjne", "%s,#0x00,%05d$",
3930 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3933 emitcode ("cjne", "a,%s,%05d$",
3934 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3937 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
3941 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3942 IS_AOP_PREG (IC_RESULT (ic)))
3943 emitcode ("cjne", "%s,#0x00,%05d$",
3944 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3948 emitcode ("cjne", "a,%s,%05d$",
3949 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3952 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
3957 emitcode ("", "%05d$:", tlbl->key + 100);
3962 /* if result is dptr */
3963 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
3964 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
3965 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
3966 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
3968 if (aopGetUsesAcc (IC_LEFT (ic), 0))
3974 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
3977 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
3978 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
3980 emitcode ("inc", "dptr");
3985 /* if the literal value of the right hand side
3986 is greater than 4 then it is not worth it */
3990 /* if the sizes are greater than 1 then we cannot */
3991 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3992 AOP_SIZE (IC_LEFT (ic)) > 1)
3995 /* we can if the aops of the left & result match or
3996 if they are in registers and the registers are the
3998 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4003 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4004 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4005 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4011 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4020 /*-----------------------------------------------------------------*/
4021 /* outBitAcc - output a bit in acc */
4022 /*-----------------------------------------------------------------*/
4024 outBitAcc (operand * result)
4026 symbol *tlbl = newiTempLabel (NULL);
4027 /* if the result is a bit */
4028 if (AOP_TYPE (result) == AOP_CRY)
4030 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4034 emitcode ("jz", "%05d$", tlbl->key + 100);
4035 emitcode ("mov", "a,%s", one);
4036 emitcode ("", "%05d$:", tlbl->key + 100);
4041 /*-----------------------------------------------------------------*/
4042 /* genPlusBits - generates code for addition of two bits */
4043 /*-----------------------------------------------------------------*/
4045 genPlusBits (iCode * ic)
4047 D(emitcode ("; genPlusBits",""));
4049 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4051 symbol *lbl = newiTempLabel (NULL);
4052 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4053 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4054 emitcode ("cpl", "c");
4055 emitcode ("", "%05d$:", (lbl->key + 100));
4056 outBitC (IC_RESULT (ic));
4060 emitcode ("clr", "a");
4061 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4062 emitcode ("rlc", "a");
4063 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4064 emitcode ("addc", "a,#0x00");
4065 outAcc (IC_RESULT (ic));
4070 /* This is the original version of this code.
4072 * This is being kept around for reference,
4073 * because I am not entirely sure I got it right...
4076 adjustArithmeticResult (iCode * ic)
4078 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4079 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4080 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4081 aopPut (IC_RESULT (ic),
4082 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4084 isOperandVolatile (IC_RESULT (ic), FALSE));
4086 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4087 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4088 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4089 aopPut (IC_RESULT (ic),
4090 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4092 isOperandVolatile (IC_RESULT (ic), FALSE));
4094 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4095 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4096 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4097 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4098 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4101 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4102 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4106 /* This is the pure and virtuous version of this code.
4107 * I'm pretty certain it's right, but not enough to toss the old
4111 adjustArithmeticResult (iCode * ic)
4113 if (opIsGptr (IC_RESULT (ic)) &&
4114 opIsGptr (IC_LEFT (ic)) &&
4115 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4117 aopPut (IC_RESULT (ic),
4118 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4120 isOperandVolatile (IC_RESULT (ic), FALSE));
4123 if (opIsGptr (IC_RESULT (ic)) &&
4124 opIsGptr (IC_RIGHT (ic)) &&
4125 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4127 aopPut (IC_RESULT (ic),
4128 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4130 isOperandVolatile (IC_RESULT (ic), FALSE));
4133 if (opIsGptr (IC_RESULT (ic)) &&
4134 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4135 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4136 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4137 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4140 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4141 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4146 /*-----------------------------------------------------------------*/
4147 /* genPlus - generates code for addition */
4148 /*-----------------------------------------------------------------*/
4150 genPlus (iCode * ic)
4152 int size, offset = 0;
4155 operand *leftOp, *rightOp;
4158 /* special cases :- */
4160 D(emitcode ("; genPlus",""));
4162 aopOp (IC_LEFT (ic), ic, FALSE);
4163 aopOp (IC_RIGHT (ic), ic, FALSE);
4164 aopOp (IC_RESULT (ic), ic, TRUE);
4166 /* if literal, literal on the right or
4167 if left requires ACC or right is already
4169 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4170 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4171 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4173 operand *t = IC_RIGHT (ic);
4174 IC_RIGHT (ic) = IC_LEFT (ic);
4178 /* if both left & right are in bit
4180 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4181 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4187 /* if left in bit space & right literal */
4188 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4189 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4191 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4192 /* if result in bit space */
4193 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4195 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4196 emitcode ("cpl", "c");
4197 outBitC (IC_RESULT (ic));
4201 size = getDataSize (IC_RESULT (ic));
4204 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4205 emitcode ("addc", "a,#00");
4206 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4212 /* if I can do an increment instead
4213 of add then GOOD for ME */
4214 if (genPlusIncr (ic) == TRUE)
4217 size = getDataSize (IC_RESULT (ic));
4218 leftOp = IC_LEFT(ic);
4219 rightOp = IC_RIGHT(ic);
4222 /* if this is an add for an array access
4223 at a 256 byte boundary */
4225 && AOP_TYPE (op) == AOP_IMMD
4227 && IS_SPEC (OP_SYM_ETYPE (op))
4228 && SPEC_ABSA (OP_SYM_ETYPE (op))
4229 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4232 D(emitcode ("; genPlus aligned array",""));
4233 aopPut (IC_RESULT (ic),
4234 aopGet (rightOp, 0, FALSE, FALSE),
4236 isOperandVolatile (IC_RESULT (ic), FALSE));
4238 if( 1 == getDataSize (IC_RIGHT (ic)) )
4240 aopPut (IC_RESULT (ic),
4241 aopGet (leftOp, 1, FALSE, FALSE),
4243 isOperandVolatile (IC_RESULT (ic), FALSE));
4247 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4248 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4249 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4254 /* if the lower bytes of a literal are zero skip the addition */
4255 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4257 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4258 (skip_bytes+1 < size))
4263 D(emitcode ("; genPlus shortcut",""));
4268 if( offset >= skip_bytes )
4270 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4273 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4275 emitcode("xch", "a,b");
4276 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4277 emitcode (add, "a,b");
4280 else if (aopGetUsesAcc (leftOp, offset))
4282 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4283 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4287 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4288 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4290 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4291 add = "addc"; /* further adds must propagate carry */
4295 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4296 isOperandVolatile (IC_RESULT (ic), FALSE))
4299 aopPut (IC_RESULT (ic),
4300 aopGet (leftOp, offset, FALSE, FALSE),
4302 isOperandVolatile (IC_RESULT (ic), FALSE));
4308 adjustArithmeticResult (ic);
4311 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4312 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4313 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4316 /*-----------------------------------------------------------------*/
4317 /* genMinusDec :- does subtraction with decrement if possible */
4318 /*-----------------------------------------------------------------*/
4320 genMinusDec (iCode * ic)
4322 unsigned int icount;
4323 unsigned int size = getDataSize (IC_RESULT (ic));
4325 /* will try to generate an increment */
4326 /* if the right side is not a literal
4328 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4331 /* if the literal value of the right hand side
4332 is greater than 4 then it is not worth it */
4333 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4336 D(emitcode ("; genMinusDec",""));
4338 /* if decrement >=16 bits in register or direct space */
4339 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4340 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4348 /* If the next instruction is a goto and the goto target
4349 * is <= 10 instructions previous to this, we can generate
4350 * jumps straight to that target.
4352 if (ic->next && ic->next->op == GOTO
4353 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4354 && labelRange <= 10)
4356 emitcode (";", "tail decrement optimized");
4357 tlbl = IC_LABEL (ic->next);
4362 tlbl = newiTempLabel (NULL);
4366 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4367 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4368 IS_AOP_PREG (IC_RESULT (ic)))
4369 emitcode ("cjne", "%s,#0xff,%05d$"
4370 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4374 emitcode ("mov", "a,#0xff");
4375 emitcode ("cjne", "a,%s,%05d$"
4376 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4379 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4382 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4383 IS_AOP_PREG (IC_RESULT (ic)))
4384 emitcode ("cjne", "%s,#0xff,%05d$"
4385 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4389 emitcode ("cjne", "a,%s,%05d$"
4390 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4393 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4397 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4398 IS_AOP_PREG (IC_RESULT (ic)))
4399 emitcode ("cjne", "%s,#0xff,%05d$"
4400 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4404 emitcode ("cjne", "a,%s,%05d$"
4405 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4408 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4412 emitcode ("", "%05d$:", tlbl->key + 100);
4417 /* if the sizes are greater than 1 then we cannot */
4418 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4419 AOP_SIZE (IC_LEFT (ic)) > 1)
4422 /* we can if the aops of the left & result match or
4423 if they are in registers and the registers are the
4425 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4429 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4437 /*-----------------------------------------------------------------*/
4438 /* addSign - complete with sign */
4439 /*-----------------------------------------------------------------*/
4441 addSign (operand * result, int offset, int sign)
4443 int size = (getDataSize (result) - offset);
4448 emitcode ("rlc", "a");
4449 emitcode ("subb", "a,acc");
4451 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4455 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4459 /*-----------------------------------------------------------------*/
4460 /* genMinusBits - generates code for subtraction of two bits */
4461 /*-----------------------------------------------------------------*/
4463 genMinusBits (iCode * ic)
4465 symbol *lbl = newiTempLabel (NULL);
4467 D(emitcode ("; genMinusBits",""));
4469 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4471 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4472 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4473 emitcode ("cpl", "c");
4474 emitcode ("", "%05d$:", (lbl->key + 100));
4475 outBitC (IC_RESULT (ic));
4479 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4480 emitcode ("subb", "a,acc");
4481 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4482 emitcode ("inc", "a");
4483 emitcode ("", "%05d$:", (lbl->key + 100));
4484 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4485 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4489 /*-----------------------------------------------------------------*/
4490 /* genMinus - generates code for subtraction */
4491 /*-----------------------------------------------------------------*/
4493 genMinus (iCode * ic)
4495 int size, offset = 0;
4497 D(emitcode ("; genMinus",""));
4499 aopOp (IC_LEFT (ic), ic, FALSE);
4500 aopOp (IC_RIGHT (ic), ic, FALSE);
4501 aopOp (IC_RESULT (ic), ic, TRUE);
4503 /* special cases :- */
4504 /* if both left & right are in bit space */
4505 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4506 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4512 /* if I can do an decrement instead
4513 of subtract then GOOD for ME */
4514 if (genMinusDec (ic) == TRUE)
4517 size = getDataSize (IC_RESULT (ic));
4519 /* if literal, add a,#-lit, else normal subb */
4520 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4522 unsigned long lit = 0L;
4523 bool useCarry = FALSE;
4525 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4530 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4532 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4533 if (!offset && !size && lit== (unsigned long) -1)
4535 emitcode ("dec", "a");
4539 /* first add without previous c */
4540 emitcode ("add", "a,#0x%02x",
4541 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4546 emitcode ("addc", "a,#0x%02x",
4547 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4549 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4553 /* no need to add zeroes */
4554 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4556 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4557 offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4565 operand *leftOp, *rightOp;
4567 leftOp = IC_LEFT(ic);
4568 rightOp = IC_RIGHT(ic);
4572 if (aopGetUsesAcc(rightOp, offset)) {
4573 if (aopGetUsesAcc(leftOp, offset)) {
4576 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4578 emitcode ("mov", "b,a");
4581 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4582 emitcode ("subb", "a,b");
4585 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4586 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4588 emitcode( "setb", "c");
4590 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4591 emitcode("cpl", "a");
4594 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4597 emitcode ("subb", "a,%s",
4598 aopGet(rightOp, offset, FALSE, TRUE));
4601 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4606 adjustArithmeticResult (ic);
4609 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4610 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4611 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4615 /*-----------------------------------------------------------------*/
4616 /* genMultbits :- multiplication of bits */
4617 /*-----------------------------------------------------------------*/
4619 genMultbits (operand * left,
4623 D(emitcode ("; genMultbits",""));
4625 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4626 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4630 /*-----------------------------------------------------------------*/
4631 /* genMultOneByte : 8*8=8/16 bit multiplication */
4632 /*-----------------------------------------------------------------*/
4634 genMultOneByte (operand * left,
4639 int size = AOP_SIZE (result);
4640 bool runtimeSign, compiletimeSign;
4641 bool lUnsigned, rUnsigned, pushedB;
4643 D(emitcode ("; genMultOneByte",""));
4645 if (size < 1 || size > 2)
4647 /* this should never happen */
4648 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4649 AOP_SIZE(result), __FILE__, lineno);
4653 /* (if two literals: the value is computed before) */
4654 /* if one literal, literal on the right */
4655 if (AOP_TYPE (left) == AOP_LIT)
4660 /* emitcode (";", "swapped left and right"); */
4662 /* if no literal, unsigned on the right: shorter code */
4663 if ( AOP_TYPE (right) != AOP_LIT
4664 && SPEC_USIGN (getSpec (operandType (left))))
4671 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4672 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4676 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4677 no need to take care about the signedness! */
4678 || (lUnsigned && rUnsigned))
4680 /* just an unsigned 8 * 8 = 8 multiply
4682 /* emitcode (";","unsigned"); */
4683 /* TODO: check for accumulator clash between left & right aops? */
4685 if (AOP_TYPE (right) == AOP_LIT)
4687 /* moving to accumulator first helps peepholes */
4688 MOVA (aopGet (left, 0, FALSE, FALSE));
4689 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4693 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4694 MOVA (aopGet (left, 0, FALSE, FALSE));
4697 emitcode ("mul", "ab");
4698 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4700 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4706 /* we have to do a signed multiply */
4707 /* emitcode (";", "signed"); */
4709 /* now sign adjust for both left & right */
4711 /* let's see what's needed: */
4712 /* apply negative sign during runtime */
4713 runtimeSign = FALSE;
4714 /* negative sign from literals */
4715 compiletimeSign = FALSE;
4719 if (AOP_TYPE(left) == AOP_LIT)
4721 /* signed literal */
4722 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4724 compiletimeSign = TRUE;
4727 /* signed but not literal */
4733 if (AOP_TYPE(right) == AOP_LIT)
4735 /* signed literal */
4736 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4738 compiletimeSign ^= TRUE;
4741 /* signed but not literal */
4745 /* initialize F0, which stores the runtime sign */
4748 if (compiletimeSign)
4749 emitcode ("setb", "F0"); /* set sign flag */
4751 emitcode ("clr", "F0"); /* reset sign flag */
4754 /* save the signs of the operands */
4755 if (AOP_TYPE(right) == AOP_LIT)
4757 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4759 if (!rUnsigned && val < 0)
4760 emitcode ("mov", "b,#0x%02x", -val);
4762 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4764 else /* ! literal */
4766 if (rUnsigned) /* emitcode (";", "signed"); */
4768 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4771 MOVA (aopGet (right, 0, FALSE, FALSE));
4772 lbl = newiTempLabel (NULL);
4773 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4774 emitcode ("cpl", "F0"); /* complement sign flag */
4775 emitcode ("cpl", "a"); /* 2's complement */
4776 emitcode ("inc", "a");
4777 emitcode ("", "%05d$:", (lbl->key + 100));
4778 emitcode ("mov", "b,a");
4782 if (AOP_TYPE(left) == AOP_LIT)
4784 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4786 if (!lUnsigned && val < 0)
4787 emitcode ("mov", "a,#0x%02x", -val);
4789 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4791 else /* ! literal */
4793 MOVA (aopGet (left, 0, FALSE, FALSE));
4797 lbl = newiTempLabel (NULL);
4798 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4799 emitcode ("cpl", "F0"); /* complement sign flag */
4800 emitcode ("cpl", "a"); /* 2's complement */
4801 emitcode ("inc", "a");
4802 emitcode ("", "%05d$:", (lbl->key + 100));
4806 /* now the multiplication */
4807 emitcode ("mul", "ab");
4808 if (runtimeSign || compiletimeSign)
4810 lbl = newiTempLabel (NULL);
4812 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4813 emitcode ("cpl", "a"); /* lsb 2's complement */
4815 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4818 emitcode ("add", "a,#1"); /* this sets carry flag */
4819 emitcode ("xch", "a,b");
4820 emitcode ("cpl", "a"); /* msb 2's complement */
4821 emitcode ("addc", "a,#0");
4822 emitcode ("xch", "a,b");
4824 emitcode ("", "%05d$:", (lbl->key + 100));
4826 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4828 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4833 /*-----------------------------------------------------------------*/
4834 /* genMult - generates code for multiplication */
4835 /*-----------------------------------------------------------------*/
4837 genMult (iCode * ic)
4839 operand *left = IC_LEFT (ic);
4840 operand *right = IC_RIGHT (ic);
4841 operand *result = IC_RESULT (ic);
4843 D(emitcode ("; genMult",""));
4845 /* assign the amsops */
4846 aopOp (left, ic, FALSE);
4847 aopOp (right, ic, FALSE);
4848 aopOp (result, ic, TRUE);
4850 /* special cases first */
4852 if (AOP_TYPE (left) == AOP_CRY &&
4853 AOP_TYPE (right) == AOP_CRY)
4855 genMultbits (left, right, result);
4859 /* if both are of size == 1 */
4860 #if 0 // one of them can be a sloc shared with the result
4861 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4863 if (getSize(operandType(left)) == 1 &&
4864 getSize(operandType(right)) == 1)
4867 genMultOneByte (left, right, result);
4871 /* should have been converted to function call */
4872 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4873 getSize(OP_SYMBOL(right)->type));
4877 freeAsmop (result, NULL, ic, TRUE);
4878 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4879 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4882 /*-----------------------------------------------------------------*/
4883 /* genDivbits :- division of bits */
4884 /*-----------------------------------------------------------------*/
4886 genDivbits (operand * left,
4893 D(emitcode ("; genDivbits",""));
4897 /* the result must be bit */
4898 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4899 l = aopGet (left, 0, FALSE, FALSE);
4903 emitcode ("div", "ab");
4904 emitcode ("rrc", "a");
4908 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4911 /*-----------------------------------------------------------------*/
4912 /* genDivOneByte : 8 bit division */
4913 /*-----------------------------------------------------------------*/
4915 genDivOneByte (operand * left,
4919 bool lUnsigned, rUnsigned, pushedB;
4920 bool runtimeSign, compiletimeSign;
4924 D(emitcode ("; genDivOneByte",""));
4926 /* Why is it necessary that genDivOneByte() can return an int result?
4929 volatile unsigned char uc;
4930 volatile signed char sc1, sc2;
4943 In all cases a one byte result would overflow, the following cast to int
4944 would return the wrong result.
4946 Two possible solution:
4947 a) cast operands to int, if ((unsigned) / (signed)) or
4948 ((signed) / (signed))
4949 b) return an 16 bit signed int; this is what we're doing here!
4952 size = AOP_SIZE (result) - 1;
4954 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4955 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4959 /* signed or unsigned */
4960 if (lUnsigned && rUnsigned)
4962 /* unsigned is easy */
4963 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4964 MOVA (aopGet (left, 0, FALSE, FALSE));
4965 emitcode ("div", "ab");
4966 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4968 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4974 /* signed is a little bit more difficult */
4976 /* now sign adjust for both left & right */
4978 /* let's see what's needed: */
4979 /* apply negative sign during runtime */
4980 runtimeSign = FALSE;
4981 /* negative sign from literals */
4982 compiletimeSign = FALSE;
4986 if (AOP_TYPE(left) == AOP_LIT)
4988 /* signed literal */
4989 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4991 compiletimeSign = TRUE;
4994 /* signed but not literal */
5000 if (AOP_TYPE(right) == AOP_LIT)
5002 /* signed literal */
5003 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5005 compiletimeSign ^= TRUE;
5008 /* signed but not literal */
5012 /* initialize F0, which stores the runtime sign */
5015 if (compiletimeSign)
5016 emitcode ("setb", "F0"); /* set sign flag */
5018 emitcode ("clr", "F0"); /* reset sign flag */
5021 /* save the signs of the operands */
5022 if (AOP_TYPE(right) == AOP_LIT)
5024 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5026 if (!rUnsigned && val < 0)
5027 emitcode ("mov", "b,#0x%02x", -val);
5029 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5031 else /* ! literal */
5034 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5037 MOVA (aopGet (right, 0, FALSE, FALSE));
5038 lbl = newiTempLabel (NULL);
5039 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5040 emitcode ("cpl", "F0"); /* complement sign flag */
5041 emitcode ("cpl", "a"); /* 2's complement */
5042 emitcode ("inc", "a");
5043 emitcode ("", "%05d$:", (lbl->key + 100));
5044 emitcode ("mov", "b,a");
5048 if (AOP_TYPE(left) == AOP_LIT)
5050 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5052 if (!lUnsigned && val < 0)
5053 emitcode ("mov", "a,#0x%02x", -val);
5055 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5057 else /* ! literal */
5059 MOVA (aopGet (left, 0, FALSE, FALSE));
5063 lbl = newiTempLabel (NULL);
5064 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5065 emitcode ("cpl", "F0"); /* complement sign flag */
5066 emitcode ("cpl", "a"); /* 2's complement */
5067 emitcode ("inc", "a");
5068 emitcode ("", "%05d$:", (lbl->key + 100));
5072 /* now the division */
5073 emitcode ("div", "ab");
5075 if (runtimeSign || compiletimeSign)
5077 lbl = newiTempLabel (NULL);
5079 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5080 emitcode ("cpl", "a"); /* lsb 2's complement */
5081 emitcode ("inc", "a");
5082 emitcode ("", "%05d$:", (lbl->key + 100));
5084 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5087 /* msb is 0x00 or 0xff depending on the sign */
5090 emitcode ("mov", "c,F0");
5091 emitcode ("subb", "a,acc");
5093 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5095 else /* compiletimeSign */
5097 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5102 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5104 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5110 /*-----------------------------------------------------------------*/
5111 /* genDiv - generates code for division */
5112 /*-----------------------------------------------------------------*/
5116 operand *left = IC_LEFT (ic);
5117 operand *right = IC_RIGHT (ic);
5118 operand *result = IC_RESULT (ic);
5120 D(emitcode ("; genDiv",""));
5122 /* assign the amsops */
5123 aopOp (left, ic, FALSE);
5124 aopOp (right, ic, FALSE);
5125 aopOp (result, ic, TRUE);
5127 /* special cases first */
5129 if (AOP_TYPE (left) == AOP_CRY &&
5130 AOP_TYPE (right) == AOP_CRY)
5132 genDivbits (left, right, result);
5136 /* if both are of size == 1 */
5137 if (AOP_SIZE (left) == 1 &&
5138 AOP_SIZE (right) == 1)
5140 genDivOneByte (left, right, result);
5144 /* should have been converted to function call */
5147 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5148 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5149 freeAsmop (result, NULL, ic, TRUE);
5152 /*-----------------------------------------------------------------*/
5153 /* genModbits :- modulus of bits */
5154 /*-----------------------------------------------------------------*/
5156 genModbits (operand * left,
5163 D(emitcode ("; genModbits",""));
5167 /* the result must be bit */
5168 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5169 l = aopGet (left, 0, FALSE, FALSE);
5173 emitcode ("div", "ab");
5174 emitcode ("mov", "a,b");
5175 emitcode ("rrc", "a");
5179 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5182 /*-----------------------------------------------------------------*/
5183 /* genModOneByte : 8 bit modulus */
5184 /*-----------------------------------------------------------------*/
5186 genModOneByte (operand * left,
5190 bool lUnsigned, rUnsigned, pushedB;
5191 bool runtimeSign, compiletimeSign;
5195 D(emitcode ("; genModOneByte",""));
5197 size = AOP_SIZE (result) - 1;
5199 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5200 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5202 /* if right is a literal, check it for 2^n */
5203 if (AOP_TYPE(right) == AOP_LIT)
5205 unsigned char val = abs((int) operandLitValue(right));
5206 symbol *lbl2 = NULL;
5210 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5219 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5220 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5221 /* because iCode should have been changed to genAnd */
5222 /* see file "SDCCopt.c", function "convertToFcall()" */
5224 MOVA (aopGet (left, 0, FALSE, FALSE));
5225 emitcode ("mov", "c,acc.7");
5226 emitcode ("anl", "a,#0x%02x", val - 1);
5227 lbl = newiTempLabel (NULL);
5228 emitcode ("jz", "%05d$", (lbl->key + 100));
5229 emitcode ("jnc", "%05d$", (lbl->key + 100));
5230 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5236 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5238 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5239 lbl2 = newiTempLabel (NULL);
5240 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5242 emitcode ("", "%05d$:", (lbl->key + 100));
5243 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5245 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5248 emitcode ("", "%05d$:", (lbl2->key + 100));
5259 /* signed or unsigned */
5260 if (lUnsigned && rUnsigned)
5262 /* unsigned is easy */
5263 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5264 MOVA (aopGet (left, 0, FALSE, FALSE));
5265 emitcode ("div", "ab");
5266 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5268 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5274 /* signed is a little bit more difficult */
5276 /* now sign adjust for both left & right */
5278 /* modulus: sign of the right operand has no influence on the result! */
5279 if (AOP_TYPE(right) == AOP_LIT)
5281 signed char val = (char) operandLitValue(right);
5283 if (!rUnsigned && val < 0)
5284 emitcode ("mov", "b,#0x%02x", -val);
5286 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5288 else /* not literal */
5291 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5294 MOVA (aopGet (right, 0, FALSE, FALSE));
5295 lbl = newiTempLabel (NULL);
5296 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5297 emitcode ("cpl", "a"); /* 2's complement */
5298 emitcode ("inc", "a");
5299 emitcode ("", "%05d$:", (lbl->key + 100));
5300 emitcode ("mov", "b,a");
5304 /* let's see what's needed: */
5305 /* apply negative sign during runtime */
5306 runtimeSign = FALSE;
5307 /* negative sign from literals */
5308 compiletimeSign = FALSE;
5310 /* sign adjust left side */
5311 if (AOP_TYPE(left) == AOP_LIT)
5313 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5315 if (!lUnsigned && val < 0)
5317 compiletimeSign = TRUE; /* set sign flag */
5318 emitcode ("mov", "a,#0x%02x", -val);
5321 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5323 else /* ! literal */
5325 MOVA (aopGet (left, 0, FALSE, FALSE));
5330 emitcode ("clr", "F0"); /* clear sign flag */
5332 lbl = newiTempLabel (NULL);
5333 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5334 emitcode ("setb", "F0"); /* set sign flag */
5335 emitcode ("cpl", "a"); /* 2's complement */
5336 emitcode ("inc", "a");
5337 emitcode ("", "%05d$:", (lbl->key + 100));
5341 /* now the modulus */
5342 emitcode ("div", "ab");
5344 if (runtimeSign || compiletimeSign)
5346 emitcode ("mov", "a,b");
5347 lbl = newiTempLabel (NULL);
5349 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5350 emitcode ("cpl", "a"); /* 2's complement */
5351 emitcode ("inc", "a");
5352 emitcode ("", "%05d$:", (lbl->key + 100));
5354 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5357 /* msb is 0x00 or 0xff depending on the sign */
5360 emitcode ("mov", "c,F0");
5361 emitcode ("subb", "a,acc");
5363 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5365 else /* compiletimeSign */
5367 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5372 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5374 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5380 /*-----------------------------------------------------------------*/
5381 /* genMod - generates code for division */
5382 /*-----------------------------------------------------------------*/
5386 operand *left = IC_LEFT (ic);
5387 operand *right = IC_RIGHT (ic);
5388 operand *result = IC_RESULT (ic);
5390 D(emitcode ("; genMod",""));
5392 /* assign the asmops */
5393 aopOp (left, ic, FALSE);
5394 aopOp (right, ic, FALSE);
5395 aopOp (result, ic, TRUE);
5397 /* special cases first */
5399 if (AOP_TYPE (left) == AOP_CRY &&
5400 AOP_TYPE (right) == AOP_CRY)
5402 genModbits (left, right, result);
5406 /* if both are of size == 1 */
5407 if (AOP_SIZE (left) == 1 &&
5408 AOP_SIZE (right) == 1)
5410 genModOneByte (left, right, result);
5414 /* should have been converted to function call */
5418 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5419 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5420 freeAsmop (result, NULL, ic, TRUE);
5423 /*-----------------------------------------------------------------*/
5424 /* genIfxJump :- will create a jump depending on the ifx */
5425 /*-----------------------------------------------------------------*/
5427 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5430 symbol *tlbl = newiTempLabel (NULL);
5433 D(emitcode ("; genIfxJump",""));
5435 /* if true label then we jump if condition
5439 jlbl = IC_TRUE (ic);
5440 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5441 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5445 /* false label is present */
5446 jlbl = IC_FALSE (ic);
5447 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5448 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5450 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5451 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5453 emitcode (inst, "%05d$", tlbl->key + 100);
5454 freeForBranchAsmop (result);
5455 freeForBranchAsmop (right);
5456 freeForBranchAsmop (left);
5457 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5458 emitcode ("", "%05d$:", tlbl->key + 100);
5460 /* mark the icode as generated */
5464 /*-----------------------------------------------------------------*/
5465 /* genCmp :- greater or less than comparison */
5466 /*-----------------------------------------------------------------*/
5468 genCmp (operand * left, operand * right,
5469 operand * result, iCode * ifx, int sign, iCode *ic)
5471 int size, offset = 0;
5472 unsigned long lit = 0L;
5475 D(emitcode ("; genCmp",""));
5477 /* if left & right are bit variables */
5478 if (AOP_TYPE (left) == AOP_CRY &&
5479 AOP_TYPE (right) == AOP_CRY)
5481 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5482 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5486 /* subtract right from left if at the
5487 end the carry flag is set then we know that
5488 left is greater than right */
5489 size = max (AOP_SIZE (left), AOP_SIZE (right));
5491 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5492 if ((size == 1) && !sign &&
5493 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5495 symbol *lbl = newiTempLabel (NULL);
5496 emitcode ("cjne", "%s,%s,%05d$",
5497 aopGet (left, offset, FALSE, FALSE),
5498 aopGet (right, offset, FALSE, FALSE),
5500 emitcode ("", "%05d$:", lbl->key + 100);
5504 if (AOP_TYPE (right) == AOP_LIT)
5506 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5507 /* optimize if(x < 0) or if(x >= 0) */
5516 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5517 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5519 genIfxJump (ifx, "acc.7", left, right, result);
5520 freeAsmop (right, NULL, ic, TRUE);
5521 freeAsmop (left, NULL, ic, TRUE);
5526 emitcode ("rlc", "a");
5534 bool pushedB = FALSE;
5535 rightInB = aopGetUsesAcc(right, offset);
5539 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5541 MOVA (aopGet (left, offset, FALSE, FALSE));
5542 if (sign && size == 0)
5544 emitcode ("xrl", "a,#0x80");
5545 if (AOP_TYPE (right) == AOP_LIT)
5547 unsigned long lit = (unsigned long)
5548 floatFromVal (AOP (right)->aopu.aop_lit);
5549 emitcode ("subb", "a,#0x%02x",
5550 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5558 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5560 emitcode ("xrl", "b,#0x80");
5561 emitcode ("subb", "a,b");
5567 emitcode ("subb", "a,b");
5569 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5579 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5580 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5581 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5587 /* if the result is used in the next
5588 ifx conditional branch then generate
5589 code a little differently */
5591 genIfxJump (ifx, "c", NULL, NULL, result);
5594 /* leave the result in acc */
5598 /*-----------------------------------------------------------------*/
5599 /* genCmpGt :- greater than comparison */
5600 /*-----------------------------------------------------------------*/
5602 genCmpGt (iCode * ic, iCode * ifx)
5604 operand *left, *right, *result;
5605 sym_link *letype, *retype;
5608 D(emitcode ("; genCmpGt",""));
5610 left = IC_LEFT (ic);
5611 right = IC_RIGHT (ic);
5612 result = IC_RESULT (ic);
5614 letype = getSpec (operandType (left));
5615 retype = getSpec (operandType (right));
5616 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5617 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5618 /* assign the amsops */
5619 aopOp (left, ic, FALSE);
5620 aopOp (right, ic, FALSE);
5621 aopOp (result, ic, TRUE);
5623 genCmp (right, left, result, ifx, sign, ic);
5625 freeAsmop (result, NULL, ic, TRUE);
5628 /*-----------------------------------------------------------------*/
5629 /* genCmpLt - less than comparisons */
5630 /*-----------------------------------------------------------------*/
5632 genCmpLt (iCode * ic, iCode * ifx)
5634 operand *left, *right, *result;
5635 sym_link *letype, *retype;
5638 D(emitcode ("; genCmpLt",""));
5640 left = IC_LEFT (ic);
5641 right = IC_RIGHT (ic);
5642 result = IC_RESULT (ic);
5644 letype = getSpec (operandType (left));
5645 retype = getSpec (operandType (right));
5646 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5647 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5648 /* assign the amsops */
5649 aopOp (left, ic, FALSE);
5650 aopOp (right, ic, FALSE);
5651 aopOp (result, ic, TRUE);
5653 genCmp (left, right, result, ifx, sign, ic);
5655 freeAsmop (result, NULL, ic, TRUE);
5658 /*-----------------------------------------------------------------*/
5659 /* gencjneshort - compare and jump if not equal */
5660 /*-----------------------------------------------------------------*/
5662 gencjneshort (operand * left, operand * right, symbol * lbl)
5664 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5666 unsigned long lit = 0L;
5668 /* if the left side is a literal or
5669 if the right is in a pointer register and left
5671 if ((AOP_TYPE (left) == AOP_LIT) ||
5672 (AOP_TYPE (left) == AOP_IMMD) ||
5673 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5680 if (AOP_TYPE (right) == AOP_LIT)
5681 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5683 /* if the right side is a literal then anything goes */
5684 if (AOP_TYPE (right) == AOP_LIT &&
5685 AOP_TYPE (left) != AOP_DIR &&
5686 AOP_TYPE (left) != AOP_IMMD)
5690 emitcode ("cjne", "%s,%s,%05d$",
5691 aopGet (left, offset, FALSE, FALSE),
5692 aopGet (right, offset, FALSE, FALSE),
5698 /* if the right side is in a register or in direct space or
5699 if the left is a pointer register & right is not */
5700 else if (AOP_TYPE (right) == AOP_REG ||
5701 AOP_TYPE (right) == AOP_DIR ||
5702 AOP_TYPE (right) == AOP_LIT ||
5703 AOP_TYPE (right) == AOP_IMMD ||
5704 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5705 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5709 MOVA (aopGet (left, offset, FALSE, FALSE));
5710 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5711 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5712 emitcode ("jnz", "%05d$", lbl->key + 100);
5714 emitcode ("cjne", "a,%s,%05d$",
5715 aopGet (right, offset, FALSE, TRUE),
5722 /* right is a pointer reg need both a & b */
5726 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5727 wassertl(!BINUSE, "B was in use");
5728 l = aopGet (left, offset, FALSE, FALSE);
5729 if (strcmp (l, "b"))
5730 emitcode ("mov", "b,%s", l);
5731 MOVA (aopGet (right, offset, FALSE, FALSE));
5732 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5738 /*-----------------------------------------------------------------*/
5739 /* gencjne - compare and jump if not equal */
5740 /*-----------------------------------------------------------------*/
5742 gencjne (operand * left, operand * right, symbol * lbl)
5744 symbol *tlbl = newiTempLabel (NULL);
5746 gencjneshort (left, right, lbl);
5748 emitcode ("mov", "a,%s", one);
5749 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5750 emitcode ("", "%05d$:", lbl->key + 100);
5751 emitcode ("clr", "a");
5752 emitcode ("", "%05d$:", tlbl->key + 100);
5755 /*-----------------------------------------------------------------*/
5756 /* genCmpEq - generates code for equal to */
5757 /*-----------------------------------------------------------------*/
5759 genCmpEq (iCode * ic, iCode * ifx)
5761 operand *left, *right, *result;
5763 D(emitcode ("; genCmpEq",""));
5765 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5766 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5767 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5769 /* if literal, literal on the right or
5770 if the right is in a pointer register and left
5772 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5773 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5775 operand *t = IC_RIGHT (ic);
5776 IC_RIGHT (ic) = IC_LEFT (ic);
5780 if (ifx && !AOP_SIZE (result))
5783 /* if they are both bit variables */
5784 if (AOP_TYPE (left) == AOP_CRY &&
5785 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5787 if (AOP_TYPE (right) == AOP_LIT)
5789 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5792 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5793 emitcode ("cpl", "c");
5797 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5801 emitcode ("clr", "c");
5803 /* AOP_TYPE(right) == AOP_CRY */
5807 symbol *lbl = newiTempLabel (NULL);
5808 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5809 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5810 emitcode ("cpl", "c");
5811 emitcode ("", "%05d$:", (lbl->key + 100));
5813 /* if true label then we jump if condition
5815 tlbl = newiTempLabel (NULL);
5818 emitcode ("jnc", "%05d$", tlbl->key + 100);
5819 freeForBranchAsmop (result);
5820 freeForBranchAsmop (right);
5821 freeForBranchAsmop (left);
5822 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5826 emitcode ("jc", "%05d$", tlbl->key + 100);
5827 freeForBranchAsmop (result);
5828 freeForBranchAsmop (right);
5829 freeForBranchAsmop (left);
5830 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5832 emitcode ("", "%05d$:", tlbl->key + 100);
5836 tlbl = newiTempLabel (NULL);
5837 gencjneshort (left, right, tlbl);
5840 freeForBranchAsmop (result);
5841 freeForBranchAsmop (right);
5842 freeForBranchAsmop (left);
5843 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5844 emitcode ("", "%05d$:", tlbl->key + 100);
5848 symbol *lbl = newiTempLabel (NULL);
5849 emitcode ("sjmp", "%05d$", lbl->key + 100);
5850 emitcode ("", "%05d$:", tlbl->key + 100);
5851 freeForBranchAsmop (result);
5852 freeForBranchAsmop (right);
5853 freeForBranchAsmop (left);
5854 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5855 emitcode ("", "%05d$:", lbl->key + 100);
5858 /* mark the icode as generated */
5863 /* if they are both bit variables */
5864 if (AOP_TYPE (left) == AOP_CRY &&
5865 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5867 if (AOP_TYPE (right) == AOP_LIT)
5869 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5872 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5873 emitcode ("cpl", "c");
5877 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5881 emitcode ("clr", "c");
5883 /* AOP_TYPE(right) == AOP_CRY */
5887 symbol *lbl = newiTempLabel (NULL);
5888 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5889 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5890 emitcode ("cpl", "c");
5891 emitcode ("", "%05d$:", (lbl->key + 100));
5894 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5901 genIfxJump (ifx, "c", left, right, result);
5904 /* if the result is used in an arithmetic operation
5905 then put the result in place */
5910 gencjne (left, right, newiTempLabel (NULL));
5911 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5913 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5918 genIfxJump (ifx, "a", left, right, result);
5921 /* if the result is used in an arithmetic operation
5922 then put the result in place */
5923 if (AOP_TYPE (result) != AOP_CRY)
5925 /* leave the result in acc */
5929 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5930 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5931 freeAsmop (result, NULL, ic, TRUE);
5934 /*-----------------------------------------------------------------*/
5935 /* ifxForOp - returns the icode containing the ifx for operand */
5936 /*-----------------------------------------------------------------*/
5938 ifxForOp (operand * op, iCode * ic)
5940 /* if true symbol then needs to be assigned */
5941 if (IS_TRUE_SYMOP (op))
5944 /* if this has register type condition and
5945 the next instruction is ifx with the same operand
5946 and live to of the operand is upto the ifx only then */
5948 ic->next->op == IFX &&
5949 IC_COND (ic->next)->key == op->key &&
5950 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5956 /*-----------------------------------------------------------------*/
5957 /* hasInc - operand is incremented before any other use */
5958 /*-----------------------------------------------------------------*/
5960 hasInc (operand *op, iCode *ic,int osize)
5962 sym_link *type = operandType(op);
5963 sym_link *retype = getSpec (type);
5964 iCode *lic = ic->next;
5967 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5968 if (!IS_SYMOP(op)) return NULL;
5970 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5971 if (IS_AGGREGATE(type->next)) return NULL;
5972 if (osize != (isize = getSize(type->next))) return NULL;
5975 /* if operand of the form op = op + <sizeof *op> */
5976 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5977 isOperandEqual(IC_RESULT(lic),op) &&
5978 isOperandLiteral(IC_RIGHT(lic)) &&
5979 operandLitValue(IC_RIGHT(lic)) == isize) {
5982 /* if the operand used or deffed */
5983 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5986 /* if GOTO or IFX */
5987 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5993 /*-----------------------------------------------------------------*/
5994 /* genAndOp - for && operation */
5995 /*-----------------------------------------------------------------*/
5997 genAndOp (iCode * ic)
5999 operand *left, *right, *result;
6002 D(emitcode ("; genAndOp",""));
6004 /* note here that && operations that are in an
6005 if statement are taken away by backPatchLabels
6006 only those used in arthmetic operations remain */
6007 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6008 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6009 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6011 /* if both are bit variables */
6012 if (AOP_TYPE (left) == AOP_CRY &&
6013 AOP_TYPE (right) == AOP_CRY)
6015 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6016 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6021 tlbl = newiTempLabel (NULL);
6023 emitcode ("jz", "%05d$", tlbl->key + 100);
6025 emitcode ("", "%05d$:", tlbl->key + 100);
6029 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6030 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6031 freeAsmop (result, NULL, ic, TRUE);
6035 /*-----------------------------------------------------------------*/
6036 /* genOrOp - for || operation */
6037 /*-----------------------------------------------------------------*/
6039 genOrOp (iCode * ic)
6041 operand *left, *right, *result;
6044 D(emitcode ("; genOrOp",""));
6046 /* note here that || operations that are in an
6047 if statement are taken away by backPatchLabels
6048 only those used in arthmetic operations remain */
6049 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6050 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6051 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6053 /* if both are bit variables */
6054 if (AOP_TYPE (left) == AOP_CRY &&
6055 AOP_TYPE (right) == AOP_CRY)
6057 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6058 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6063 tlbl = newiTempLabel (NULL);
6065 emitcode ("jnz", "%05d$", tlbl->key + 100);
6067 emitcode ("", "%05d$:", tlbl->key + 100);
6071 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6072 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6073 freeAsmop (result, NULL, ic, TRUE);
6076 /*-----------------------------------------------------------------*/
6077 /* isLiteralBit - test if lit == 2^n */
6078 /*-----------------------------------------------------------------*/
6080 isLiteralBit (unsigned long lit)
6082 unsigned long pw[32] =
6083 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6084 0x100L, 0x200L, 0x400L, 0x800L,
6085 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6086 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6087 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6088 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6089 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6092 for (idx = 0; idx < 32; idx++)
6098 /*-----------------------------------------------------------------*/
6099 /* continueIfTrue - */
6100 /*-----------------------------------------------------------------*/
6102 continueIfTrue (iCode * ic)
6105 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6109 /*-----------------------------------------------------------------*/
6111 /*-----------------------------------------------------------------*/
6113 jumpIfTrue (iCode * ic)
6116 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6120 /*-----------------------------------------------------------------*/
6121 /* jmpTrueOrFalse - */
6122 /*-----------------------------------------------------------------*/
6124 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6126 // ugly but optimized by peephole
6129 symbol *nlbl = newiTempLabel (NULL);
6130 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6131 emitcode ("", "%05d$:", tlbl->key + 100);
6132 freeForBranchAsmop (result);
6133 freeForBranchAsmop (right);
6134 freeForBranchAsmop (left);
6135 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6136 emitcode ("", "%05d$:", nlbl->key + 100);
6140 freeForBranchAsmop (result);
6141 freeForBranchAsmop (right);
6142 freeForBranchAsmop (left);
6143 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6144 emitcode ("", "%05d$:", tlbl->key + 100);
6149 /*-----------------------------------------------------------------*/
6150 /* genAnd - code for and */
6151 /*-----------------------------------------------------------------*/
6153 genAnd (iCode * ic, iCode * ifx)
6155 operand *left, *right, *result;
6156 int size, offset = 0;
6157 unsigned long lit = 0L;
6161 D(emitcode ("; genAnd",""));
6163 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6164 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6165 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6168 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6170 AOP_TYPE (left), AOP_TYPE (right));
6171 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6173 AOP_SIZE (left), AOP_SIZE (right));
6176 /* if left is a literal & right is not then exchange them */
6177 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6178 AOP_NEEDSACC (left))
6180 operand *tmp = right;
6185 /* if result = right then exchange left and right */
6186 if (sameRegs (AOP (result), AOP (right)))
6188 operand *tmp = right;
6193 /* if right is bit then exchange them */
6194 if (AOP_TYPE (right) == AOP_CRY &&
6195 AOP_TYPE (left) != AOP_CRY)
6197 operand *tmp = right;
6201 if (AOP_TYPE (right) == AOP_LIT)
6202 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6204 size = AOP_SIZE (result);
6207 // result = bit & yy;
6208 if (AOP_TYPE (left) == AOP_CRY)
6210 // c = bit & literal;
6211 if (AOP_TYPE (right) == AOP_LIT)
6215 if (size && sameRegs (AOP (result), AOP (left)))
6218 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6223 if (size && (AOP_TYPE (result) == AOP_CRY))
6225 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6228 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6233 emitcode ("clr", "c");
6238 if (AOP_TYPE (right) == AOP_CRY)
6241 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6242 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6247 MOVA (aopGet (right, 0, FALSE, FALSE));
6249 emitcode ("rrc", "a");
6250 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6258 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6259 genIfxJump (ifx, "c", left, right, result);
6263 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6264 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6265 if ((AOP_TYPE (right) == AOP_LIT) &&
6266 (AOP_TYPE (result) == AOP_CRY) &&
6267 (AOP_TYPE (left) != AOP_CRY))
6269 int posbit = isLiteralBit (lit);
6274 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6278 switch (posbit & 0x07)
6280 case 0: emitcode ("rrc", "a");
6282 case 7: emitcode ("rlc", "a");
6284 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6293 SNPRINTF (buffer, sizeof(buffer),
6294 "acc.%d", posbit & 0x07);
6295 genIfxJump (ifx, buffer, left, right, result);
6298 {// what is this case? just found it in ds390/gen.c
6299 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6306 symbol *tlbl = newiTempLabel (NULL);
6307 int sizel = AOP_SIZE (left);
6309 emitcode ("setb", "c");
6312 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6314 MOVA (aopGet (left, offset, FALSE, FALSE));
6316 if ((posbit = isLiteralBit (bytelit)) != 0)
6317 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6320 if (bytelit != 0x0FFL)
6321 emitcode ("anl", "a,%s",
6322 aopGet (right, offset, FALSE, TRUE));
6323 emitcode ("jnz", "%05d$", tlbl->key + 100);
6328 // bit = left & literal
6331 emitcode ("clr", "c");
6332 emitcode ("", "%05d$:", tlbl->key + 100);
6334 // if(left & literal)
6338 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6340 emitcode ("", "%05d$:", tlbl->key + 100);
6348 /* if left is same as result */
6349 if (sameRegs (AOP (result), AOP (left)))
6351 for (; size--; offset++)
6353 if (AOP_TYPE (right) == AOP_LIT)
6355 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6356 if (bytelit == 0x0FF)
6358 /* dummy read of volatile operand */
6359 if (isOperandVolatile (left, FALSE))
6360 MOVA (aopGet (left, offset, FALSE, FALSE));
6364 else if (bytelit == 0)
6366 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6368 else if (IS_AOP_PREG (result))
6370 MOVA (aopGet (left, offset, FALSE, TRUE));
6371 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6372 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6375 emitcode ("anl", "%s,%s",
6376 aopGet (left, offset, FALSE, TRUE),
6377 aopGet (right, offset, FALSE, FALSE));
6381 if (AOP_TYPE (left) == AOP_ACC && offset == 0)
6383 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6387 MOVA (aopGet (right, offset, FALSE, FALSE));
6388 if (IS_AOP_PREG (result))
6390 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6391 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6394 emitcode ("anl", "%s,a",
6395 aopGet (left, offset, FALSE, TRUE));
6402 // left & result in different registers
6403 if (AOP_TYPE (result) == AOP_CRY)
6406 // if(size), result in bit
6407 // if(!size && ifx), conditional oper: if(left & right)
6408 symbol *tlbl = newiTempLabel (NULL);
6409 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6411 emitcode ("setb", "c");
6414 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6415 && AOP_TYPE(left)==AOP_ACC)
6418 emitcode("mov", "a,b");
6419 emitcode ("anl", "a,%s",
6420 aopGet (right, offset, FALSE, FALSE));
6422 if (AOP_TYPE(left)==AOP_ACC)
6426 bool pushedB = pushB ();
6427 emitcode("mov", "b,a");
6428 MOVA (aopGet (right, offset, FALSE, FALSE));
6429 emitcode("anl", "a,b");
6434 MOVA (aopGet (right, offset, FALSE, FALSE));
6435 emitcode("anl", "a,b");
6438 MOVA (aopGet (right, offset, FALSE, FALSE));
6439 emitcode ("anl", "a,%s",
6440 aopGet (left, offset, FALSE, FALSE));
6443 emitcode ("jnz", "%05d$", tlbl->key + 100);
6449 emitcode ("", "%05d$:", tlbl->key + 100);
6453 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6455 emitcode ("", "%05d$:", tlbl->key + 100);
6459 for (; (size--); offset++)
6462 // result = left & right
6463 if (AOP_TYPE (right) == AOP_LIT)
6465 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6466 if (bytelit == 0x0FF)
6469 aopGet (left, offset, FALSE, FALSE),
6471 isOperandVolatile (result, FALSE));
6474 else if (bytelit == 0)
6476 /* dummy read of volatile operand */
6477 if (isOperandVolatile (left, FALSE))
6478 MOVA (aopGet (left, offset, FALSE, FALSE));
6479 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6482 else if (AOP_TYPE (left) == AOP_ACC)
6486 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6487 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6492 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6493 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6498 // faster than result <- left, anl result,right
6499 // and better if result is SFR
6500 if (AOP_TYPE (left) == AOP_ACC)
6503 emitcode("mov", "a,b");
6504 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6508 MOVA (aopGet (right, offset, FALSE, FALSE));
6509 emitcode ("anl", "a,%s",
6510 aopGet (left, offset, FALSE, FALSE));
6512 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6518 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6519 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6520 freeAsmop (result, NULL, ic, TRUE);
6523 /*-----------------------------------------------------------------*/
6524 /* genOr - code for or */
6525 /*-----------------------------------------------------------------*/
6527 genOr (iCode * ic, iCode * ifx)
6529 operand *left, *right, *result;
6530 int size, offset = 0;
6531 unsigned long lit = 0L;
6534 D(emitcode ("; genOr",""));
6536 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6537 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6538 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6541 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6543 AOP_TYPE (left), AOP_TYPE (right));
6544 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6546 AOP_SIZE (left), AOP_SIZE (right));
6549 /* if left is a literal & right is not then exchange them */
6550 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6551 AOP_NEEDSACC (left))
6553 operand *tmp = right;
6558 /* if result = right then exchange them */
6559 if (sameRegs (AOP (result), AOP (right)))
6561 operand *tmp = right;
6566 /* if right is bit then exchange them */
6567 if (AOP_TYPE (right) == AOP_CRY &&
6568 AOP_TYPE (left) != AOP_CRY)
6570 operand *tmp = right;
6574 if (AOP_TYPE (right) == AOP_LIT)
6575 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6577 size = AOP_SIZE (result);
6581 if (AOP_TYPE (left) == AOP_CRY)
6583 if (AOP_TYPE (right) == AOP_LIT)
6585 // c = bit | literal;
6588 // lit != 0 => result = 1
6589 if (AOP_TYPE (result) == AOP_CRY)
6592 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6594 continueIfTrue (ifx);
6597 emitcode ("setb", "c");
6601 // lit == 0 => result = left
6602 if (size && sameRegs (AOP (result), AOP (left)))
6604 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6609 if (AOP_TYPE (right) == AOP_CRY)
6612 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6613 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6618 symbol *tlbl = newiTempLabel (NULL);
6619 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6620 emitcode ("setb", "c");
6621 emitcode ("jb", "%s,%05d$",
6622 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6624 emitcode ("jnz", "%05d$", tlbl->key + 100);
6625 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6627 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6633 emitcode ("", "%05d$:", tlbl->key + 100);
6642 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6643 genIfxJump (ifx, "c", left, right, result);
6647 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6648 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6649 if ((AOP_TYPE (right) == AOP_LIT) &&
6650 (AOP_TYPE (result) == AOP_CRY) &&
6651 (AOP_TYPE (left) != AOP_CRY))
6657 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6659 continueIfTrue (ifx);
6664 // lit = 0, result = boolean(left)
6666 emitcode ("setb", "c");
6670 symbol *tlbl = newiTempLabel (NULL);
6671 emitcode ("jnz", "%05d$", tlbl->key + 100);
6673 emitcode ("", "%05d$:", tlbl->key + 100);
6677 genIfxJump (ifx, "a", left, right, result);
6685 /* if left is same as result */
6686 if (sameRegs (AOP (result), AOP (left)))
6688 for (; size--; offset++)
6690 if (AOP_TYPE (right) == AOP_LIT)
6692 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6695 /* dummy read of volatile operand */
6696 if (isOperandVolatile (left, FALSE))
6697 MOVA (aopGet (left, offset, FALSE, FALSE));
6701 else if (bytelit == 0x0FF)
6703 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6705 else if (IS_AOP_PREG (left))
6707 MOVA (aopGet (left, offset, FALSE, TRUE));
6708 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6709 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6713 emitcode ("orl", "%s,%s",
6714 aopGet (left, offset, FALSE, TRUE),
6715 aopGet (right, offset, FALSE, FALSE));
6720 if (AOP_TYPE (left) == AOP_ACC)
6723 emitcode("mov", "a,b");
6724 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6728 MOVA (aopGet (right, offset, FALSE, FALSE));
6729 if (IS_AOP_PREG (left))
6731 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6732 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6736 emitcode ("orl", "%s,a",
6737 aopGet (left, offset, FALSE, TRUE));
6745 // left & result in different registers
6746 if (AOP_TYPE (result) == AOP_CRY)
6749 // if(size), result in bit
6750 // if(!size && ifx), conditional oper: if(left | right)
6751 symbol *tlbl = newiTempLabel (NULL);
6752 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6754 emitcode ("setb", "c");
6757 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6759 emitcode("mov", "a,b");
6760 emitcode ("orl", "a,%s",
6761 aopGet (right, offset, FALSE, FALSE));
6763 MOVA (aopGet (right, offset, FALSE, FALSE));
6764 emitcode ("orl", "a,%s",
6765 aopGet (left, offset, FALSE, FALSE));
6767 emitcode ("jnz", "%05d$", tlbl->key + 100);
6773 emitcode ("", "%05d$:", tlbl->key + 100);
6777 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6779 emitcode ("", "%05d$:", tlbl->key + 100);
6783 for (; (size--); offset++)
6786 // result = left | right
6787 if (AOP_TYPE (right) == AOP_LIT)
6789 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6793 aopGet (left, offset, FALSE, FALSE),
6795 isOperandVolatile (result, FALSE));
6798 else if (bytelit == 0x0FF)
6800 /* dummy read of volatile operand */
6801 if (isOperandVolatile (left, FALSE))
6802 MOVA (aopGet (left, offset, FALSE, FALSE));
6803 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6807 // faster than result <- left, anl result,right
6808 // and better if result is SFR
6809 if (AOP_TYPE (left) == AOP_ACC)
6812 emitcode("mov", "a,b");
6813 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6817 MOVA (aopGet (right, offset, FALSE, FALSE));
6818 emitcode ("orl", "a,%s",
6819 aopGet (left, offset, FALSE, FALSE));
6821 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6827 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6828 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6829 freeAsmop (result, NULL, ic, TRUE);
6832 /*-----------------------------------------------------------------*/
6833 /* genXor - code for xclusive or */
6834 /*-----------------------------------------------------------------*/
6836 genXor (iCode * ic, iCode * ifx)
6838 operand *left, *right, *result;
6839 int size, offset = 0;
6840 unsigned long lit = 0L;
6843 D(emitcode ("; genXor",""));
6845 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6846 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6847 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6850 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6852 AOP_TYPE (left), AOP_TYPE (right));
6853 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6855 AOP_SIZE (left), AOP_SIZE (right));
6858 /* if left is a literal & right is not ||
6859 if left needs acc & right does not */
6860 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6861 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6863 operand *tmp = right;
6868 /* if result = right then exchange them */
6869 if (sameRegs (AOP (result), AOP (right)))
6871 operand *tmp = right;
6876 /* if right is bit then exchange them */
6877 if (AOP_TYPE (right) == AOP_CRY &&
6878 AOP_TYPE (left) != AOP_CRY)
6880 operand *tmp = right;
6884 if (AOP_TYPE (right) == AOP_LIT)
6885 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6887 size = AOP_SIZE (result);
6891 if (AOP_TYPE (left) == AOP_CRY)
6893 if (AOP_TYPE (right) == AOP_LIT)
6895 // c = bit & literal;
6898 // lit>>1 != 0 => result = 1
6899 if (AOP_TYPE (result) == AOP_CRY)
6902 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6904 continueIfTrue (ifx);
6907 emitcode ("setb", "c");
6914 // lit == 0, result = left
6915 if (size && sameRegs (AOP (result), AOP (left)))
6917 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6921 // lit == 1, result = not(left)
6922 if (size && sameRegs (AOP (result), AOP (left)))
6924 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6929 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6930 emitcode ("cpl", "c");
6939 symbol *tlbl = newiTempLabel (NULL);
6940 if (AOP_TYPE (right) == AOP_CRY)
6943 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6947 int sizer = AOP_SIZE (right);
6949 // if val>>1 != 0, result = 1
6950 emitcode ("setb", "c");
6953 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
6955 // test the msb of the lsb
6956 emitcode ("anl", "a,#0xfe");
6957 emitcode ("jnz", "%05d$", tlbl->key + 100);
6961 emitcode ("rrc", "a");
6963 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6964 emitcode ("cpl", "c");
6965 emitcode ("", "%05d$:", (tlbl->key + 100));
6972 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6973 genIfxJump (ifx, "c", left, right, result);
6977 /* if left is same as result */
6978 if (sameRegs (AOP (result), AOP (left)))
6980 for (; size--; offset++)
6982 if (AOP_TYPE (right) == AOP_LIT)
6984 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6987 /* dummy read of volatile operand */
6988 if (isOperandVolatile (left, FALSE))
6989 MOVA (aopGet (left, offset, FALSE, FALSE));
6993 else if (IS_AOP_PREG (left))
6995 MOVA (aopGet (left, offset, FALSE, TRUE));
6996 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6997 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7001 emitcode ("xrl", "%s,%s",
7002 aopGet (left, offset, FALSE, TRUE),
7003 aopGet (right, offset, FALSE, FALSE));
7008 if (AOP_TYPE (left) == AOP_ACC)
7011 emitcode("mov", "a,b");
7012 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7016 MOVA (aopGet (right, offset, FALSE, FALSE));
7017 if (IS_AOP_PREG (left))
7019 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7020 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7023 emitcode ("xrl", "%s,a",
7024 aopGet (left, offset, FALSE, TRUE));
7031 // left & result in different registers
7032 if (AOP_TYPE (result) == AOP_CRY)
7035 // if(size), result in bit
7036 // if(!size && ifx), conditional oper: if(left ^ right)
7037 symbol *tlbl = newiTempLabel (NULL);
7038 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7040 emitcode ("setb", "c");
7043 if ((AOP_TYPE (right) == AOP_LIT) &&
7044 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7046 MOVA (aopGet (left, offset, FALSE, FALSE));
7050 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7052 emitcode("mov", "a,b");
7053 emitcode ("xrl", "a,%s",
7054 aopGet (right, offset, FALSE, FALSE));
7056 MOVA (aopGet (right, offset, FALSE, FALSE));
7057 emitcode ("xrl", "a,%s",
7058 aopGet (left, offset, FALSE, FALSE));
7061 emitcode ("jnz", "%05d$", tlbl->key + 100);
7067 emitcode ("", "%05d$:", tlbl->key + 100);
7071 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7075 for (; (size--); offset++)
7078 // result = left & right
7079 if (AOP_TYPE (right) == AOP_LIT)
7081 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7085 aopGet (left, offset, FALSE, FALSE),
7087 isOperandVolatile (result, FALSE));
7091 // faster than result <- left, anl result,right
7092 // and better if result is SFR
7093 if (AOP_TYPE (left) == AOP_ACC)
7096 emitcode("mov", "a,b");
7097 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7101 MOVA (aopGet (right, offset, FALSE, FALSE));
7102 emitcode ("xrl", "a,%s",
7103 aopGet (left, offset, FALSE, TRUE));
7105 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7111 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7112 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7113 freeAsmop (result, NULL, ic, TRUE);
7116 /*-----------------------------------------------------------------*/
7117 /* genInline - write the inline code out */
7118 /*-----------------------------------------------------------------*/
7120 genInline (iCode * ic)
7122 char *buffer, *bp, *bp1;
7124 D(emitcode ("; genInline",""));
7126 _G.inLine += (!options.asmpeep);
7128 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7129 strcpy (buffer, IC_INLINE (ic));
7131 /* emit each line as a code */
7142 /* Add \n for labels, not dirs such as c:\mydir */
7143 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7157 /* emitcode("",buffer); */
7158 _G.inLine -= (!options.asmpeep);
7161 /*-----------------------------------------------------------------*/
7162 /* genRRC - rotate right with carry */
7163 /*-----------------------------------------------------------------*/
7167 operand *left, *result;
7168 int size, offset = 0;
7171 D(emitcode ("; genRRC",""));
7173 /* rotate right with carry */
7174 left = IC_LEFT (ic);
7175 result = IC_RESULT (ic);
7176 aopOp (left, ic, FALSE);
7177 aopOp (result, ic, FALSE);
7179 /* move it to the result */
7180 size = AOP_SIZE (result);
7182 if (size == 1) { /* special case for 1 byte */
7183 l = aopGet (left, offset, FALSE, FALSE);
7185 emitcode ("rr", "a");
7188 /* no need to clear carry, bit7 will be written later */
7191 l = aopGet (left, offset, FALSE, FALSE);
7193 emitcode ("rrc", "a");
7194 if (AOP_SIZE (result) > 1)
7195 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7197 /* now we need to put the carry into the
7198 highest order byte of the result */
7199 if (AOP_SIZE (result) > 1)
7201 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7204 emitcode ("mov", "acc.7,c");
7206 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7207 freeAsmop (left, NULL, ic, TRUE);
7208 freeAsmop (result, NULL, ic, TRUE);
7211 /*-----------------------------------------------------------------*/
7212 /* genRLC - generate code for rotate left with carry */
7213 /*-----------------------------------------------------------------*/
7217 operand *left, *result;
7218 int size, offset = 0;
7221 D(emitcode ("; genRLC",""));
7223 /* rotate right with carry */
7224 left = IC_LEFT (ic);
7225 result = IC_RESULT (ic);
7226 aopOp (left, ic, FALSE);
7227 aopOp (result, ic, FALSE);
7229 /* move it to the result */
7230 size = AOP_SIZE (result);
7234 l = aopGet (left, offset, FALSE, FALSE);
7236 if (size == 0) { /* special case for 1 byte */
7240 emitcode("rlc","a"); /* bit0 will be written later */
7241 if (AOP_SIZE (result) > 1)
7242 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7245 l = aopGet (left, offset, FALSE, FALSE);
7247 emitcode ("rlc", "a");
7248 if (AOP_SIZE (result) > 1)
7249 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7252 /* now we need to put the carry into the
7253 highest order byte of the result */
7254 if (AOP_SIZE (result) > 1)
7256 l = aopGet (result, 0, FALSE, FALSE);
7259 emitcode ("mov", "acc.0,c");
7261 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7262 freeAsmop (left, NULL, ic, TRUE);
7263 freeAsmop (result, NULL, ic, TRUE);
7266 /*-----------------------------------------------------------------*/
7267 /* genGetHbit - generates code get highest order bit */
7268 /*-----------------------------------------------------------------*/
7270 genGetHbit (iCode * ic)
7272 operand *left, *result;
7274 D(emitcode ("; genGetHbit",""));
7276 left = IC_LEFT (ic);
7277 result = IC_RESULT (ic);
7278 aopOp (left, ic, FALSE);
7279 aopOp (result, ic, FALSE);
7281 /* get the highest order byte into a */
7282 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7283 if (AOP_TYPE (result) == AOP_CRY)
7285 emitcode ("rlc", "a");
7290 emitcode ("rl", "a");
7291 emitcode ("anl", "a,#0x01");
7296 freeAsmop (left, NULL, ic, TRUE);
7297 freeAsmop (result, NULL, ic, TRUE);
7300 /*-----------------------------------------------------------------*/
7301 /* genSwap - generates code to swap nibbles or bytes */
7302 /*-----------------------------------------------------------------*/
7304 genSwap (iCode * ic)
7306 operand *left, *result;
7308 D(emitcode ("; genSwap",""));
7310 left = IC_LEFT (ic);
7311 result = IC_RESULT (ic);
7312 aopOp (left, ic, FALSE);
7313 aopOp (result, ic, FALSE);
7315 switch (AOP_SIZE (left))
7317 case 1: /* swap nibbles in byte */
7318 MOVA (aopGet (left, 0, FALSE, FALSE));
7319 emitcode ("swap", "a");
7320 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7322 case 2: /* swap bytes in word */
7323 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7325 MOVA (aopGet (left, 0, FALSE, FALSE));
7326 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7327 0, isOperandVolatile (result, FALSE));
7328 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7330 else if (operandsEqu (left, result))
7333 bool pushedB = FALSE, leftInB = FALSE;
7335 MOVA (aopGet (left, 0, FALSE, FALSE));
7336 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7339 emitcode ("mov", "b,a");
7343 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7344 0, isOperandVolatile (result, FALSE));
7345 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7352 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7353 0, isOperandVolatile (result, FALSE));
7354 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7355 1, isOperandVolatile (result, FALSE));
7359 wassertl(FALSE, "unsupported SWAP operand size");
7362 freeAsmop (left, NULL, ic, TRUE);
7363 freeAsmop (result, NULL, ic, TRUE);
7367 /*-----------------------------------------------------------------*/
7368 /* AccRol - rotate left accumulator by known count */
7369 /*-----------------------------------------------------------------*/
7371 AccRol (int shCount)
7373 shCount &= 0x0007; // shCount : 0..7
7380 emitcode ("rl", "a");
7383 emitcode ("rl", "a");
7384 emitcode ("rl", "a");
7387 emitcode ("swap", "a");
7388 emitcode ("rr", "a");
7391 emitcode ("swap", "a");
7394 emitcode ("swap", "a");
7395 emitcode ("rl", "a");
7398 emitcode ("rr", "a");
7399 emitcode ("rr", "a");
7402 emitcode ("rr", "a");
7407 /*-----------------------------------------------------------------*/
7408 /* AccLsh - left shift accumulator by known count */
7409 /*-----------------------------------------------------------------*/
7411 AccLsh (int shCount)
7416 emitcode ("add", "a,acc");
7417 else if (shCount == 2)
7419 emitcode ("add", "a,acc");
7420 emitcode ("add", "a,acc");
7424 /* rotate left accumulator */
7426 /* and kill the lower order bits */
7427 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7432 /*-----------------------------------------------------------------*/
7433 /* AccRsh - right shift accumulator by known count */
7434 /*-----------------------------------------------------------------*/
7436 AccRsh (int shCount)
7443 emitcode ("rrc", "a");
7447 /* rotate right accumulator */
7448 AccRol (8 - shCount);
7449 /* and kill the higher order bits */
7450 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7455 /*-----------------------------------------------------------------*/
7456 /* AccSRsh - signed right shift accumulator by known count */
7457 /*-----------------------------------------------------------------*/
7459 AccSRsh (int shCount)
7466 emitcode ("mov", "c,acc.7");
7467 emitcode ("rrc", "a");
7469 else if (shCount == 2)
7471 emitcode ("mov", "c,acc.7");
7472 emitcode ("rrc", "a");
7473 emitcode ("mov", "c,acc.7");
7474 emitcode ("rrc", "a");
7478 tlbl = newiTempLabel (NULL);
7479 /* rotate right accumulator */
7480 AccRol (8 - shCount);
7481 /* and kill the higher order bits */
7482 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7483 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7484 emitcode ("orl", "a,#0x%02x",
7485 (unsigned char) ~SRMask[shCount]);
7486 emitcode ("", "%05d$:", tlbl->key + 100);
7491 /*-----------------------------------------------------------------*/
7492 /* shiftR1Left2Result - shift right one byte from left to result */
7493 /*-----------------------------------------------------------------*/
7495 shiftR1Left2Result (operand * left, int offl,
7496 operand * result, int offr,
7497 int shCount, int sign)
7499 MOVA (aopGet (left, offl, FALSE, FALSE));
7500 /* shift right accumulator */
7505 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7508 /*-----------------------------------------------------------------*/
7509 /* shiftL1Left2Result - shift left one byte from left to result */
7510 /*-----------------------------------------------------------------*/
7512 shiftL1Left2Result (operand * left, int offl,
7513 operand * result, int offr, int shCount)
7516 l = aopGet (left, offl, FALSE, FALSE);
7518 /* shift left accumulator */
7520 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7523 /*-----------------------------------------------------------------*/
7524 /* movLeft2Result - move byte from left to result */
7525 /*-----------------------------------------------------------------*/
7527 movLeft2Result (operand * left, int offl,
7528 operand * result, int offr, int sign)
7531 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7533 l = aopGet (left, offl, FALSE, FALSE);
7535 if (*l == '@' && (IS_AOP_PREG (result)))
7537 emitcode ("mov", "a,%s", l);
7538 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7543 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7546 /* MSB sign in acc.7 ! */
7547 if (getDataSize (left) == offl + 1)
7549 emitcode ("mov", "a,%s", l);
7550 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7557 /*-----------------------------------------------------------------*/
7558 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7559 /*-----------------------------------------------------------------*/
7563 emitcode ("rrc", "a");
7564 emitcode ("xch", "a,%s", x);
7565 emitcode ("rrc", "a");
7566 emitcode ("xch", "a,%s", x);
7569 /*-----------------------------------------------------------------*/
7570 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7571 /*-----------------------------------------------------------------*/
7575 emitcode ("xch", "a,%s", x);
7576 emitcode ("rlc", "a");
7577 emitcode ("xch", "a,%s", x);
7578 emitcode ("rlc", "a");
7581 /*-----------------------------------------------------------------*/
7582 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7583 /*-----------------------------------------------------------------*/
7587 emitcode ("xch", "a,%s", x);
7588 emitcode ("add", "a,acc");
7589 emitcode ("xch", "a,%s", x);
7590 emitcode ("rlc", "a");
7593 /*-----------------------------------------------------------------*/
7594 /* AccAXLsh - left shift a:x by known count (0..7) */
7595 /*-----------------------------------------------------------------*/
7597 AccAXLsh (char *x, int shCount)
7612 case 5: // AAAAABBB:CCCCCDDD
7614 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7616 emitcode ("anl", "a,#0x%02x",
7617 SLMask[shCount]); // BBB00000:CCCCCDDD
7619 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7621 AccRol (shCount); // DDDCCCCC:BBB00000
7623 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7625 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7627 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7629 emitcode ("anl", "a,#0x%02x",
7630 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7632 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7634 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7637 case 6: // AAAAAABB:CCCCCCDD
7638 emitcode ("anl", "a,#0x%02x",
7639 SRMask[shCount]); // 000000BB:CCCCCCDD
7640 emitcode ("mov", "c,acc.0"); // c = B
7641 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7643 AccAXRrl1 (x); // BCCCCCCD:D000000B
7644 AccAXRrl1 (x); // BBCCCCCC:DD000000
7646 emitcode("rrc","a");
7647 emitcode("xch","a,%s", x);
7648 emitcode("rrc","a");
7649 emitcode("mov","c,acc.0"); //<< get correct bit
7650 emitcode("xch","a,%s", x);
7652 emitcode("rrc","a");
7653 emitcode("xch","a,%s", x);
7654 emitcode("rrc","a");
7655 emitcode("xch","a,%s", x);
7658 case 7: // a:x <<= 7
7660 emitcode ("anl", "a,#0x%02x",
7661 SRMask[shCount]); // 0000000B:CCCCCCCD
7663 emitcode ("mov", "c,acc.0"); // c = B
7665 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7667 AccAXRrl1 (x); // BCCCCCCC:D0000000
7675 /*-----------------------------------------------------------------*/
7676 /* AccAXRsh - right shift a:x known count (0..7) */
7677 /*-----------------------------------------------------------------*/
7679 AccAXRsh (char *x, int shCount)
7687 AccAXRrl1 (x); // 0->a:x
7692 AccAXRrl1 (x); // 0->a:x
7695 AccAXRrl1 (x); // 0->a:x
7700 case 5: // AAAAABBB:CCCCCDDD = a:x
7702 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7704 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7706 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7708 emitcode ("anl", "a,#0x%02x",
7709 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7711 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7713 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7715 emitcode ("anl", "a,#0x%02x",
7716 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7718 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7720 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7722 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7725 case 6: // AABBBBBB:CCDDDDDD
7727 emitcode ("mov", "c,acc.7");
7728 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7730 emitcode ("mov", "c,acc.7");
7731 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7733 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7735 emitcode ("anl", "a,#0x%02x",
7736 SRMask[shCount]); // 000000AA:BBBBBBCC
7739 case 7: // ABBBBBBB:CDDDDDDD
7741 emitcode ("mov", "c,acc.7"); // c = A
7743 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7745 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7747 emitcode ("anl", "a,#0x%02x",
7748 SRMask[shCount]); // 0000000A:BBBBBBBC
7756 /*-----------------------------------------------------------------*/
7757 /* AccAXRshS - right shift signed a:x known count (0..7) */
7758 /*-----------------------------------------------------------------*/
7760 AccAXRshS (char *x, int shCount)
7768 emitcode ("mov", "c,acc.7");
7769 AccAXRrl1 (x); // s->a:x
7773 emitcode ("mov", "c,acc.7");
7774 AccAXRrl1 (x); // s->a:x
7776 emitcode ("mov", "c,acc.7");
7777 AccAXRrl1 (x); // s->a:x
7782 case 5: // AAAAABBB:CCCCCDDD = a:x
7784 tlbl = newiTempLabel (NULL);
7785 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7787 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7789 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7791 emitcode ("anl", "a,#0x%02x",
7792 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7794 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7796 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7798 emitcode ("anl", "a,#0x%02x",
7799 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7801 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7803 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7805 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7807 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7808 emitcode ("orl", "a,#0x%02x",
7809 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7811 emitcode ("", "%05d$:", tlbl->key + 100);
7812 break; // SSSSAAAA:BBBCCCCC
7814 case 6: // AABBBBBB:CCDDDDDD
7816 tlbl = newiTempLabel (NULL);
7817 emitcode ("mov", "c,acc.7");
7818 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7820 emitcode ("mov", "c,acc.7");
7821 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7823 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7825 emitcode ("anl", "a,#0x%02x",
7826 SRMask[shCount]); // 000000AA:BBBBBBCC
7828 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7829 emitcode ("orl", "a,#0x%02x",
7830 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7832 emitcode ("", "%05d$:", tlbl->key + 100);
7834 case 7: // ABBBBBBB:CDDDDDDD
7836 tlbl = newiTempLabel (NULL);
7837 emitcode ("mov", "c,acc.7"); // c = A
7839 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7841 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7843 emitcode ("anl", "a,#0x%02x",
7844 SRMask[shCount]); // 0000000A:BBBBBBBC
7846 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7847 emitcode ("orl", "a,#0x%02x",
7848 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7850 emitcode ("", "%05d$:", tlbl->key + 100);
7857 /*-----------------------------------------------------------------*/
7858 /* shiftL2Left2Result - shift left two bytes from left to result */
7859 /*-----------------------------------------------------------------*/
7861 shiftL2Left2Result (operand * left, int offl,
7862 operand * result, int offr, int shCount)
7864 if (sameRegs (AOP (result), AOP (left)) &&
7865 ((offl + MSB16) == offr))
7867 /* don't crash result[offr] */
7868 MOVA (aopGet (left, offl, FALSE, FALSE));
7869 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7873 movLeft2Result (left, offl, result, offr, 0);
7874 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7876 /* ax << shCount (x = lsb(result)) */
7877 AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount);
7878 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7882 /*-----------------------------------------------------------------*/
7883 /* shiftR2Left2Result - shift right two bytes from left to result */
7884 /*-----------------------------------------------------------------*/
7886 shiftR2Left2Result (operand * left, int offl,
7887 operand * result, int offr,
7888 int shCount, int sign)
7890 if (sameRegs (AOP (result), AOP (left)) &&
7891 ((offl + MSB16) == offr))
7893 /* don't crash result[offr] */
7894 MOVA (aopGet (left, offl, FALSE, FALSE));
7895 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7899 movLeft2Result (left, offl, result, offr, 0);
7900 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7902 /* a:x >> shCount (x = lsb(result)) */
7904 AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount);
7906 AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount);
7907 if (getDataSize (result) > 1)
7908 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7911 /*-----------------------------------------------------------------*/
7912 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7913 /*-----------------------------------------------------------------*/
7915 shiftLLeftOrResult (operand * left, int offl,
7916 operand * result, int offr, int shCount)
7918 MOVA (aopGet (left, offl, FALSE, FALSE));
7919 /* shift left accumulator */
7921 /* or with result */
7922 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7923 /* back to result */
7924 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7927 /*-----------------------------------------------------------------*/
7928 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7929 /*-----------------------------------------------------------------*/
7931 shiftRLeftOrResult (operand * left, int offl,
7932 operand * result, int offr, int shCount)
7934 MOVA (aopGet (left, offl, FALSE, FALSE));
7935 /* shift right accumulator */
7937 /* or with result */
7938 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7939 /* back to result */
7940 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7943 /*-----------------------------------------------------------------*/
7944 /* genlshOne - left shift a one byte quantity by known count */
7945 /*-----------------------------------------------------------------*/
7947 genlshOne (operand * result, operand * left, int shCount)
7949 D(emitcode ("; genlshOne",""));
7951 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7954 /*-----------------------------------------------------------------*/
7955 /* genlshTwo - left shift two bytes by known amount != 0 */
7956 /*-----------------------------------------------------------------*/
7958 genlshTwo (operand * result, operand * left, int shCount)
7962 D(emitcode ("; genlshTwo",""));
7964 size = getDataSize (result);
7966 /* if shCount >= 8 */
7974 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7976 movLeft2Result (left, LSB, result, MSB16, 0);
7978 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7981 /* 1 <= shCount <= 7 */
7985 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7987 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7991 /*-----------------------------------------------------------------*/
7992 /* shiftLLong - shift left one long from left to result */
7993 /* offl = LSB or MSB16 */
7994 /*-----------------------------------------------------------------*/
7996 shiftLLong (operand * left, operand * result, int offr)
7999 int size = AOP_SIZE (result);
8001 if (size >= LSB + offr)
8003 l = aopGet (left, LSB, FALSE, FALSE);
8005 emitcode ("add", "a,acc");
8006 if (sameRegs (AOP (left), AOP (result)) &&
8007 size >= MSB16 + offr && offr != LSB)
8008 emitcode ("xch", "a,%s",
8009 aopGet (left, LSB + offr, FALSE, FALSE));
8011 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8014 if (size >= MSB16 + offr)
8016 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8018 l = aopGet (left, MSB16, FALSE, FALSE);
8021 emitcode ("rlc", "a");
8022 if (sameRegs (AOP (left), AOP (result)) &&
8023 size >= MSB24 + offr && offr != LSB)
8024 emitcode ("xch", "a,%s",
8025 aopGet (left, MSB16 + offr, FALSE, FALSE));
8027 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8030 if (size >= MSB24 + offr)
8032 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8034 l = aopGet (left, MSB24, FALSE, FALSE);
8037 emitcode ("rlc", "a");
8038 if (sameRegs (AOP (left), AOP (result)) &&
8039 size >= MSB32 + offr && offr != LSB)
8040 emitcode ("xch", "a,%s",
8041 aopGet (left, MSB24 + offr, FALSE, FALSE));
8043 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8046 if (size > MSB32 + offr)
8048 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8050 l = aopGet (left, MSB32, FALSE, FALSE);
8053 emitcode ("rlc", "a");
8054 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8057 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8060 /*-----------------------------------------------------------------*/
8061 /* genlshFour - shift four byte by a known amount != 0 */
8062 /*-----------------------------------------------------------------*/
8064 genlshFour (operand * result, operand * left, int shCount)
8068 D(emitcode ("; genlshFour",""));
8070 size = AOP_SIZE (result);
8072 /* if shifting more that 3 bytes */
8077 /* lowest order of left goes to the highest
8078 order of the destination */
8079 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8081 movLeft2Result (left, LSB, result, MSB32, 0);
8082 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8083 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8084 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8088 /* more than two bytes */
8089 else if (shCount >= 16)
8091 /* lower order two bytes goes to higher order two bytes */
8093 /* if some more remaining */
8095 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8098 movLeft2Result (left, MSB16, result, MSB32, 0);
8099 movLeft2Result (left, LSB, result, MSB24, 0);
8101 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8102 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8106 /* if more than 1 byte */
8107 else if (shCount >= 8)
8109 /* lower order three bytes goes to higher order three bytes */
8114 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8116 movLeft2Result (left, LSB, result, MSB16, 0);
8122 movLeft2Result (left, MSB24, result, MSB32, 0);
8123 movLeft2Result (left, MSB16, result, MSB24, 0);
8124 movLeft2Result (left, LSB, result, MSB16, 0);
8125 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8127 else if (shCount == 1)
8128 shiftLLong (left, result, MSB16);
8131 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8132 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8133 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8134 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8139 /* 1 <= shCount <= 7 */
8140 else if (shCount <= 2)
8142 shiftLLong (left, result, LSB);
8144 shiftLLong (result, result, LSB);
8146 /* 3 <= shCount <= 7, optimize */
8149 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8150 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8151 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8155 /*-----------------------------------------------------------------*/
8156 /* genLeftShiftLiteral - left shifting by known count */
8157 /*-----------------------------------------------------------------*/
8159 genLeftShiftLiteral (operand * left,
8164 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8167 D(emitcode ("; genLeftShiftLiteral",""));
8169 freeAsmop (right, NULL, ic, TRUE);
8171 aopOp (left, ic, FALSE);
8172 aopOp (result, ic, FALSE);
8174 size = getSize (operandType (result));
8177 emitcode ("; shift left ", "result %d, left %d", size,
8181 /* I suppose that the left size >= result size */
8186 movLeft2Result (left, size, result, size, 0);
8190 else if (shCount >= (size * 8))
8192 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8198 genlshOne (result, left, shCount);
8202 genlshTwo (result, left, shCount);
8206 genlshFour (result, left, shCount);
8209 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8210 "*** ack! mystery literal shift!\n");
8214 freeAsmop (left, NULL, ic, TRUE);
8215 freeAsmop (result, NULL, ic, TRUE);
8218 /*-----------------------------------------------------------------*/
8219 /* genLeftShift - generates code for left shifting */
8220 /*-----------------------------------------------------------------*/
8222 genLeftShift (iCode * ic)
8224 operand *left, *right, *result;
8227 symbol *tlbl, *tlbl1;
8230 D(emitcode ("; genLeftShift",""));
8232 right = IC_RIGHT (ic);
8233 left = IC_LEFT (ic);
8234 result = IC_RESULT (ic);
8236 aopOp (right, ic, FALSE);
8238 /* if the shift count is known then do it
8239 as efficiently as possible */
8240 if (AOP_TYPE (right) == AOP_LIT)
8242 genLeftShiftLiteral (left, right, result, ic);
8246 /* shift count is unknown then we have to form
8247 a loop get the loop count in B : Note: we take
8248 only the lower order byte since shifting
8249 more that 32 bits make no sense anyway, ( the
8250 largest size of an object can be only 32 bits ) */
8253 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8254 emitcode ("inc", "b");
8255 freeAsmop (right, NULL, ic, TRUE);
8256 aopOp (left, ic, FALSE);
8257 aopOp (result, ic, FALSE);
8259 /* now move the left to the result if they are not the same */
8260 if (!sameRegs (AOP (left), AOP (result)) &&
8261 AOP_SIZE (result) > 1)
8264 size = AOP_SIZE (result);
8268 l = aopGet (left, offset, FALSE, TRUE);
8269 if (*l == '@' && (IS_AOP_PREG (result)))
8272 emitcode ("mov", "a,%s", l);
8273 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8276 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8281 tlbl = newiTempLabel (NULL);
8282 size = AOP_SIZE (result);
8284 tlbl1 = newiTempLabel (NULL);
8286 /* if it is only one byte then */
8289 symbol *tlbl1 = newiTempLabel (NULL);
8291 l = aopGet (left, 0, FALSE, FALSE);
8293 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8294 emitcode ("", "%05d$:", tlbl->key + 100);
8295 emitcode ("add", "a,acc");
8296 emitcode ("", "%05d$:", tlbl1->key + 100);
8297 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8299 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8303 reAdjustPreg (AOP (result));
8305 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8306 emitcode ("", "%05d$:", tlbl->key + 100);
8307 l = aopGet (result, offset, FALSE, FALSE);
8309 emitcode ("add", "a,acc");
8310 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8313 l = aopGet (result, offset, FALSE, FALSE);
8315 emitcode ("rlc", "a");
8316 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8318 reAdjustPreg (AOP (result));
8320 emitcode ("", "%05d$:", tlbl1->key + 100);
8321 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8324 freeAsmop (left, NULL, ic, TRUE);
8325 freeAsmop (result, NULL, ic, TRUE);
8328 /*-----------------------------------------------------------------*/
8329 /* genrshOne - right shift a one byte quantity by known count */
8330 /*-----------------------------------------------------------------*/
8332 genrshOne (operand * result, operand * left,
8333 int shCount, int sign)
8335 D(emitcode ("; genrshOne",""));
8337 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8340 /*-----------------------------------------------------------------*/
8341 /* genrshTwo - right shift two bytes by known amount != 0 */
8342 /*-----------------------------------------------------------------*/
8344 genrshTwo (operand * result, operand * left,
8345 int shCount, int sign)
8347 D(emitcode ("; genrshTwo",""));
8349 /* if shCount >= 8 */
8354 shiftR1Left2Result (left, MSB16, result, LSB,
8357 movLeft2Result (left, MSB16, result, LSB, sign);
8358 addSign (result, MSB16, sign);
8361 /* 1 <= shCount <= 7 */
8363 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8366 /*-----------------------------------------------------------------*/
8367 /* shiftRLong - shift right one long from left to result */
8368 /* offl = LSB or MSB16 */
8369 /*-----------------------------------------------------------------*/
8371 shiftRLong (operand * left, int offl,
8372 operand * result, int sign)
8374 int isSameRegs=sameRegs(AOP(left),AOP(result));
8376 if (isSameRegs && offl>1) {
8377 // we are in big trouble, but this shouldn't happen
8378 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8381 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8386 emitcode ("rlc", "a");
8387 emitcode ("subb", "a,acc");
8389 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8391 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8392 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8395 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8400 emitcode ("clr", "c");
8402 emitcode ("mov", "c,acc.7");
8405 emitcode ("rrc", "a");
8407 if (isSameRegs && offl==MSB16) {
8408 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8410 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8411 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8414 emitcode ("rrc", "a");
8415 if (isSameRegs && offl==1) {
8416 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8418 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8419 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8421 emitcode ("rrc", "a");
8422 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8426 MOVA (aopGet (left, LSB, FALSE, FALSE));
8427 emitcode ("rrc", "a");
8428 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8432 /*-----------------------------------------------------------------*/
8433 /* genrshFour - shift four byte by a known amount != 0 */
8434 /*-----------------------------------------------------------------*/
8436 genrshFour (operand * result, operand * left,
8437 int shCount, int sign)
8439 D(emitcode ("; genrshFour",""));
8441 /* if shifting more that 3 bytes */
8446 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8448 movLeft2Result (left, MSB32, result, LSB, sign);
8449 addSign (result, MSB16, sign);
8451 else if (shCount >= 16)
8455 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8458 movLeft2Result (left, MSB24, result, LSB, 0);
8459 movLeft2Result (left, MSB32, result, MSB16, sign);
8461 addSign (result, MSB24, sign);
8463 else if (shCount >= 8)
8467 shiftRLong (left, MSB16, result, sign);
8468 else if (shCount == 0)
8470 movLeft2Result (left, MSB16, result, LSB, 0);
8471 movLeft2Result (left, MSB24, result, MSB16, 0);
8472 movLeft2Result (left, MSB32, result, MSB24, sign);
8473 addSign (result, MSB32, sign);
8477 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8478 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8479 /* the last shift is signed */
8480 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8481 addSign (result, MSB32, sign);
8485 { /* 1 <= shCount <= 7 */
8488 shiftRLong (left, LSB, result, sign);
8490 shiftRLong (result, LSB, result, sign);
8494 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8495 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8496 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8501 /*-----------------------------------------------------------------*/
8502 /* genRightShiftLiteral - right shifting by known count */
8503 /*-----------------------------------------------------------------*/
8505 genRightShiftLiteral (operand * left,
8511 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8514 D(emitcode ("; genRightShiftLiteral",""));
8516 freeAsmop (right, NULL, ic, TRUE);
8518 aopOp (left, ic, FALSE);
8519 aopOp (result, ic, FALSE);
8522 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8526 size = getDataSize (left);
8527 /* test the LEFT size !!! */
8529 /* I suppose that the left size >= result size */
8532 size = getDataSize (result);
8534 movLeft2Result (left, size, result, size, 0);
8537 else if (shCount >= (size * 8))
8540 /* get sign in acc.7 */
8541 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8543 addSign (result, LSB, sign);
8550 genrshOne (result, left, shCount, sign);
8554 genrshTwo (result, left, shCount, sign);
8558 genrshFour (result, left, shCount, sign);
8564 freeAsmop (left, NULL, ic, TRUE);
8565 freeAsmop (result, NULL, ic, TRUE);
8568 /*-----------------------------------------------------------------*/
8569 /* genSignedRightShift - right shift of signed number */
8570 /*-----------------------------------------------------------------*/
8572 genSignedRightShift (iCode * ic)
8574 operand *right, *left, *result;
8577 symbol *tlbl, *tlbl1;
8580 D(emitcode ("; genSignedRightShift",""));
8582 /* we do it the hard way put the shift count in b
8583 and loop thru preserving the sign */
8585 right = IC_RIGHT (ic);
8586 left = IC_LEFT (ic);
8587 result = IC_RESULT (ic);
8589 aopOp (right, ic, FALSE);
8592 if (AOP_TYPE (right) == AOP_LIT)
8594 genRightShiftLiteral (left, right, result, ic, 1);
8597 /* shift count is unknown then we have to form
8598 a loop get the loop count in B : Note: we take
8599 only the lower order byte since shifting
8600 more that 32 bits make no sense anyway, ( the
8601 largest size of an object can be only 32 bits ) */
8604 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8605 emitcode ("inc", "b");
8606 freeAsmop (right, NULL, ic, TRUE);
8607 aopOp (left, ic, FALSE);
8608 aopOp (result, ic, FALSE);
8610 /* now move the left to the result if they are not the
8612 if (!sameRegs (AOP (left), AOP (result)) &&
8613 AOP_SIZE (result) > 1)
8616 size = AOP_SIZE (result);
8620 l = aopGet (left, offset, FALSE, TRUE);
8621 if (*l == '@' && IS_AOP_PREG (result))
8624 emitcode ("mov", "a,%s", l);
8625 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8628 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8633 /* mov the highest order bit to OVR */
8634 tlbl = newiTempLabel (NULL);
8635 tlbl1 = newiTempLabel (NULL);
8637 size = AOP_SIZE (result);
8639 MOVA (aopGet (left, offset, FALSE, FALSE));
8640 emitcode ("rlc", "a");
8641 emitcode ("mov", "ov,c");
8642 /* if it is only one byte then */
8645 l = aopGet (left, 0, FALSE, FALSE);
8647 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8648 emitcode ("", "%05d$:", tlbl->key + 100);
8649 emitcode ("mov", "c,ov");
8650 emitcode ("rrc", "a");
8651 emitcode ("", "%05d$:", tlbl1->key + 100);
8652 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8654 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8658 reAdjustPreg (AOP (result));
8659 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8660 emitcode ("", "%05d$:", tlbl->key + 100);
8661 emitcode ("mov", "c,ov");
8664 l = aopGet (result, offset, FALSE, FALSE);
8666 emitcode ("rrc", "a");
8667 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8669 reAdjustPreg (AOP (result));
8670 emitcode ("", "%05d$:", tlbl1->key + 100);
8671 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8675 freeAsmop (left, NULL, ic, TRUE);
8676 freeAsmop (result, NULL, ic, TRUE);
8679 /*-----------------------------------------------------------------*/
8680 /* genRightShift - generate code for right shifting */
8681 /*-----------------------------------------------------------------*/
8683 genRightShift (iCode * ic)
8685 operand *right, *left, *result;
8689 symbol *tlbl, *tlbl1;
8692 D(emitcode ("; genRightShift",""));
8694 /* if signed then we do it the hard way preserve the
8695 sign bit moving it inwards */
8696 letype = getSpec (operandType (IC_LEFT (ic)));
8698 if (!SPEC_USIGN (letype))
8700 genSignedRightShift (ic);
8704 /* signed & unsigned types are treated the same : i.e. the
8705 signed is NOT propagated inwards : quoting from the
8706 ANSI - standard : "for E1 >> E2, is equivalent to division
8707 by 2**E2 if unsigned or if it has a non-negative value,
8708 otherwise the result is implementation defined ", MY definition
8709 is that the sign does not get propagated */
8711 right = IC_RIGHT (ic);
8712 left = IC_LEFT (ic);
8713 result = IC_RESULT (ic);
8715 aopOp (right, ic, FALSE);
8717 /* if the shift count is known then do it
8718 as efficiently as possible */
8719 if (AOP_TYPE (right) == AOP_LIT)
8721 genRightShiftLiteral (left, right, result, ic, 0);
8725 /* shift count is unknown then we have to form
8726 a loop get the loop count in B : Note: we take
8727 only the lower order byte since shifting
8728 more that 32 bits make no sense anyway, ( the
8729 largest size of an object can be only 32 bits ) */
8732 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8733 emitcode ("inc", "b");
8734 freeAsmop (right, NULL, ic, TRUE);
8735 aopOp (left, ic, FALSE);
8736 aopOp (result, ic, FALSE);
8738 /* now move the left to the result if they are not the
8740 if (!sameRegs (AOP (left), AOP (result)) &&
8741 AOP_SIZE (result) > 1)
8744 size = AOP_SIZE (result);
8748 l = aopGet (left, offset, FALSE, TRUE);
8749 if (*l == '@' && IS_AOP_PREG (result))
8752 emitcode ("mov", "a,%s", l);
8753 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8756 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8761 tlbl = newiTempLabel (NULL);
8762 tlbl1 = newiTempLabel (NULL);
8763 size = AOP_SIZE (result);
8766 /* if it is only one byte then */
8769 l = aopGet (left, 0, FALSE, FALSE);
8771 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8772 emitcode ("", "%05d$:", tlbl->key + 100);
8774 emitcode ("rrc", "a");
8775 emitcode ("", "%05d$:", tlbl1->key + 100);
8776 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8778 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8782 reAdjustPreg (AOP (result));
8783 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8784 emitcode ("", "%05d$:", tlbl->key + 100);
8788 l = aopGet (result, offset, FALSE, FALSE);
8790 emitcode ("rrc", "a");
8791 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8793 reAdjustPreg (AOP (result));
8795 emitcode ("", "%05d$:", tlbl1->key + 100);
8796 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8800 freeAsmop (left, NULL, ic, TRUE);
8801 freeAsmop (result, NULL, ic, TRUE);
8804 /*-----------------------------------------------------------------*/
8805 /* emitPtrByteGet - emits code to get a byte into A through a */
8806 /* pointer register (R0, R1, or DPTR). The */
8807 /* original value of A can be preserved in B. */
8808 /*-----------------------------------------------------------------*/
8810 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8817 emitcode ("mov", "b,a");
8818 emitcode ("mov", "a,@%s", rname);
8823 emitcode ("mov", "b,a");
8824 emitcode ("movx", "a,@%s", rname);
8829 emitcode ("mov", "b,a");
8830 emitcode ("movx", "a,@dptr");
8835 emitcode ("mov", "b,a");
8836 emitcode ("clr", "a");
8837 emitcode ("movc", "a,@a+dptr");
8843 emitcode ("push", "b");
8844 emitcode ("push", "acc");
8846 emitcode ("lcall", "__gptrget");
8848 emitcode ("pop", "b");
8853 /*-----------------------------------------------------------------*/
8854 /* emitPtrByteSet - emits code to set a byte from src through a */
8855 /* pointer register (R0, R1, or DPTR). */
8856 /*-----------------------------------------------------------------*/
8858 emitPtrByteSet (char *rname, int p_type, char *src)
8867 emitcode ("mov", "@%s,a", rname);
8870 emitcode ("mov", "@%s,%s", rname, src);
8875 emitcode ("movx", "@%s,a", rname);
8880 emitcode ("movx", "@dptr,a");
8885 emitcode ("lcall", "__gptrput");
8890 /*-----------------------------------------------------------------*/
8891 /* genUnpackBits - generates code for unpacking bits */
8892 /*-----------------------------------------------------------------*/
8894 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8896 int offset = 0; /* result byte offset */
8897 int rsize; /* result size */
8898 int rlen = 0; /* remaining bitfield length */
8899 sym_link *etype; /* bitfield type information */
8900 int blen; /* bitfield length */
8901 int bstr; /* bitfield starting bit within byte */
8904 D(emitcode ("; genUnpackBits",""));
8906 etype = getSpec (operandType (result));
8907 rsize = getSize (operandType (result));
8908 blen = SPEC_BLEN (etype);
8909 bstr = SPEC_BSTR (etype);
8911 if (ifx && blen <= 8)
8913 emitPtrByteGet (rname, ptype, FALSE);
8916 SNPRINTF (buffer, sizeof(buffer),
8918 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8923 emitcode ("anl", "a,#0x%02x",
8924 (((unsigned char) -1) >> (8 - blen)) << bstr);
8925 genIfxJump (ifx, "a", NULL, NULL, NULL);
8931 /* If the bitfield length is less than a byte */
8934 emitPtrByteGet (rname, ptype, FALSE);
8936 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8937 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8941 /* Bit field did not fit in a byte. Copy all
8942 but the partial byte at the end. */
8943 for (rlen=blen;rlen>=8;rlen-=8)
8945 emitPtrByteGet (rname, ptype, FALSE);
8946 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8948 emitcode ("inc", "%s", rname);
8951 /* Handle the partial byte at the end */
8954 emitPtrByteGet (rname, ptype, FALSE);
8955 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8956 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8964 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
8969 /*-----------------------------------------------------------------*/
8970 /* genDataPointerGet - generates code when ptr offset is known */
8971 /*-----------------------------------------------------------------*/
8973 genDataPointerGet (operand * left,
8979 int size, offset = 0;
8981 D(emitcode ("; genDataPointerGet",""));
8983 aopOp (result, ic, TRUE);
8985 /* get the string representation of the name */
8986 l = aopGet (left, 0, FALSE, TRUE);
8987 size = AOP_SIZE (result);
8991 sprintf (buffer, "(%s + %d)", l + 1, offset);
8993 sprintf (buffer, "%s", l + 1);
8994 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
8997 freeAsmop (left, NULL, ic, TRUE);
8998 freeAsmop (result, NULL, ic, TRUE);
9001 /*-----------------------------------------------------------------*/
9002 /* genNearPointerGet - emitcode for near pointer fetch */
9003 /*-----------------------------------------------------------------*/
9005 genNearPointerGet (operand * left,
9014 sym_link *rtype, *retype;
9015 sym_link *ltype = operandType (left);
9018 D(emitcode ("; genNearPointerGet",""));
9020 rtype = operandType (result);
9021 retype = getSpec (rtype);
9023 aopOp (left, ic, FALSE);
9025 /* if left is rematerialisable and
9026 result is not bitfield variable type and
9027 the left is pointer to data space i.e
9028 lower 128 bytes of space */
9029 if (AOP_TYPE (left) == AOP_IMMD &&
9030 !IS_BITFIELD (retype) &&
9031 DCL_TYPE (ltype) == POINTER)
9033 genDataPointerGet (left, result, ic);
9037 /* if the value is already in a pointer register
9038 then don't need anything more */
9039 if (!AOP_INPREG (AOP (left)))
9041 if (IS_AOP_PREG (left))
9043 // Aha, it is a pointer, just in disguise.
9044 rname = aopGet (left, 0, FALSE, FALSE);
9047 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9048 __FILE__, __LINE__);
9053 emitcode ("mov", "a%s,%s", rname + 1, rname);
9054 rname++; // skip the '@'.
9059 /* otherwise get a free pointer register */
9061 preg = getFreePtr (ic, &aop, FALSE);
9062 emitcode ("mov", "%s,%s",
9064 aopGet (left, 0, FALSE, TRUE));
9069 rname = aopGet (left, 0, FALSE, FALSE);
9071 //aopOp (result, ic, FALSE);
9072 aopOp (result, ic, result?TRUE:FALSE);
9074 /* if bitfield then unpack the bits */
9075 if (IS_BITFIELD (retype))
9076 genUnpackBits (result, rname, POINTER, ifx);
9079 /* we have can just get the values */
9080 int size = AOP_SIZE (result);
9085 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9088 emitcode ("mov", "a,@%s", rname);
9090 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9094 sprintf (buffer, "@%s", rname);
9095 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9099 emitcode ("inc", "%s", rname);
9103 /* now some housekeeping stuff */
9104 if (aop) /* we had to allocate for this iCode */
9106 if (pi) { /* post increment present */
9107 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9109 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9113 /* we did not allocate which means left
9114 already in a pointer register, then
9115 if size > 0 && this could be used again
9116 we have to point it back to where it
9118 if ((AOP_SIZE (result) > 1 &&
9119 !OP_SYMBOL (left)->remat &&
9120 (OP_SYMBOL (left)->liveTo > ic->seq ||
9124 int size = AOP_SIZE (result) - 1;
9126 emitcode ("dec", "%s", rname);
9130 if (ifx && !ifx->generated)
9132 genIfxJump (ifx, "a", left, NULL, result);
9136 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9137 freeAsmop (left, NULL, ic, TRUE);
9138 if (pi) pi->generated = 1;
9141 /*-----------------------------------------------------------------*/
9142 /* genPagedPointerGet - emitcode for paged pointer fetch */
9143 /*-----------------------------------------------------------------*/
9145 genPagedPointerGet (operand * left,
9154 sym_link *rtype, *retype;
9156 D(emitcode ("; genPagedPointerGet",""));
9158 rtype = operandType (result);
9159 retype = getSpec (rtype);
9161 aopOp (left, ic, FALSE);
9163 /* if the value is already in a pointer register
9164 then don't need anything more */
9165 if (!AOP_INPREG (AOP (left)))
9167 /* otherwise get a free pointer register */
9169 preg = getFreePtr (ic, &aop, FALSE);
9170 emitcode ("mov", "%s,%s",
9172 aopGet (left, 0, FALSE, TRUE));
9176 rname = aopGet (left, 0, FALSE, FALSE);
9178 aopOp (result, ic, FALSE);
9180 /* if bitfield then unpack the bits */
9181 if (IS_BITFIELD (retype))
9182 genUnpackBits (result, rname, PPOINTER, ifx);
9185 /* we have can just get the values */
9186 int size = AOP_SIZE (result);
9192 emitcode ("movx", "a,@%s", rname);
9194 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9199 emitcode ("inc", "%s", rname);
9203 /* now some housekeeping stuff */
9204 if (aop) /* we had to allocate for this iCode */
9206 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9207 freeAsmop (NULL, aop, ic, TRUE);
9211 /* we did not allocate which means left
9212 already in a pointer register, then
9213 if size > 0 && this could be used again
9214 we have to point it back to where it
9216 if ((AOP_SIZE (result) > 1 &&
9217 !OP_SYMBOL (left)->remat &&
9218 (OP_SYMBOL (left)->liveTo > ic->seq ||
9222 int size = AOP_SIZE (result) - 1;
9224 emitcode ("dec", "%s", rname);
9228 if (ifx && !ifx->generated)
9230 genIfxJump (ifx, "a", left, NULL, result);
9234 freeAsmop (left, NULL, ic, TRUE);
9235 freeAsmop (result, NULL, ic, TRUE);
9236 if (pi) pi->generated = 1;
9240 /*--------------------------------------------------------------------*/
9241 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9242 /*--------------------------------------------------------------------*/
9244 loadDptrFromOperand (operand *op, bool loadBToo)
9246 if (AOP_TYPE (op) != AOP_STR)
9248 /* if this is rematerializable */
9249 if (AOP_TYPE (op) == AOP_IMMD)
9251 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9254 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9255 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9258 wassertl(FALSE, "need pointerCode");
9259 emitcode ("", "; mov b,???");
9260 /* genPointerGet and genPointerSet originally did different
9261 ** things for this case. Both seem wrong.
9262 ** from genPointerGet:
9263 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9264 ** from genPointerSet:
9265 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9270 else if (AOP_TYPE (op) == AOP_DPTR)
9274 MOVA (aopGet (op, 0, FALSE, FALSE));
9275 emitcode ("push", "acc");
9276 MOVA (aopGet (op, 1, FALSE, FALSE));
9277 emitcode ("push", "acc");
9278 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9279 emitcode ("pop", "dph");
9280 emitcode ("pop", "dpl");
9284 MOVA (aopGet (op, 0, FALSE, FALSE));
9285 emitcode ("push", "acc");
9286 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9287 emitcode ("pop", "dpl");
9291 { /* we need to get it byte by byte */
9292 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9293 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9295 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9300 /*-----------------------------------------------------------------*/
9301 /* genFarPointerGet - gget value from far space */
9302 /*-----------------------------------------------------------------*/
9304 genFarPointerGet (operand * left,
9305 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9308 sym_link *retype = getSpec (operandType (result));
9310 D(emitcode ("; genFarPointerGet",""));
9312 aopOp (left, ic, FALSE);
9313 loadDptrFromOperand (left, FALSE);
9315 /* so dptr now contains the address */
9316 aopOp (result, ic, FALSE);
9318 /* if bit then unpack */
9319 if (IS_BITFIELD (retype))
9320 genUnpackBits (result, "dptr", FPOINTER, ifx);
9323 size = AOP_SIZE (result);
9328 emitcode ("movx", "a,@dptr");
9330 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9332 emitcode ("inc", "dptr");
9336 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9338 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9339 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9343 if (ifx && !ifx->generated)
9345 genIfxJump (ifx, "a", left, NULL, result);
9348 freeAsmop (left, NULL, ic, TRUE);
9349 freeAsmop (result, NULL, ic, TRUE);
9352 /*-----------------------------------------------------------------*/
9353 /* genCodePointerGet - gget value from code space */
9354 /*-----------------------------------------------------------------*/
9356 genCodePointerGet (operand * left,
9357 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9360 sym_link *retype = getSpec (operandType (result));
9362 D(emitcode ("; genCodePointerGet",""));
9364 aopOp (left, ic, FALSE);
9365 loadDptrFromOperand (left, FALSE);
9367 /* so dptr now contains the address */
9368 aopOp (result, ic, FALSE);
9370 /* if bit then unpack */
9371 if (IS_BITFIELD (retype))
9372 genUnpackBits (result, "dptr", CPOINTER, ifx);
9375 size = AOP_SIZE (result);
9382 emitcode ("clr", "a");
9383 emitcode ("movc", "a,@a+dptr");
9385 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9386 emitcode ("inc", "dptr");
9390 emitcode ("mov", "a,#0x%02x", offset);
9391 emitcode ("movc", "a,@a+dptr");
9393 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9398 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9400 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9401 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9405 if (ifx && !ifx->generated)
9407 genIfxJump (ifx, "a", left, NULL, result);
9410 freeAsmop (left, NULL, ic, TRUE);
9411 freeAsmop (result, NULL, ic, TRUE);
9414 /*-----------------------------------------------------------------*/
9415 /* genGenPointerGet - gget value from generic pointer space */
9416 /*-----------------------------------------------------------------*/
9418 genGenPointerGet (operand * left,
9419 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9422 sym_link *retype = getSpec (operandType (result));
9424 D(emitcode ("; genGenPointerGet",""));
9426 aopOp (left, ic, FALSE);
9427 loadDptrFromOperand (left, TRUE);
9429 /* so dptr know contains the address */
9430 aopOp (result, ic, FALSE);
9432 /* if bit then unpack */
9433 if (IS_BITFIELD (retype))
9434 genUnpackBits (result, "dptr", GPOINTER, ifx);
9437 size = AOP_SIZE (result);
9442 emitcode ("lcall", "__gptrget");
9444 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9446 emitcode ("inc", "dptr");
9450 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9452 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9453 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9457 if (ifx && !ifx->generated)
9459 genIfxJump (ifx, "a", left, NULL, result);
9463 freeAsmop (left, NULL, ic, TRUE);
9464 freeAsmop (result, NULL, ic, TRUE);
9467 /*-----------------------------------------------------------------*/
9468 /* genPointerGet - generate code for pointer get */
9469 /*-----------------------------------------------------------------*/
9471 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9473 operand *left, *result;
9474 sym_link *type, *etype;
9477 D(emitcode ("; genPointerGet",""));
9479 left = IC_LEFT (ic);
9480 result = IC_RESULT (ic);
9482 if (getSize (operandType (result))>1)
9485 /* depending on the type of pointer we need to
9486 move it to the correct pointer register */
9487 type = operandType (left);
9488 etype = getSpec (type);
9489 /* if left is of type of pointer then it is simple */
9490 if (IS_PTR (type) && !IS_FUNC (type->next))
9491 p_type = DCL_TYPE (type);
9494 /* we have to go by the storage class */
9495 p_type = PTR_TYPE (SPEC_OCLS (etype));
9498 /* special case when cast remat */
9499 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9500 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9501 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9502 type = operandType (left);
9503 p_type = DCL_TYPE (type);
9505 /* now that we have the pointer type we assign
9506 the pointer values */
9512 genNearPointerGet (left, result, ic, pi, ifx);
9516 genPagedPointerGet (left, result, ic, pi, ifx);
9520 genFarPointerGet (left, result, ic, pi, ifx);
9524 genCodePointerGet (left, result, ic, pi, ifx);
9528 genGenPointerGet (left, result, ic, pi, ifx);
9536 /*-----------------------------------------------------------------*/
9537 /* genPackBits - generates code for packed bit storage */
9538 /*-----------------------------------------------------------------*/
9540 genPackBits (sym_link * etype,
9542 char *rname, int p_type)
9544 int offset = 0; /* source byte offset */
9545 int rlen = 0; /* remaining bitfield length */
9546 int blen; /* bitfield length */
9547 int bstr; /* bitfield starting bit within byte */
9548 int litval; /* source literal value (if AOP_LIT) */
9549 unsigned char mask; /* bitmask within current byte */
9551 D(emitcode ("; genPackBits",""));
9553 blen = SPEC_BLEN (etype);
9554 bstr = SPEC_BSTR (etype);
9556 /* If the bitfield length is less than a byte */
9559 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9560 (unsigned char) (0xFF >> (8 - bstr)));
9562 if (AOP_TYPE (right) == AOP_LIT)
9564 /* Case with a bitfield length <8 and literal source
9566 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9568 litval &= (~mask) & 0xff;
9569 emitPtrByteGet (rname, p_type, FALSE);
9570 if ((mask|litval)!=0xff)
9571 emitcode ("anl","a,#0x%02x", mask);
9573 emitcode ("orl","a,#0x%02x", litval);
9577 if ((blen==1) && (p_type!=GPOINTER))
9579 /* Case with a bitfield length == 1 and no generic pointer
9581 if (AOP_TYPE (right) == AOP_CRY)
9582 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9585 MOVA (aopGet (right, 0, FALSE, FALSE));
9586 emitcode ("rrc","a");
9588 emitPtrByteGet (rname, p_type, FALSE);
9589 emitcode ("mov","acc.%d,c",bstr);
9594 /* Case with a bitfield length < 8 and arbitrary source
9596 MOVA (aopGet (right, 0, FALSE, FALSE));
9597 /* shift and mask source value */
9599 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9602 /* transfer A to B and get next byte */
9603 emitPtrByteGet (rname, p_type, TRUE);
9605 emitcode ("anl", "a,#0x%02x", mask);
9606 emitcode ("orl", "a,b");
9607 if (p_type == GPOINTER)
9608 emitcode ("pop", "b");
9614 emitPtrByteSet (rname, p_type, "a");
9618 /* Bit length is greater than 7 bits. In this case, copy */
9619 /* all except the partial byte at the end */
9620 for (rlen=blen;rlen>=8;rlen-=8)
9622 emitPtrByteSet (rname, p_type,
9623 aopGet (right, offset++, FALSE, TRUE) );
9625 emitcode ("inc", "%s", rname);
9628 /* If there was a partial byte at the end */
9631 mask = (((unsigned char) -1 << rlen) & 0xff);
9633 if (AOP_TYPE (right) == AOP_LIT)
9635 /* Case with partial byte and literal source
9637 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9638 litval >>= (blen-rlen);
9639 litval &= (~mask) & 0xff;
9640 emitPtrByteGet (rname, p_type, FALSE);
9641 if ((mask|litval)!=0xff)
9642 emitcode ("anl","a,#0x%02x", mask);
9644 emitcode ("orl","a,#0x%02x", litval);
9649 /* Case with partial byte and arbitrary source
9651 MOVA (aopGet (right, offset++, FALSE, FALSE));
9652 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9655 /* transfer A to B and get next byte */
9656 emitPtrByteGet (rname, p_type, TRUE);
9658 emitcode ("anl", "a,#0x%02x", mask);
9659 emitcode ("orl", "a,b");
9660 if (p_type == GPOINTER)
9661 emitcode ("pop", "b");
9665 emitPtrByteSet (rname, p_type, "a");
9671 /*-----------------------------------------------------------------*/
9672 /* genDataPointerSet - remat pointer to data space */
9673 /*-----------------------------------------------------------------*/
9675 genDataPointerSet (operand * right,
9679 int size, offset = 0;
9680 char *l, buffer[256];
9682 D(emitcode ("; genDataPointerSet",""));
9684 aopOp (right, ic, FALSE);
9686 l = aopGet (result, 0, FALSE, TRUE);
9687 size = AOP_SIZE (right);
9691 sprintf (buffer, "(%s + %d)", l + 1, offset);
9693 sprintf (buffer, "%s", l + 1);
9694 emitcode ("mov", "%s,%s", buffer,
9695 aopGet (right, offset++, FALSE, FALSE));
9698 freeAsmop (right, NULL, ic, TRUE);
9699 freeAsmop (result, NULL, ic, TRUE);
9702 /*-----------------------------------------------------------------*/
9703 /* genNearPointerSet - emitcode for near pointer put */
9704 /*-----------------------------------------------------------------*/
9706 genNearPointerSet (operand * right,
9714 sym_link *retype, *letype;
9715 sym_link *ptype = operandType (result);
9717 D(emitcode ("; genNearPointerSet",""));
9719 retype = getSpec (operandType (right));
9720 letype = getSpec (ptype);
9721 aopOp (result, ic, FALSE);
9723 /* if the result is rematerializable &
9724 in data space & not a bit variable */
9725 if (AOP_TYPE (result) == AOP_IMMD &&
9726 DCL_TYPE (ptype) == POINTER &&
9727 !IS_BITVAR (retype) &&
9728 !IS_BITVAR (letype))
9730 genDataPointerSet (right, result, ic);
9734 /* if the value is already in a pointer register
9735 then don't need anything more */
9736 if (!AOP_INPREG (AOP (result)))
9739 //AOP_TYPE (result) == AOP_STK
9743 // Aha, it is a pointer, just in disguise.
9744 rname = aopGet (result, 0, FALSE, FALSE);
9747 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9748 __FILE__, __LINE__);
9753 emitcode ("mov", "a%s,%s", rname + 1, rname);
9754 rname++; // skip the '@'.
9759 /* otherwise get a free pointer register */
9761 preg = getFreePtr (ic, &aop, FALSE);
9762 emitcode ("mov", "%s,%s",
9764 aopGet (result, 0, FALSE, TRUE));
9770 rname = aopGet (result, 0, FALSE, FALSE);
9773 aopOp (right, ic, FALSE);
9775 /* if bitfield then unpack the bits */
9776 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9777 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9780 /* we have can just get the values */
9781 int size = AOP_SIZE (right);
9786 l = aopGet (right, offset, FALSE, TRUE);
9790 emitcode ("mov", "@%s,a", rname);
9793 emitcode ("mov", "@%s,%s", rname, l);
9795 emitcode ("inc", "%s", rname);
9800 /* now some housekeeping stuff */
9801 if (aop) /* we had to allocate for this iCode */
9804 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9805 freeAsmop (NULL, aop, ic, TRUE);
9809 /* we did not allocate which means left
9810 already in a pointer register, then
9811 if size > 0 && this could be used again
9812 we have to point it back to where it
9814 if ((AOP_SIZE (right) > 1 &&
9815 !OP_SYMBOL (result)->remat &&
9816 (OP_SYMBOL (result)->liveTo > ic->seq ||
9820 int size = AOP_SIZE (right) - 1;
9822 emitcode ("dec", "%s", rname);
9827 if (pi) pi->generated = 1;
9828 freeAsmop (result, NULL, ic, TRUE);
9829 freeAsmop (right, NULL, ic, TRUE);
9832 /*-----------------------------------------------------------------*/
9833 /* genPagedPointerSet - emitcode for Paged pointer put */
9834 /*-----------------------------------------------------------------*/
9836 genPagedPointerSet (operand * right,
9844 sym_link *retype, *letype;
9846 D(emitcode ("; genPagedPointerSet",""));
9848 retype = getSpec (operandType (right));
9849 letype = getSpec (operandType (result));
9851 aopOp (result, ic, FALSE);
9853 /* if the value is already in a pointer register
9854 then don't need anything more */
9855 if (!AOP_INPREG (AOP (result)))
9857 /* otherwise get a free pointer register */
9859 preg = getFreePtr (ic, &aop, FALSE);
9860 emitcode ("mov", "%s,%s",
9862 aopGet (result, 0, FALSE, TRUE));
9866 rname = aopGet (result, 0, FALSE, FALSE);
9868 aopOp (right, ic, FALSE);
9870 /* if bitfield then unpack the bits */
9871 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9872 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9875 /* we have can just get the values */
9876 int size = AOP_SIZE (right);
9881 l = aopGet (right, offset, FALSE, TRUE);
9884 emitcode ("movx", "@%s,a", rname);
9887 emitcode ("inc", "%s", rname);
9893 /* now some housekeeping stuff */
9894 if (aop) /* we had to allocate for this iCode */
9897 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9898 freeAsmop (NULL, aop, ic, TRUE);
9902 /* we did not allocate which means left
9903 already in a pointer register, then
9904 if size > 0 && this could be used again
9905 we have to point it back to where it
9907 if (AOP_SIZE (right) > 1 &&
9908 !OP_SYMBOL (result)->remat &&
9909 (OP_SYMBOL (result)->liveTo > ic->seq ||
9912 int size = AOP_SIZE (right) - 1;
9914 emitcode ("dec", "%s", rname);
9919 if (pi) pi->generated = 1;
9920 freeAsmop (result, NULL, ic, TRUE);
9921 freeAsmop (right, NULL, ic, TRUE);
9926 /*-----------------------------------------------------------------*/
9927 /* genFarPointerSet - set value from far space */
9928 /*-----------------------------------------------------------------*/
9930 genFarPointerSet (operand * right,
9931 operand * result, iCode * ic, iCode * pi)
9934 sym_link *retype = getSpec (operandType (right));
9935 sym_link *letype = getSpec (operandType (result));
9937 D(emitcode ("; genFarPointerSet",""));
9939 aopOp (result, ic, FALSE);
9940 loadDptrFromOperand (result, FALSE);
9942 /* so dptr know contains the address */
9943 aopOp (right, ic, FALSE);
9945 /* if bit then unpack */
9946 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9947 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9950 size = AOP_SIZE (right);
9955 char *l = aopGet (right, offset++, FALSE, FALSE);
9957 emitcode ("movx", "@dptr,a");
9959 emitcode ("inc", "dptr");
9962 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9963 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9964 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9967 freeAsmop (result, NULL, ic, TRUE);
9968 freeAsmop (right, NULL, ic, TRUE);
9971 /*-----------------------------------------------------------------*/
9972 /* genGenPointerSet - set value from generic pointer space */
9973 /*-----------------------------------------------------------------*/
9975 genGenPointerSet (operand * right,
9976 operand * result, iCode * ic, iCode * pi)
9979 sym_link *retype = getSpec (operandType (right));
9980 sym_link *letype = getSpec (operandType (result));
9982 D(emitcode ("; genGenPointerSet",""));
9984 aopOp (result, ic, FALSE);
9985 loadDptrFromOperand (result, TRUE);
9987 /* so dptr know contains the address */
9988 aopOp (right, ic, FALSE);
9990 /* if bit then unpack */
9991 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9992 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9995 size = AOP_SIZE (right);
10000 char *l = aopGet (right, offset++, FALSE, FALSE);
10002 emitcode ("lcall", "__gptrput");
10004 emitcode ("inc", "dptr");
10008 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10009 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10010 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10013 freeAsmop (result, NULL, ic, TRUE);
10014 freeAsmop (right, NULL, ic, TRUE);
10017 /*-----------------------------------------------------------------*/
10018 /* genPointerSet - stores the value into a pointer location */
10019 /*-----------------------------------------------------------------*/
10021 genPointerSet (iCode * ic, iCode *pi)
10023 operand *right, *result;
10024 sym_link *type, *etype;
10027 D(emitcode ("; genPointerSet",""));
10029 right = IC_RIGHT (ic);
10030 result = IC_RESULT (ic);
10032 /* depending on the type of pointer we need to
10033 move it to the correct pointer register */
10034 type = operandType (result);
10035 etype = getSpec (type);
10036 /* if left is of type of pointer then it is simple */
10037 if (IS_PTR (type) && !IS_FUNC (type->next))
10039 p_type = DCL_TYPE (type);
10043 /* we have to go by the storage class */
10044 p_type = PTR_TYPE (SPEC_OCLS (etype));
10047 /* special case when cast remat */
10048 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10049 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10050 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10051 type = operandType (result);
10052 p_type = DCL_TYPE (type);
10054 /* now that we have the pointer type we assign
10055 the pointer values */
10061 genNearPointerSet (right, result, ic, pi);
10065 genPagedPointerSet (right, result, ic, pi);
10069 genFarPointerSet (right, result, ic, pi);
10073 genGenPointerSet (right, result, ic, pi);
10077 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10078 "genPointerSet: illegal pointer type");
10083 /*-----------------------------------------------------------------*/
10084 /* genIfx - generate code for Ifx statement */
10085 /*-----------------------------------------------------------------*/
10087 genIfx (iCode * ic, iCode * popIc)
10089 operand *cond = IC_COND (ic);
10093 D(emitcode ("; genIfx",""));
10095 aopOp (cond, ic, FALSE);
10097 /* get the value into acc */
10098 if (AOP_TYPE (cond) != AOP_CRY)
10103 if (AOP(cond)->aopu.aop_dir)
10104 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10106 /* the result is now in the accumulator or a directly addressable bit */
10107 freeAsmop (cond, NULL, ic, TRUE);
10109 /* if there was something to be popped then do it */
10113 /* if the condition is a bit variable */
10115 genIfxJump(ic, dup, NULL, NULL, NULL);
10116 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10117 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10118 else if (isbit && !IS_ITEMP (cond))
10119 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10121 genIfxJump (ic, "a", NULL, NULL, NULL);
10126 /*-----------------------------------------------------------------*/
10127 /* genAddrOf - generates code for address of */
10128 /*-----------------------------------------------------------------*/
10130 genAddrOf (iCode * ic)
10132 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10135 D(emitcode ("; genAddrOf",""));
10137 aopOp (IC_RESULT (ic), ic, FALSE);
10139 /* if the operand is on the stack then we
10140 need to get the stack offset of this
10144 /* if it has an offset then we need to compute
10148 emitcode ("mov", "a,%s", SYM_BP (sym));
10149 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10150 ((char) (sym->stack - _G.nRegsSaved)) :
10151 ((char) sym->stack)) & 0xff);
10152 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10156 /* we can just move _bp */
10157 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10159 /* fill the result with zero */
10160 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10165 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10171 /* object not on stack then we need the name */
10172 size = AOP_SIZE (IC_RESULT (ic));
10177 char s[SDCC_NAME_MAX];
10179 sprintf (s, "#(%s >> %d)",
10183 sprintf (s, "#%s", sym->rname);
10184 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10188 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10192 /*-----------------------------------------------------------------*/
10193 /* genFarFarAssign - assignment when both are in far space */
10194 /*-----------------------------------------------------------------*/
10196 genFarFarAssign (operand * result, operand * right, iCode * ic)
10198 int size = AOP_SIZE (right);
10202 D(emitcode ("; genFarFarAssign",""));
10204 /* first push the right side on to the stack */
10207 l = aopGet (right, offset++, FALSE, FALSE);
10209 emitcode ("push", "acc");
10212 freeAsmop (right, NULL, ic, FALSE);
10213 /* now assign DPTR to result */
10214 aopOp (result, ic, FALSE);
10215 size = AOP_SIZE (result);
10218 emitcode ("pop", "acc");
10219 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10221 freeAsmop (result, NULL, ic, FALSE);
10225 /*-----------------------------------------------------------------*/
10226 /* genAssign - generate code for assignment */
10227 /*-----------------------------------------------------------------*/
10229 genAssign (iCode * ic)
10231 operand *result, *right;
10233 unsigned long lit = 0L;
10235 D(emitcode("; genAssign",""));
10237 result = IC_RESULT (ic);
10238 right = IC_RIGHT (ic);
10240 /* if they are the same */
10241 if (operandsEqu (result, right) &&
10242 !isOperandVolatile (result, FALSE) &&
10243 !isOperandVolatile (right, FALSE))
10246 aopOp (right, ic, FALSE);
10248 /* special case both in far space */
10249 if (AOP_TYPE (right) == AOP_DPTR &&
10250 IS_TRUE_SYMOP (result) &&
10251 isOperandInFarSpace (result))
10254 genFarFarAssign (result, right, ic);
10258 aopOp (result, ic, TRUE);
10260 /* if they are the same registers */
10261 if (sameRegs (AOP (right), AOP (result)) &&
10262 !isOperandVolatile (result, FALSE) &&
10263 !isOperandVolatile (right, FALSE))
10266 /* if the result is a bit */
10267 if (AOP_TYPE (result) == AOP_CRY)
10270 /* if the right size is a literal then
10271 we know what the value is */
10272 if (AOP_TYPE (right) == AOP_LIT)
10274 if (((int) operandLitValue (right)))
10275 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10277 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10281 /* the right is also a bit variable */
10282 if (AOP_TYPE (right) == AOP_CRY)
10284 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10285 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10289 /* we need to or */
10291 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10295 /* bit variables done */
10297 size = AOP_SIZE (result);
10299 if (AOP_TYPE (right) == AOP_LIT)
10300 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10302 (AOP_TYPE (result) != AOP_REG) &&
10303 (AOP_TYPE (right) == AOP_LIT) &&
10304 !IS_FLOAT (operandType (right)) &&
10307 while ((size) && (lit))
10310 aopGet (right, offset, FALSE, FALSE),
10312 isOperandVolatile (result, FALSE));
10317 emitcode ("clr", "a");
10320 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10329 aopGet (right, offset, FALSE, FALSE),
10331 isOperandVolatile (result, FALSE));
10337 freeAsmop (right, NULL, ic, TRUE);
10338 freeAsmop (result, NULL, ic, TRUE);
10341 /*-----------------------------------------------------------------*/
10342 /* genJumpTab - generates code for jump table */
10343 /*-----------------------------------------------------------------*/
10345 genJumpTab (iCode * ic)
10347 symbol *jtab,*jtablo,*jtabhi;
10349 unsigned int count;
10351 D(emitcode ("; genJumpTab",""));
10353 count = elementsInSet( IC_JTLABELS (ic) );
10357 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10358 if the switch argument is in a register.
10359 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10360 /* (MB) What if peephole converts ljmp to sjmp or ret ???
10361 How will multiply by three be updated ???*/
10362 aopOp (IC_JTCOND (ic), ic, FALSE);
10363 /* get the condition into accumulator */
10364 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10366 /* multiply by three */
10367 emitcode ("add", "a,acc");
10368 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10369 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10371 jtab = newiTempLabel (NULL);
10372 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10373 emitcode ("jmp", "@a+dptr");
10374 emitcode ("", "%05d$:", jtab->key + 100);
10375 /* now generate the jump labels */
10376 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10377 jtab = setNextItem (IC_JTLABELS (ic)))
10378 emitcode ("ljmp", "%05d$", jtab->key + 100);
10382 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10383 if the switch argument is in a register.
10384 For n>6 this algorithm may be more compact */
10385 jtablo = newiTempLabel (NULL);
10386 jtabhi = newiTempLabel (NULL);
10388 /* get the condition into accumulator.
10389 Using b as temporary storage, if register push/pop is needed */
10390 aopOp (IC_JTCOND (ic), ic, FALSE);
10391 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10392 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10393 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10395 // (MB) what if B is in use???
10396 wassertl(!BINUSE, "B was in use");
10397 emitcode ("mov", "b,%s", l);
10400 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10404 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10405 emitcode ("movc", "a,@a+pc");
10406 emitcode ("push", "acc");
10409 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10410 emitcode ("movc", "a,@a+pc");
10411 emitcode ("push", "acc");
10415 /* this scales up to n<=255, but needs two more bytes
10416 and changes dptr */
10417 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10418 emitcode ("movc", "a,@a+dptr");
10419 emitcode ("push", "acc");
10422 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10423 emitcode ("movc", "a,@a+dptr");
10424 emitcode ("push", "acc");
10427 emitcode ("ret", "");
10429 /* now generate jump table, LSB */
10430 emitcode ("", "%05d$:", jtablo->key + 100);
10431 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10432 jtab = setNextItem (IC_JTLABELS (ic)))
10433 emitcode (".db", "%05d$", jtab->key + 100);
10435 /* now generate jump table, MSB */
10436 emitcode ("", "%05d$:", jtabhi->key + 100);
10437 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10438 jtab = setNextItem (IC_JTLABELS (ic)))
10439 emitcode (".db", "%05d$>>8", jtab->key + 100);
10443 /*-----------------------------------------------------------------*/
10444 /* genCast - gen code for casting */
10445 /*-----------------------------------------------------------------*/
10447 genCast (iCode * ic)
10449 operand *result = IC_RESULT (ic);
10450 sym_link *ctype = operandType (IC_LEFT (ic));
10451 sym_link *rtype = operandType (IC_RIGHT (ic));
10452 operand *right = IC_RIGHT (ic);
10455 D(emitcode("; genCast",""));
10457 /* if they are equivalent then do nothing */
10458 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10461 aopOp (right, ic, FALSE);
10462 aopOp (result, ic, FALSE);
10464 /* if the result is a bit (and not a bitfield) */
10465 // if (AOP_TYPE (result) == AOP_CRY)
10466 if (IS_BITVAR (OP_SYMBOL (result)->type)
10467 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10469 /* if the right size is a literal then
10470 we know what the value is */
10471 if (AOP_TYPE (right) == AOP_LIT)
10473 if (((int) operandLitValue (right)))
10474 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10476 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10481 /* the right is also a bit variable */
10482 if (AOP_TYPE (right) == AOP_CRY)
10484 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10485 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10489 /* we need to or */
10491 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10496 /* if they are the same size : or less */
10497 if (AOP_SIZE (result) <= AOP_SIZE (right))
10500 /* if they are in the same place */
10501 if (sameRegs (AOP (right), AOP (result)))
10504 /* if they in different places then copy */
10505 size = AOP_SIZE (result);
10510 aopGet (right, offset, FALSE, FALSE),
10512 isOperandVolatile (result, FALSE));
10519 /* if the result is of type pointer */
10520 if (IS_PTR (ctype))
10524 sym_link *type = operandType (right);
10525 sym_link *etype = getSpec (type);
10527 /* pointer to generic pointer */
10528 if (IS_GENPTR (ctype))
10531 p_type = DCL_TYPE (type);
10534 if (SPEC_SCLS(etype)==S_REGISTER) {
10535 // let's assume it is a generic pointer
10538 /* we have to go by the storage class */
10539 p_type = PTR_TYPE (SPEC_OCLS (etype));
10543 /* the first two bytes are known */
10544 size = GPTRSIZE - 1;
10549 aopGet (right, offset, FALSE, FALSE),
10551 isOperandVolatile (result, FALSE));
10554 /* the last byte depending on type */
10556 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10561 // pointerTypeToGPByte will have bitched.
10565 sprintf(gpValStr, "#0x%x", gpVal);
10566 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10571 /* just copy the pointers */
10572 size = AOP_SIZE (result);
10577 aopGet (right, offset, FALSE, FALSE),
10579 isOperandVolatile (result, FALSE));
10585 /* so we now know that the size of destination is greater
10586 than the size of the source */
10587 /* we move to result for the size of source */
10588 size = AOP_SIZE (right);
10593 aopGet (right, offset, FALSE, FALSE),
10595 isOperandVolatile (result, FALSE));
10599 /* now depending on the sign of the source && destination */
10600 size = AOP_SIZE (result) - AOP_SIZE (right);
10601 /* if unsigned or not an integral type */
10602 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10605 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10609 /* we need to extend the sign :{ */
10610 char *l = aopGet (right, AOP_SIZE (right) - 1,
10613 emitcode ("rlc", "a");
10614 emitcode ("subb", "a,acc");
10616 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10619 /* we are done hurray !!!! */
10622 freeAsmop (right, NULL, ic, TRUE);
10623 freeAsmop (result, NULL, ic, TRUE);
10627 /*-----------------------------------------------------------------*/
10628 /* genDjnz - generate decrement & jump if not zero instrucion */
10629 /*-----------------------------------------------------------------*/
10631 genDjnz (iCode * ic, iCode * ifx)
10633 symbol *lbl, *lbl1;
10637 D(emitcode ("; genDjnz",""));
10639 /* if the if condition has a false label
10640 then we cannot save */
10641 if (IC_FALSE (ifx))
10644 /* if the minus is not of the form
10646 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10647 !IS_OP_LITERAL (IC_RIGHT (ic)))
10650 if (operandLitValue (IC_RIGHT (ic)) != 1)
10653 /* if the size of this greater than one then no
10655 if (getSize (operandType (IC_RESULT (ic))) > 1)
10658 /* otherwise we can save BIG */
10659 lbl = newiTempLabel (NULL);
10660 lbl1 = newiTempLabel (NULL);
10662 aopOp (IC_RESULT (ic), ic, FALSE);
10664 if (AOP_NEEDSACC(IC_RESULT(ic)))
10666 /* If the result is accessed indirectly via
10667 * the accumulator, we must explicitly write
10668 * it back after the decrement.
10670 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
10672 if (strcmp(rByte, "a"))
10674 /* Something is hopelessly wrong */
10675 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10676 __FILE__, __LINE__);
10677 /* We can just give up; the generated code will be inefficient,
10678 * but what the hey.
10680 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10683 emitcode ("dec", "%s", rByte);
10684 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10685 emitcode ("jnz", "%05d$", lbl->key + 100);
10687 else if (IS_AOP_PREG (IC_RESULT (ic)))
10689 emitcode ("dec", "%s",
10690 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10691 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10692 emitcode ("jnz", "%05d$", lbl->key + 100);
10696 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
10699 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10700 emitcode ("", "%05d$:", lbl->key + 100);
10701 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10702 emitcode ("", "%05d$:", lbl1->key + 100);
10704 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10705 ifx->generated = 1;
10709 /*-----------------------------------------------------------------*/
10710 /* genReceive - generate code for a receive iCode */
10711 /*-----------------------------------------------------------------*/
10713 genReceive (iCode * ic)
10715 int size = getSize (operandType (IC_RESULT (ic)));
10718 D(emitcode ("; genReceive",""));
10720 if (ic->argreg == 1)
10721 { /* first parameter */
10722 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10723 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10724 IS_TRUE_SYMOP (IC_RESULT (ic))))
10727 int receivingA = 0;
10730 for (offset = 0; offset<size; offset++)
10731 if (!strcmp (fReturn[offset], "a"))
10736 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10738 for (offset = size-1; offset>0; offset--)
10739 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10740 emitcode("mov","a,%s", fReturn[0]);
10742 aopOp (IC_RESULT (ic), ic, FALSE);
10744 aopPut (IC_RESULT (ic), "a", offset,
10745 isOperandVolatile (IC_RESULT (ic), FALSE));
10746 for (offset = 1; offset<size; offset++)
10747 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
10748 isOperandVolatile (IC_RESULT (ic), FALSE));
10754 if (getTempRegs(tempRegs, size, ic))
10756 for (offset = 0; offset<size; offset++)
10757 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10758 aopOp (IC_RESULT (ic), ic, FALSE);
10759 for (offset = 0; offset<size; offset++)
10760 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
10761 isOperandVolatile (IC_RESULT (ic), FALSE));
10766 offset = fReturnSizeMCS51 - size;
10769 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10770 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10773 aopOp (IC_RESULT (ic), ic, FALSE);
10774 size = AOP_SIZE (IC_RESULT (ic));
10778 emitcode ("pop", "acc");
10779 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10785 aopOp (IC_RESULT (ic), ic, FALSE);
10787 assignResultValue (IC_RESULT (ic), NULL);
10790 else if (ic->argreg > 12)
10791 { /* bit parameters */
10792 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
10794 aopOp (IC_RESULT (ic), ic, FALSE);
10795 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
10796 outBitC(IC_RESULT (ic));
10800 { /* other parameters */
10802 aopOp (IC_RESULT (ic), ic, FALSE);
10803 rb1off = ic->argreg;
10806 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10811 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10814 /*-----------------------------------------------------------------*/
10815 /* genDummyRead - generate code for dummy read of volatiles */
10816 /*-----------------------------------------------------------------*/
10818 genDummyRead (iCode * ic)
10823 D(emitcode("; genDummyRead",""));
10825 op = IC_RIGHT (ic);
10826 if (op && IS_SYMOP (op))
10828 aopOp (op, ic, FALSE);
10830 /* if the result is a bit */
10831 if (AOP_TYPE (op) == AOP_CRY)
10832 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10835 /* bit variables done */
10837 size = AOP_SIZE (op);
10841 MOVA (aopGet (op, offset, FALSE, FALSE));
10846 freeAsmop (op, NULL, ic, TRUE);
10850 if (op && IS_SYMOP (op))
10852 aopOp (op, ic, FALSE);
10854 /* if the result is a bit */
10855 if (AOP_TYPE (op) == AOP_CRY)
10856 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10859 /* bit variables done */
10861 size = AOP_SIZE (op);
10865 MOVA (aopGet (op, offset, FALSE, FALSE));
10870 freeAsmop (op, NULL, ic, TRUE);
10874 /*-----------------------------------------------------------------*/
10875 /* genCritical - generate code for start of a critical sequence */
10876 /*-----------------------------------------------------------------*/
10878 genCritical (iCode *ic)
10880 symbol *tlbl = newiTempLabel (NULL);
10882 D(emitcode("; genCritical",""));
10884 if (IC_RESULT (ic))
10886 aopOp (IC_RESULT (ic), ic, TRUE);
10887 aopPut (IC_RESULT (ic), one, 0, 0);
10888 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10889 aopPut (IC_RESULT (ic), zero, 0, 0);
10890 emitcode ("", "%05d$:", (tlbl->key + 100));
10891 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10895 emitcode ("setb", "c");
10896 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10897 emitcode ("clr", "c");
10898 emitcode ("", "%05d$:", (tlbl->key + 100));
10899 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10903 /*-----------------------------------------------------------------*/
10904 /* genEndCritical - generate code for end of a critical sequence */
10905 /*-----------------------------------------------------------------*/
10907 genEndCritical (iCode *ic)
10909 D(emitcode("; genEndCritical",""));
10913 aopOp (IC_RIGHT (ic), ic, FALSE);
10914 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10916 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10917 emitcode ("mov", "ea,c");
10921 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10922 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
10923 emitcode ("rrc", "a");
10924 emitcode ("mov", "ea,c");
10926 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10930 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10931 emitcode ("mov", "ea,c");
10935 /*-----------------------------------------------------------------*/
10936 /* gen51Code - generate code for 8051 based controllers */
10937 /*-----------------------------------------------------------------*/
10939 gen51Code (iCode * lic)
10943 /* int cseq = 0; */
10945 _G.currentFunc = NULL;
10946 lineHead = lineCurr = NULL;
10948 /* print the allocation information */
10949 if (allocInfo && currFunc)
10950 printAllocInfo (currFunc, codeOutFile);
10951 /* if debug information required */
10952 if (options.debug && currFunc)
10954 debugFile->writeFunction (currFunc, lic);
10956 /* stack pointer name */
10957 if (options.useXstack)
10963 for (ic = lic; ic; ic = ic->next)
10965 _G.current_iCode = ic;
10967 if (ic->lineno && cln != ic->lineno)
10971 debugFile->writeCLine (ic);
10973 if (!options.noCcodeInAsm) {
10974 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10975 printCLine(ic->filename, ic->lineno));
10980 if (ic->seqPoint && ic->seqPoint != cseq)
10982 emitcode ("", "; sequence point %d", ic->seqPoint);
10983 cseq = ic->seqPoint;
10986 if (options.iCodeInAsm) {
10987 char regsInUse[80];
10990 for (i=0; i<8; i++) {
10991 sprintf (®sInUse[i],
10992 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10995 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10997 /* if the result is marked as
10998 spilt and rematerializable or code for
10999 this has already been generated then
11001 if (resultRemat (ic) || ic->generated)
11004 /* depending on the operation */
11024 /* IPOP happens only when trying to restore a
11025 spilt live range, if there is an ifx statement
11026 following this pop then the if statement might
11027 be using some of the registers being popped which
11028 would destory the contents of the register so
11029 we need to check for this condition and handle it */
11031 ic->next->op == IFX &&
11032 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11033 genIfx (ic->next, ic);
11051 genEndFunction (ic);
11071 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11088 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11092 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11099 /* note these two are xlated by algebraic equivalence
11100 during parsing SDCC.y */
11101 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11102 "got '>=' or '<=' shouldn't have come here");
11106 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11118 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11122 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11126 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11150 genRightShift (ic);
11153 case GET_VALUE_AT_ADDRESS:
11155 hasInc (IC_LEFT (ic), ic,
11156 getSize (operandType (IC_RESULT (ic)))),
11157 ifxForOp (IC_RESULT (ic), ic) );
11161 if (POINTER_SET (ic))
11162 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11188 addSet (&_G.sendSet, ic);
11191 case DUMMY_READ_VOLATILE:
11200 genEndCritical (ic);
11212 _G.current_iCode = NULL;
11214 /* now we are ready to call the
11215 peep hole optimizer */
11216 if (!options.nopeep)
11217 peepHole (&lineHead);
11219 /* now do the actual printing */
11220 printLine (lineHead, codeOutFile);