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 deccrement 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)) {
4531 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4532 if (!offset && !size && lit== (unsigned long) -1) {
4533 emitcode ("dec", "a");
4534 } else if (!useCarry) {
4535 /* first add without previous c */
4536 emitcode ("add", "a,#0x%02x",
4537 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4540 emitcode ("addc", "a,#0x%02x",
4541 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4543 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4545 /* no need to add zeroes */
4552 operand *leftOp, *rightOp;
4554 leftOp = IC_LEFT(ic);
4555 rightOp = IC_RIGHT(ic);
4559 if (aopGetUsesAcc(rightOp, offset)) {
4560 if (aopGetUsesAcc(leftOp, offset)) {
4563 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4565 emitcode ("mov", "b,a");
4568 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4569 emitcode ("subb", "a,b");
4572 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4573 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4575 emitcode( "setb", "c");
4577 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4578 emitcode("cpl", "a");
4581 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4584 emitcode ("subb", "a,%s",
4585 aopGet(rightOp, offset, FALSE, TRUE));
4588 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4593 adjustArithmeticResult (ic);
4596 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4597 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4598 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4602 /*-----------------------------------------------------------------*/
4603 /* genMultbits :- multiplication of bits */
4604 /*-----------------------------------------------------------------*/
4606 genMultbits (operand * left,
4610 D(emitcode ("; genMultbits",""));
4612 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4613 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4617 /*-----------------------------------------------------------------*/
4618 /* genMultOneByte : 8*8=8/16 bit multiplication */
4619 /*-----------------------------------------------------------------*/
4621 genMultOneByte (operand * left,
4626 int size = AOP_SIZE (result);
4627 bool runtimeSign, compiletimeSign;
4628 bool lUnsigned, rUnsigned, pushedB;
4630 D(emitcode ("; genMultOneByte",""));
4632 if (size < 1 || size > 2)
4634 /* this should never happen */
4635 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4636 AOP_SIZE(result), __FILE__, lineno);
4640 /* (if two literals: the value is computed before) */
4641 /* if one literal, literal on the right */
4642 if (AOP_TYPE (left) == AOP_LIT)
4647 /* emitcode (";", "swapped left and right"); */
4649 /* if no literal, unsigned on the right: shorter code */
4650 if ( AOP_TYPE (right) != AOP_LIT
4651 && SPEC_USIGN (getSpec (operandType (left))))
4658 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4659 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4663 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4664 no need to take care about the signedness! */
4665 || (lUnsigned && rUnsigned))
4667 /* just an unsigned 8 * 8 = 8 multiply
4669 /* emitcode (";","unsigned"); */
4670 /* TODO: check for accumulator clash between left & right aops? */
4672 if (AOP_TYPE (right) == AOP_LIT)
4674 /* moving to accumulator first helps peepholes */
4675 MOVA (aopGet (left, 0, FALSE, FALSE));
4676 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4680 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4681 MOVA (aopGet (left, 0, FALSE, FALSE));
4684 emitcode ("mul", "ab");
4685 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4687 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4693 /* we have to do a signed multiply */
4694 /* emitcode (";", "signed"); */
4696 /* now sign adjust for both left & right */
4698 /* let's see what's needed: */
4699 /* apply negative sign during runtime */
4700 runtimeSign = FALSE;
4701 /* negative sign from literals */
4702 compiletimeSign = FALSE;
4706 if (AOP_TYPE(left) == AOP_LIT)
4708 /* signed literal */
4709 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4711 compiletimeSign = TRUE;
4714 /* signed but not literal */
4720 if (AOP_TYPE(right) == AOP_LIT)
4722 /* signed literal */
4723 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4725 compiletimeSign ^= TRUE;
4728 /* signed but not literal */
4732 /* initialize F0, which stores the runtime sign */
4735 if (compiletimeSign)
4736 emitcode ("setb", "F0"); /* set sign flag */
4738 emitcode ("clr", "F0"); /* reset sign flag */
4741 /* save the signs of the operands */
4742 if (AOP_TYPE(right) == AOP_LIT)
4744 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4746 if (!rUnsigned && val < 0)
4747 emitcode ("mov", "b,#0x%02x", -val);
4749 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4751 else /* ! literal */
4753 if (rUnsigned) /* emitcode (";", "signed"); */
4755 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4758 MOVA (aopGet (right, 0, FALSE, FALSE));
4759 lbl = newiTempLabel (NULL);
4760 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4761 emitcode ("cpl", "F0"); /* complement sign flag */
4762 emitcode ("cpl", "a"); /* 2's complement */
4763 emitcode ("inc", "a");
4764 emitcode ("", "%05d$:", (lbl->key + 100));
4765 emitcode ("mov", "b,a");
4769 if (AOP_TYPE(left) == AOP_LIT)
4771 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4773 if (!lUnsigned && val < 0)
4774 emitcode ("mov", "a,#0x%02x", -val);
4776 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4778 else /* ! literal */
4780 MOVA (aopGet (left, 0, FALSE, FALSE));
4784 lbl = newiTempLabel (NULL);
4785 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4786 emitcode ("cpl", "F0"); /* complement sign flag */
4787 emitcode ("cpl", "a"); /* 2's complement */
4788 emitcode ("inc", "a");
4789 emitcode ("", "%05d$:", (lbl->key + 100));
4793 /* now the multiplication */
4794 emitcode ("mul", "ab");
4795 if (runtimeSign || compiletimeSign)
4797 lbl = newiTempLabel (NULL);
4799 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4800 emitcode ("cpl", "a"); /* lsb 2's complement */
4802 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4805 emitcode ("add", "a,#1"); /* this sets carry flag */
4806 emitcode ("xch", "a,b");
4807 emitcode ("cpl", "a"); /* msb 2's complement */
4808 emitcode ("addc", "a,#0");
4809 emitcode ("xch", "a,b");
4811 emitcode ("", "%05d$:", (lbl->key + 100));
4813 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4815 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4820 /*-----------------------------------------------------------------*/
4821 /* genMult - generates code for multiplication */
4822 /*-----------------------------------------------------------------*/
4824 genMult (iCode * ic)
4826 operand *left = IC_LEFT (ic);
4827 operand *right = IC_RIGHT (ic);
4828 operand *result = IC_RESULT (ic);
4830 D(emitcode ("; genMult",""));
4832 /* assign the amsops */
4833 aopOp (left, ic, FALSE);
4834 aopOp (right, ic, FALSE);
4835 aopOp (result, ic, TRUE);
4837 /* special cases first */
4839 if (AOP_TYPE (left) == AOP_CRY &&
4840 AOP_TYPE (right) == AOP_CRY)
4842 genMultbits (left, right, result);
4846 /* if both are of size == 1 */
4847 #if 0 // one of them can be a sloc shared with the result
4848 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4850 if (getSize(operandType(left)) == 1 &&
4851 getSize(operandType(right)) == 1)
4854 genMultOneByte (left, right, result);
4858 /* should have been converted to function call */
4859 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4860 getSize(OP_SYMBOL(right)->type));
4864 freeAsmop (result, NULL, ic, TRUE);
4865 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4866 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4869 /*-----------------------------------------------------------------*/
4870 /* genDivbits :- division of bits */
4871 /*-----------------------------------------------------------------*/
4873 genDivbits (operand * left,
4880 D(emitcode ("; genDivbits",""));
4884 /* the result must be bit */
4885 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4886 l = aopGet (left, 0, FALSE, FALSE);
4890 emitcode ("div", "ab");
4891 emitcode ("rrc", "a");
4895 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4898 /*-----------------------------------------------------------------*/
4899 /* genDivOneByte : 8 bit division */
4900 /*-----------------------------------------------------------------*/
4902 genDivOneByte (operand * left,
4906 bool lUnsigned, rUnsigned, pushedB;
4907 bool runtimeSign, compiletimeSign;
4911 D(emitcode ("; genDivOneByte",""));
4913 /* Why is it necessary that genDivOneByte() can return an int result?
4916 volatile unsigned char uc;
4917 volatile signed char sc1, sc2;
4930 In all cases a one byte result would overflow, the following cast to int
4931 would return the wrong result.
4933 Two possible solution:
4934 a) cast operands to int, if ((unsigned) / (signed)) or
4935 ((signed) / (signed))
4936 b) return an 16 bit signed int; this is what we're doing here!
4939 size = AOP_SIZE (result) - 1;
4941 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4942 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4946 /* signed or unsigned */
4947 if (lUnsigned && rUnsigned)
4949 /* unsigned is easy */
4950 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4951 MOVA (aopGet (left, 0, FALSE, FALSE));
4952 emitcode ("div", "ab");
4953 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4955 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4961 /* signed is a little bit more difficult */
4963 /* now sign adjust for both left & right */
4965 /* let's see what's needed: */
4966 /* apply negative sign during runtime */
4967 runtimeSign = FALSE;
4968 /* negative sign from literals */
4969 compiletimeSign = FALSE;
4973 if (AOP_TYPE(left) == AOP_LIT)
4975 /* signed literal */
4976 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4978 compiletimeSign = TRUE;
4981 /* signed but not literal */
4987 if (AOP_TYPE(right) == AOP_LIT)
4989 /* signed literal */
4990 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4992 compiletimeSign ^= TRUE;
4995 /* signed but not literal */
4999 /* initialize F0, which stores the runtime sign */
5002 if (compiletimeSign)
5003 emitcode ("setb", "F0"); /* set sign flag */
5005 emitcode ("clr", "F0"); /* reset sign flag */
5008 /* save the signs of the operands */
5009 if (AOP_TYPE(right) == AOP_LIT)
5011 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5013 if (!rUnsigned && val < 0)
5014 emitcode ("mov", "b,#0x%02x", -val);
5016 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5018 else /* ! literal */
5021 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5024 MOVA (aopGet (right, 0, FALSE, FALSE));
5025 lbl = newiTempLabel (NULL);
5026 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5027 emitcode ("cpl", "F0"); /* complement sign flag */
5028 emitcode ("cpl", "a"); /* 2's complement */
5029 emitcode ("inc", "a");
5030 emitcode ("", "%05d$:", (lbl->key + 100));
5031 emitcode ("mov", "b,a");
5035 if (AOP_TYPE(left) == AOP_LIT)
5037 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5039 if (!lUnsigned && val < 0)
5040 emitcode ("mov", "a,#0x%02x", -val);
5042 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5044 else /* ! literal */
5046 MOVA (aopGet (left, 0, FALSE, FALSE));
5050 lbl = newiTempLabel (NULL);
5051 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5052 emitcode ("cpl", "F0"); /* complement sign flag */
5053 emitcode ("cpl", "a"); /* 2's complement */
5054 emitcode ("inc", "a");
5055 emitcode ("", "%05d$:", (lbl->key + 100));
5059 /* now the division */
5060 emitcode ("div", "ab");
5062 if (runtimeSign || compiletimeSign)
5064 lbl = newiTempLabel (NULL);
5066 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5067 emitcode ("cpl", "a"); /* lsb 2's complement */
5068 emitcode ("inc", "a");
5069 emitcode ("", "%05d$:", (lbl->key + 100));
5071 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5074 /* msb is 0x00 or 0xff depending on the sign */
5077 emitcode ("mov", "c,F0");
5078 emitcode ("subb", "a,acc");
5080 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5082 else /* compiletimeSign */
5084 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5089 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5091 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5097 /*-----------------------------------------------------------------*/
5098 /* genDiv - generates code for division */
5099 /*-----------------------------------------------------------------*/
5103 operand *left = IC_LEFT (ic);
5104 operand *right = IC_RIGHT (ic);
5105 operand *result = IC_RESULT (ic);
5107 D(emitcode ("; genDiv",""));
5109 /* assign the amsops */
5110 aopOp (left, ic, FALSE);
5111 aopOp (right, ic, FALSE);
5112 aopOp (result, ic, TRUE);
5114 /* special cases first */
5116 if (AOP_TYPE (left) == AOP_CRY &&
5117 AOP_TYPE (right) == AOP_CRY)
5119 genDivbits (left, right, result);
5123 /* if both are of size == 1 */
5124 if (AOP_SIZE (left) == 1 &&
5125 AOP_SIZE (right) == 1)
5127 genDivOneByte (left, right, result);
5131 /* should have been converted to function call */
5134 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5135 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5136 freeAsmop (result, NULL, ic, TRUE);
5139 /*-----------------------------------------------------------------*/
5140 /* genModbits :- modulus of bits */
5141 /*-----------------------------------------------------------------*/
5143 genModbits (operand * left,
5150 D(emitcode ("; genModbits",""));
5154 /* the result must be bit */
5155 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5156 l = aopGet (left, 0, FALSE, FALSE);
5160 emitcode ("div", "ab");
5161 emitcode ("mov", "a,b");
5162 emitcode ("rrc", "a");
5166 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5169 /*-----------------------------------------------------------------*/
5170 /* genModOneByte : 8 bit modulus */
5171 /*-----------------------------------------------------------------*/
5173 genModOneByte (operand * left,
5177 bool lUnsigned, rUnsigned, pushedB;
5178 bool runtimeSign, compiletimeSign;
5182 D(emitcode ("; genModOneByte",""));
5184 size = AOP_SIZE (result) - 1;
5186 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5187 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5189 /* if right is a literal, check it for 2^n */
5190 if (AOP_TYPE(right) == AOP_LIT)
5192 unsigned char val = abs((int) operandLitValue(right));
5193 symbol *lbl2 = NULL;
5197 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5206 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5207 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5208 /* because iCode should have been changed to genAnd */
5209 /* see file "SDCCopt.c", function "convertToFcall()" */
5211 MOVA (aopGet (left, 0, FALSE, FALSE));
5212 emitcode ("mov", "c,acc.7");
5213 emitcode ("anl", "a,#0x%02x", val - 1);
5214 lbl = newiTempLabel (NULL);
5215 emitcode ("jz", "%05d$", (lbl->key + 100));
5216 emitcode ("jnc", "%05d$", (lbl->key + 100));
5217 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5223 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5225 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5226 lbl2 = newiTempLabel (NULL);
5227 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5229 emitcode ("", "%05d$:", (lbl->key + 100));
5230 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5232 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5235 emitcode ("", "%05d$:", (lbl2->key + 100));
5246 /* signed or unsigned */
5247 if (lUnsigned && rUnsigned)
5249 /* unsigned is easy */
5250 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5251 MOVA (aopGet (left, 0, FALSE, FALSE));
5252 emitcode ("div", "ab");
5253 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5255 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5261 /* signed is a little bit more difficult */
5263 /* now sign adjust for both left & right */
5265 /* modulus: sign of the right operand has no influence on the result! */
5266 if (AOP_TYPE(right) == AOP_LIT)
5268 signed char val = (char) operandLitValue(right);
5270 if (!rUnsigned && val < 0)
5271 emitcode ("mov", "b,#0x%02x", -val);
5273 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5275 else /* not literal */
5278 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5281 MOVA (aopGet (right, 0, FALSE, FALSE));
5282 lbl = newiTempLabel (NULL);
5283 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5284 emitcode ("cpl", "a"); /* 2's complement */
5285 emitcode ("inc", "a");
5286 emitcode ("", "%05d$:", (lbl->key + 100));
5287 emitcode ("mov", "b,a");
5291 /* let's see what's needed: */
5292 /* apply negative sign during runtime */
5293 runtimeSign = FALSE;
5294 /* negative sign from literals */
5295 compiletimeSign = FALSE;
5297 /* sign adjust left side */
5298 if (AOP_TYPE(left) == AOP_LIT)
5300 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5302 if (!lUnsigned && val < 0)
5304 compiletimeSign = TRUE; /* set sign flag */
5305 emitcode ("mov", "a,#0x%02x", -val);
5308 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5310 else /* ! literal */
5312 MOVA (aopGet (left, 0, FALSE, FALSE));
5317 emitcode ("clr", "F0"); /* clear sign flag */
5319 lbl = newiTempLabel (NULL);
5320 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5321 emitcode ("setb", "F0"); /* set sign flag */
5322 emitcode ("cpl", "a"); /* 2's complement */
5323 emitcode ("inc", "a");
5324 emitcode ("", "%05d$:", (lbl->key + 100));
5328 /* now the modulus */
5329 emitcode ("div", "ab");
5331 if (runtimeSign || compiletimeSign)
5333 emitcode ("mov", "a,b");
5334 lbl = newiTempLabel (NULL);
5336 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5337 emitcode ("cpl", "a"); /* 2's complement */
5338 emitcode ("inc", "a");
5339 emitcode ("", "%05d$:", (lbl->key + 100));
5341 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5344 /* msb is 0x00 or 0xff depending on the sign */
5347 emitcode ("mov", "c,F0");
5348 emitcode ("subb", "a,acc");
5350 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5352 else /* compiletimeSign */
5354 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5359 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5361 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5367 /*-----------------------------------------------------------------*/
5368 /* genMod - generates code for division */
5369 /*-----------------------------------------------------------------*/
5373 operand *left = IC_LEFT (ic);
5374 operand *right = IC_RIGHT (ic);
5375 operand *result = IC_RESULT (ic);
5377 D(emitcode ("; genMod",""));
5379 /* assign the asmops */
5380 aopOp (left, ic, FALSE);
5381 aopOp (right, ic, FALSE);
5382 aopOp (result, ic, TRUE);
5384 /* special cases first */
5386 if (AOP_TYPE (left) == AOP_CRY &&
5387 AOP_TYPE (right) == AOP_CRY)
5389 genModbits (left, right, result);
5393 /* if both are of size == 1 */
5394 if (AOP_SIZE (left) == 1 &&
5395 AOP_SIZE (right) == 1)
5397 genModOneByte (left, right, result);
5401 /* should have been converted to function call */
5405 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5406 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5407 freeAsmop (result, NULL, ic, TRUE);
5410 /*-----------------------------------------------------------------*/
5411 /* genIfxJump :- will create a jump depending on the ifx */
5412 /*-----------------------------------------------------------------*/
5414 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5417 symbol *tlbl = newiTempLabel (NULL);
5420 D(emitcode ("; genIfxJump",""));
5422 /* if true label then we jump if condition
5426 jlbl = IC_TRUE (ic);
5427 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5428 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5432 /* false label is present */
5433 jlbl = IC_FALSE (ic);
5434 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5435 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5437 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5438 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5440 emitcode (inst, "%05d$", tlbl->key + 100);
5441 freeForBranchAsmop (result);
5442 freeForBranchAsmop (right);
5443 freeForBranchAsmop (left);
5444 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5445 emitcode ("", "%05d$:", tlbl->key + 100);
5447 /* mark the icode as generated */
5451 /*-----------------------------------------------------------------*/
5452 /* genCmp :- greater or less than comparison */
5453 /*-----------------------------------------------------------------*/
5455 genCmp (operand * left, operand * right,
5456 operand * result, iCode * ifx, int sign, iCode *ic)
5458 int size, offset = 0;
5459 unsigned long lit = 0L;
5462 D(emitcode ("; genCmp",""));
5464 /* if left & right are bit variables */
5465 if (AOP_TYPE (left) == AOP_CRY &&
5466 AOP_TYPE (right) == AOP_CRY)
5468 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5469 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5473 /* subtract right from left if at the
5474 end the carry flag is set then we know that
5475 left is greater than right */
5476 size = max (AOP_SIZE (left), AOP_SIZE (right));
5478 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5479 if ((size == 1) && !sign &&
5480 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5482 symbol *lbl = newiTempLabel (NULL);
5483 emitcode ("cjne", "%s,%s,%05d$",
5484 aopGet (left, offset, FALSE, FALSE),
5485 aopGet (right, offset, FALSE, FALSE),
5487 emitcode ("", "%05d$:", lbl->key + 100);
5491 if (AOP_TYPE (right) == AOP_LIT)
5493 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5494 /* optimize if(x < 0) or if(x >= 0) */
5503 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5504 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5506 genIfxJump (ifx, "acc.7", left, right, result);
5507 freeAsmop (right, NULL, ic, TRUE);
5508 freeAsmop (left, NULL, ic, TRUE);
5513 emitcode ("rlc", "a");
5521 bool pushedB = FALSE;
5522 rightInB = aopGetUsesAcc(right, offset);
5526 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5528 MOVA (aopGet (left, offset, FALSE, FALSE));
5529 if (sign && size == 0)
5531 emitcode ("xrl", "a,#0x80");
5532 if (AOP_TYPE (right) == AOP_LIT)
5534 unsigned long lit = (unsigned long)
5535 floatFromVal (AOP (right)->aopu.aop_lit);
5536 emitcode ("subb", "a,#0x%02x",
5537 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5545 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5547 emitcode ("xrl", "b,#0x80");
5548 emitcode ("subb", "a,b");
5554 emitcode ("subb", "a,b");
5556 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5566 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5567 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5568 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5574 /* if the result is used in the next
5575 ifx conditional branch then generate
5576 code a little differently */
5578 genIfxJump (ifx, "c", NULL, NULL, result);
5581 /* leave the result in acc */
5585 /*-----------------------------------------------------------------*/
5586 /* genCmpGt :- greater than comparison */
5587 /*-----------------------------------------------------------------*/
5589 genCmpGt (iCode * ic, iCode * ifx)
5591 operand *left, *right, *result;
5592 sym_link *letype, *retype;
5595 D(emitcode ("; genCmpGt",""));
5597 left = IC_LEFT (ic);
5598 right = IC_RIGHT (ic);
5599 result = IC_RESULT (ic);
5601 letype = getSpec (operandType (left));
5602 retype = getSpec (operandType (right));
5603 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5604 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5605 /* assign the amsops */
5606 aopOp (left, ic, FALSE);
5607 aopOp (right, ic, FALSE);
5608 aopOp (result, ic, TRUE);
5610 genCmp (right, left, result, ifx, sign, ic);
5612 freeAsmop (result, NULL, ic, TRUE);
5615 /*-----------------------------------------------------------------*/
5616 /* genCmpLt - less than comparisons */
5617 /*-----------------------------------------------------------------*/
5619 genCmpLt (iCode * ic, iCode * ifx)
5621 operand *left, *right, *result;
5622 sym_link *letype, *retype;
5625 D(emitcode ("; genCmpLt",""));
5627 left = IC_LEFT (ic);
5628 right = IC_RIGHT (ic);
5629 result = IC_RESULT (ic);
5631 letype = getSpec (operandType (left));
5632 retype = getSpec (operandType (right));
5633 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5634 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5635 /* assign the amsops */
5636 aopOp (left, ic, FALSE);
5637 aopOp (right, ic, FALSE);
5638 aopOp (result, ic, TRUE);
5640 genCmp (left, right, result, ifx, sign, ic);
5642 freeAsmop (result, NULL, ic, TRUE);
5645 /*-----------------------------------------------------------------*/
5646 /* gencjneshort - compare and jump if not equal */
5647 /*-----------------------------------------------------------------*/
5649 gencjneshort (operand * left, operand * right, symbol * lbl)
5651 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5653 unsigned long lit = 0L;
5655 /* if the left side is a literal or
5656 if the right is in a pointer register and left
5658 if ((AOP_TYPE (left) == AOP_LIT) ||
5659 (AOP_TYPE (left) == AOP_IMMD) ||
5660 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5667 if (AOP_TYPE (right) == AOP_LIT)
5668 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5670 /* if the right side is a literal then anything goes */
5671 if (AOP_TYPE (right) == AOP_LIT &&
5672 AOP_TYPE (left) != AOP_DIR &&
5673 AOP_TYPE (left) != AOP_IMMD)
5677 emitcode ("cjne", "%s,%s,%05d$",
5678 aopGet (left, offset, FALSE, FALSE),
5679 aopGet (right, offset, FALSE, FALSE),
5685 /* if the right side is in a register or in direct space or
5686 if the left is a pointer register & right is not */
5687 else if (AOP_TYPE (right) == AOP_REG ||
5688 AOP_TYPE (right) == AOP_DIR ||
5689 AOP_TYPE (right) == AOP_LIT ||
5690 AOP_TYPE (right) == AOP_IMMD ||
5691 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5692 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5696 MOVA (aopGet (left, offset, FALSE, FALSE));
5697 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5698 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5699 emitcode ("jnz", "%05d$", lbl->key + 100);
5701 emitcode ("cjne", "a,%s,%05d$",
5702 aopGet (right, offset, FALSE, TRUE),
5709 /* right is a pointer reg need both a & b */
5713 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5714 wassertl(!BINUSE, "B was in use");
5715 l = aopGet (left, offset, FALSE, FALSE);
5716 if (strcmp (l, "b"))
5717 emitcode ("mov", "b,%s", l);
5718 MOVA (aopGet (right, offset, FALSE, FALSE));
5719 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5725 /*-----------------------------------------------------------------*/
5726 /* gencjne - compare and jump if not equal */
5727 /*-----------------------------------------------------------------*/
5729 gencjne (operand * left, operand * right, symbol * lbl)
5731 symbol *tlbl = newiTempLabel (NULL);
5733 gencjneshort (left, right, lbl);
5735 emitcode ("mov", "a,%s", one);
5736 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5737 emitcode ("", "%05d$:", lbl->key + 100);
5738 emitcode ("clr", "a");
5739 emitcode ("", "%05d$:", tlbl->key + 100);
5742 /*-----------------------------------------------------------------*/
5743 /* genCmpEq - generates code for equal to */
5744 /*-----------------------------------------------------------------*/
5746 genCmpEq (iCode * ic, iCode * ifx)
5748 operand *left, *right, *result;
5750 D(emitcode ("; genCmpEq",""));
5752 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5753 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5754 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5756 /* if literal, literal on the right or
5757 if the right is in a pointer register and left
5759 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5760 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5762 operand *t = IC_RIGHT (ic);
5763 IC_RIGHT (ic) = IC_LEFT (ic);
5767 if (ifx && !AOP_SIZE (result))
5770 /* if they are both bit variables */
5771 if (AOP_TYPE (left) == AOP_CRY &&
5772 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5774 if (AOP_TYPE (right) == AOP_LIT)
5776 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5779 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5780 emitcode ("cpl", "c");
5784 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5788 emitcode ("clr", "c");
5790 /* AOP_TYPE(right) == AOP_CRY */
5794 symbol *lbl = newiTempLabel (NULL);
5795 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5796 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5797 emitcode ("cpl", "c");
5798 emitcode ("", "%05d$:", (lbl->key + 100));
5800 /* if true label then we jump if condition
5802 tlbl = newiTempLabel (NULL);
5805 emitcode ("jnc", "%05d$", tlbl->key + 100);
5806 freeForBranchAsmop (result);
5807 freeForBranchAsmop (right);
5808 freeForBranchAsmop (left);
5809 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5813 emitcode ("jc", "%05d$", tlbl->key + 100);
5814 freeForBranchAsmop (result);
5815 freeForBranchAsmop (right);
5816 freeForBranchAsmop (left);
5817 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5819 emitcode ("", "%05d$:", tlbl->key + 100);
5823 tlbl = newiTempLabel (NULL);
5824 gencjneshort (left, right, tlbl);
5827 freeForBranchAsmop (result);
5828 freeForBranchAsmop (right);
5829 freeForBranchAsmop (left);
5830 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5831 emitcode ("", "%05d$:", tlbl->key + 100);
5835 symbol *lbl = newiTempLabel (NULL);
5836 emitcode ("sjmp", "%05d$", lbl->key + 100);
5837 emitcode ("", "%05d$:", tlbl->key + 100);
5838 freeForBranchAsmop (result);
5839 freeForBranchAsmop (right);
5840 freeForBranchAsmop (left);
5841 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5842 emitcode ("", "%05d$:", lbl->key + 100);
5845 /* mark the icode as generated */
5850 /* if they are both bit variables */
5851 if (AOP_TYPE (left) == AOP_CRY &&
5852 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5854 if (AOP_TYPE (right) == AOP_LIT)
5856 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5859 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5860 emitcode ("cpl", "c");
5864 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5868 emitcode ("clr", "c");
5870 /* AOP_TYPE(right) == AOP_CRY */
5874 symbol *lbl = newiTempLabel (NULL);
5875 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5876 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5877 emitcode ("cpl", "c");
5878 emitcode ("", "%05d$:", (lbl->key + 100));
5881 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5888 genIfxJump (ifx, "c", left, right, result);
5891 /* if the result is used in an arithmetic operation
5892 then put the result in place */
5897 gencjne (left, right, newiTempLabel (NULL));
5898 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5900 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5905 genIfxJump (ifx, "a", left, right, result);
5908 /* if the result is used in an arithmetic operation
5909 then put the result in place */
5910 if (AOP_TYPE (result) != AOP_CRY)
5912 /* leave the result in acc */
5916 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5917 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5918 freeAsmop (result, NULL, ic, TRUE);
5921 /*-----------------------------------------------------------------*/
5922 /* ifxForOp - returns the icode containing the ifx for operand */
5923 /*-----------------------------------------------------------------*/
5925 ifxForOp (operand * op, iCode * ic)
5927 /* if true symbol then needs to be assigned */
5928 if (IS_TRUE_SYMOP (op))
5931 /* if this has register type condition and
5932 the next instruction is ifx with the same operand
5933 and live to of the operand is upto the ifx only then */
5935 ic->next->op == IFX &&
5936 IC_COND (ic->next)->key == op->key &&
5937 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5943 /*-----------------------------------------------------------------*/
5944 /* hasInc - operand is incremented before any other use */
5945 /*-----------------------------------------------------------------*/
5947 hasInc (operand *op, iCode *ic,int osize)
5949 sym_link *type = operandType(op);
5950 sym_link *retype = getSpec (type);
5951 iCode *lic = ic->next;
5954 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5955 if (!IS_SYMOP(op)) return NULL;
5957 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5958 if (IS_AGGREGATE(type->next)) return NULL;
5959 if (osize != (isize = getSize(type->next))) return NULL;
5962 /* if operand of the form op = op + <sizeof *op> */
5963 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5964 isOperandEqual(IC_RESULT(lic),op) &&
5965 isOperandLiteral(IC_RIGHT(lic)) &&
5966 operandLitValue(IC_RIGHT(lic)) == isize) {
5969 /* if the operand used or deffed */
5970 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5973 /* if GOTO or IFX */
5974 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5980 /*-----------------------------------------------------------------*/
5981 /* genAndOp - for && operation */
5982 /*-----------------------------------------------------------------*/
5984 genAndOp (iCode * ic)
5986 operand *left, *right, *result;
5989 D(emitcode ("; genAndOp",""));
5991 /* note here that && operations that are in an
5992 if statement are taken away by backPatchLabels
5993 only those used in arthmetic operations remain */
5994 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5995 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5996 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
5998 /* if both are bit variables */
5999 if (AOP_TYPE (left) == AOP_CRY &&
6000 AOP_TYPE (right) == AOP_CRY)
6002 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6003 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6008 tlbl = newiTempLabel (NULL);
6010 emitcode ("jz", "%05d$", tlbl->key + 100);
6012 emitcode ("", "%05d$:", tlbl->key + 100);
6016 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6017 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6018 freeAsmop (result, NULL, ic, TRUE);
6022 /*-----------------------------------------------------------------*/
6023 /* genOrOp - for || operation */
6024 /*-----------------------------------------------------------------*/
6026 genOrOp (iCode * ic)
6028 operand *left, *right, *result;
6031 D(emitcode ("; genOrOp",""));
6033 /* note here that || operations that are in an
6034 if statement are taken away by backPatchLabels
6035 only those used in arthmetic operations remain */
6036 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6037 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6038 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6040 /* if both are bit variables */
6041 if (AOP_TYPE (left) == AOP_CRY &&
6042 AOP_TYPE (right) == AOP_CRY)
6044 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6045 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6050 tlbl = newiTempLabel (NULL);
6052 emitcode ("jnz", "%05d$", tlbl->key + 100);
6054 emitcode ("", "%05d$:", tlbl->key + 100);
6058 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6059 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6060 freeAsmop (result, NULL, ic, TRUE);
6063 /*-----------------------------------------------------------------*/
6064 /* isLiteralBit - test if lit == 2^n */
6065 /*-----------------------------------------------------------------*/
6067 isLiteralBit (unsigned long lit)
6069 unsigned long pw[32] =
6070 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6071 0x100L, 0x200L, 0x400L, 0x800L,
6072 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6073 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6074 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6075 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6076 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6079 for (idx = 0; idx < 32; idx++)
6085 /*-----------------------------------------------------------------*/
6086 /* continueIfTrue - */
6087 /*-----------------------------------------------------------------*/
6089 continueIfTrue (iCode * ic)
6092 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6096 /*-----------------------------------------------------------------*/
6098 /*-----------------------------------------------------------------*/
6100 jumpIfTrue (iCode * ic)
6103 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6107 /*-----------------------------------------------------------------*/
6108 /* jmpTrueOrFalse - */
6109 /*-----------------------------------------------------------------*/
6111 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6113 // ugly but optimized by peephole
6116 symbol *nlbl = newiTempLabel (NULL);
6117 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6118 emitcode ("", "%05d$:", tlbl->key + 100);
6119 freeForBranchAsmop (result);
6120 freeForBranchAsmop (right);
6121 freeForBranchAsmop (left);
6122 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6123 emitcode ("", "%05d$:", nlbl->key + 100);
6127 freeForBranchAsmop (result);
6128 freeForBranchAsmop (right);
6129 freeForBranchAsmop (left);
6130 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6131 emitcode ("", "%05d$:", tlbl->key + 100);
6136 /*-----------------------------------------------------------------*/
6137 /* genAnd - code for and */
6138 /*-----------------------------------------------------------------*/
6140 genAnd (iCode * ic, iCode * ifx)
6142 operand *left, *right, *result;
6143 int size, offset = 0;
6144 unsigned long lit = 0L;
6148 D(emitcode ("; genAnd",""));
6150 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6151 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6152 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6155 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6157 AOP_TYPE (left), AOP_TYPE (right));
6158 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6160 AOP_SIZE (left), AOP_SIZE (right));
6163 /* if left is a literal & right is not then exchange them */
6164 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6165 AOP_NEEDSACC (left))
6167 operand *tmp = right;
6172 /* if result = right then exchange left and right */
6173 if (sameRegs (AOP (result), AOP (right)))
6175 operand *tmp = right;
6180 /* if right is bit then exchange them */
6181 if (AOP_TYPE (right) == AOP_CRY &&
6182 AOP_TYPE (left) != AOP_CRY)
6184 operand *tmp = right;
6188 if (AOP_TYPE (right) == AOP_LIT)
6189 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6191 size = AOP_SIZE (result);
6194 // result = bit & yy;
6195 if (AOP_TYPE (left) == AOP_CRY)
6197 // c = bit & literal;
6198 if (AOP_TYPE (right) == AOP_LIT)
6202 if (size && sameRegs (AOP (result), AOP (left)))
6205 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6210 if (size && (AOP_TYPE (result) == AOP_CRY))
6212 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6215 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6220 emitcode ("clr", "c");
6225 if (AOP_TYPE (right) == AOP_CRY)
6228 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6229 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6234 MOVA (aopGet (right, 0, FALSE, FALSE));
6236 emitcode ("rrc", "a");
6237 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6245 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6246 genIfxJump (ifx, "c", left, right, result);
6250 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6251 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6252 if ((AOP_TYPE (right) == AOP_LIT) &&
6253 (AOP_TYPE (result) == AOP_CRY) &&
6254 (AOP_TYPE (left) != AOP_CRY))
6256 int posbit = isLiteralBit (lit);
6261 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6265 switch (posbit & 0x07)
6267 case 0: emitcode ("rrc", "a");
6269 case 7: emitcode ("rlc", "a");
6271 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6280 SNPRINTF (buffer, sizeof(buffer),
6281 "acc.%d", posbit & 0x07);
6282 genIfxJump (ifx, buffer, left, right, result);
6285 {// what is this case? just found it in ds390/gen.c
6286 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6293 symbol *tlbl = newiTempLabel (NULL);
6294 int sizel = AOP_SIZE (left);
6296 emitcode ("setb", "c");
6299 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6301 MOVA (aopGet (left, offset, FALSE, FALSE));
6303 if ((posbit = isLiteralBit (bytelit)) != 0)
6304 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6307 if (bytelit != 0x0FFL)
6308 emitcode ("anl", "a,%s",
6309 aopGet (right, offset, FALSE, TRUE));
6310 emitcode ("jnz", "%05d$", tlbl->key + 100);
6315 // bit = left & literal
6318 emitcode ("clr", "c");
6319 emitcode ("", "%05d$:", tlbl->key + 100);
6321 // if(left & literal)
6325 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6327 emitcode ("", "%05d$:", tlbl->key + 100);
6335 /* if left is same as result */
6336 if (sameRegs (AOP (result), AOP (left)))
6338 for (; size--; offset++)
6340 if (AOP_TYPE (right) == AOP_LIT)
6342 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6343 if (bytelit == 0x0FF)
6345 /* dummy read of volatile operand */
6346 if (isOperandVolatile (left, FALSE))
6347 MOVA (aopGet (left, offset, FALSE, FALSE));
6351 else if (bytelit == 0)
6353 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6355 else if (IS_AOP_PREG (result))
6357 MOVA (aopGet (left, offset, FALSE, TRUE));
6358 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6359 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6362 emitcode ("anl", "%s,%s",
6363 aopGet (left, offset, FALSE, TRUE),
6364 aopGet (right, offset, FALSE, FALSE));
6368 if (AOP_TYPE (left) == AOP_ACC && offset == 0)
6370 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6374 MOVA (aopGet (right, offset, FALSE, FALSE));
6375 if (IS_AOP_PREG (result))
6377 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6378 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6381 emitcode ("anl", "%s,a",
6382 aopGet (left, offset, FALSE, TRUE));
6389 // left & result in different registers
6390 if (AOP_TYPE (result) == AOP_CRY)
6393 // if(size), result in bit
6394 // if(!size && ifx), conditional oper: if(left & right)
6395 symbol *tlbl = newiTempLabel (NULL);
6396 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6398 emitcode ("setb", "c");
6401 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6402 && AOP_TYPE(left)==AOP_ACC)
6405 emitcode("mov", "a,b");
6406 emitcode ("anl", "a,%s",
6407 aopGet (right, offset, FALSE, FALSE));
6409 if (AOP_TYPE(left)==AOP_ACC)
6413 bool pushedB = pushB ();
6414 emitcode("mov", "b,a");
6415 MOVA (aopGet (right, offset, FALSE, FALSE));
6416 emitcode("anl", "a,b");
6421 MOVA (aopGet (right, offset, FALSE, FALSE));
6422 emitcode("anl", "a,b");
6425 MOVA (aopGet (right, offset, FALSE, FALSE));
6426 emitcode ("anl", "a,%s",
6427 aopGet (left, offset, FALSE, FALSE));
6430 emitcode ("jnz", "%05d$", tlbl->key + 100);
6436 emitcode ("", "%05d$:", tlbl->key + 100);
6440 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6442 emitcode ("", "%05d$:", tlbl->key + 100);
6446 for (; (size--); offset++)
6449 // result = left & right
6450 if (AOP_TYPE (right) == AOP_LIT)
6452 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6453 if (bytelit == 0x0FF)
6456 aopGet (left, offset, FALSE, FALSE),
6458 isOperandVolatile (result, FALSE));
6461 else if (bytelit == 0)
6463 /* dummy read of volatile operand */
6464 if (isOperandVolatile (left, FALSE))
6465 MOVA (aopGet (left, offset, FALSE, FALSE));
6466 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6469 else if (AOP_TYPE (left) == AOP_ACC)
6473 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6474 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6479 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6480 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6485 // faster than result <- left, anl result,right
6486 // and better if result is SFR
6487 if (AOP_TYPE (left) == AOP_ACC)
6490 emitcode("mov", "a,b");
6491 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6495 MOVA (aopGet (right, offset, FALSE, FALSE));
6496 emitcode ("anl", "a,%s",
6497 aopGet (left, offset, FALSE, FALSE));
6499 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6505 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6506 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6507 freeAsmop (result, NULL, ic, TRUE);
6510 /*-----------------------------------------------------------------*/
6511 /* genOr - code for or */
6512 /*-----------------------------------------------------------------*/
6514 genOr (iCode * ic, iCode * ifx)
6516 operand *left, *right, *result;
6517 int size, offset = 0;
6518 unsigned long lit = 0L;
6521 D(emitcode ("; genOr",""));
6523 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6524 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6525 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6528 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6530 AOP_TYPE (left), AOP_TYPE (right));
6531 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6533 AOP_SIZE (left), AOP_SIZE (right));
6536 /* if left is a literal & right is not then exchange them */
6537 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6538 AOP_NEEDSACC (left))
6540 operand *tmp = right;
6545 /* if result = right then exchange them */
6546 if (sameRegs (AOP (result), AOP (right)))
6548 operand *tmp = right;
6553 /* if right is bit then exchange them */
6554 if (AOP_TYPE (right) == AOP_CRY &&
6555 AOP_TYPE (left) != AOP_CRY)
6557 operand *tmp = right;
6561 if (AOP_TYPE (right) == AOP_LIT)
6562 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6564 size = AOP_SIZE (result);
6568 if (AOP_TYPE (left) == AOP_CRY)
6570 if (AOP_TYPE (right) == AOP_LIT)
6572 // c = bit | literal;
6575 // lit != 0 => result = 1
6576 if (AOP_TYPE (result) == AOP_CRY)
6579 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6581 continueIfTrue (ifx);
6584 emitcode ("setb", "c");
6588 // lit == 0 => result = left
6589 if (size && sameRegs (AOP (result), AOP (left)))
6591 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6596 if (AOP_TYPE (right) == AOP_CRY)
6599 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6600 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6605 symbol *tlbl = newiTempLabel (NULL);
6606 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6607 emitcode ("setb", "c");
6608 emitcode ("jb", "%s,%05d$",
6609 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6611 emitcode ("jnz", "%05d$", tlbl->key + 100);
6612 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6614 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6620 emitcode ("", "%05d$:", tlbl->key + 100);
6629 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6630 genIfxJump (ifx, "c", left, right, result);
6634 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6635 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6636 if ((AOP_TYPE (right) == AOP_LIT) &&
6637 (AOP_TYPE (result) == AOP_CRY) &&
6638 (AOP_TYPE (left) != AOP_CRY))
6644 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6646 continueIfTrue (ifx);
6651 // lit = 0, result = boolean(left)
6653 emitcode ("setb", "c");
6657 symbol *tlbl = newiTempLabel (NULL);
6658 emitcode ("jnz", "%05d$", tlbl->key + 100);
6660 emitcode ("", "%05d$:", tlbl->key + 100);
6664 genIfxJump (ifx, "a", left, right, result);
6672 /* if left is same as result */
6673 if (sameRegs (AOP (result), AOP (left)))
6675 for (; size--; offset++)
6677 if (AOP_TYPE (right) == AOP_LIT)
6679 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6682 /* dummy read of volatile operand */
6683 if (isOperandVolatile (left, FALSE))
6684 MOVA (aopGet (left, offset, FALSE, FALSE));
6688 else if (bytelit == 0x0FF)
6690 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6692 else if (IS_AOP_PREG (left))
6694 MOVA (aopGet (left, offset, FALSE, TRUE));
6695 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6696 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6700 emitcode ("orl", "%s,%s",
6701 aopGet (left, offset, FALSE, TRUE),
6702 aopGet (right, offset, FALSE, FALSE));
6707 if (AOP_TYPE (left) == AOP_ACC)
6710 emitcode("mov", "a,b");
6711 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6715 MOVA (aopGet (right, offset, FALSE, FALSE));
6716 if (IS_AOP_PREG (left))
6718 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6719 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6723 emitcode ("orl", "%s,a",
6724 aopGet (left, offset, FALSE, TRUE));
6732 // left & result in different registers
6733 if (AOP_TYPE (result) == AOP_CRY)
6736 // if(size), result in bit
6737 // if(!size && ifx), conditional oper: if(left | right)
6738 symbol *tlbl = newiTempLabel (NULL);
6739 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6741 emitcode ("setb", "c");
6744 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6746 emitcode("mov", "a,b");
6747 emitcode ("orl", "a,%s",
6748 aopGet (right, offset, FALSE, FALSE));
6750 MOVA (aopGet (right, offset, FALSE, FALSE));
6751 emitcode ("orl", "a,%s",
6752 aopGet (left, offset, FALSE, FALSE));
6754 emitcode ("jnz", "%05d$", tlbl->key + 100);
6760 emitcode ("", "%05d$:", tlbl->key + 100);
6764 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6766 emitcode ("", "%05d$:", tlbl->key + 100);
6770 for (; (size--); offset++)
6773 // result = left | right
6774 if (AOP_TYPE (right) == AOP_LIT)
6776 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6780 aopGet (left, offset, FALSE, FALSE),
6782 isOperandVolatile (result, FALSE));
6785 else if (bytelit == 0x0FF)
6787 /* dummy read of volatile operand */
6788 if (isOperandVolatile (left, FALSE))
6789 MOVA (aopGet (left, offset, FALSE, FALSE));
6790 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6794 // faster than result <- left, anl result,right
6795 // and better if result is SFR
6796 if (AOP_TYPE (left) == AOP_ACC)
6799 emitcode("mov", "a,b");
6800 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6804 MOVA (aopGet (right, offset, FALSE, FALSE));
6805 emitcode ("orl", "a,%s",
6806 aopGet (left, offset, FALSE, FALSE));
6808 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6814 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6815 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6816 freeAsmop (result, NULL, ic, TRUE);
6819 /*-----------------------------------------------------------------*/
6820 /* genXor - code for xclusive or */
6821 /*-----------------------------------------------------------------*/
6823 genXor (iCode * ic, iCode * ifx)
6825 operand *left, *right, *result;
6826 int size, offset = 0;
6827 unsigned long lit = 0L;
6830 D(emitcode ("; genXor",""));
6832 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6833 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6834 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6837 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6839 AOP_TYPE (left), AOP_TYPE (right));
6840 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6842 AOP_SIZE (left), AOP_SIZE (right));
6845 /* if left is a literal & right is not ||
6846 if left needs acc & right does not */
6847 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6848 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6850 operand *tmp = right;
6855 /* if result = right then exchange them */
6856 if (sameRegs (AOP (result), AOP (right)))
6858 operand *tmp = right;
6863 /* if right is bit then exchange them */
6864 if (AOP_TYPE (right) == AOP_CRY &&
6865 AOP_TYPE (left) != AOP_CRY)
6867 operand *tmp = right;
6871 if (AOP_TYPE (right) == AOP_LIT)
6872 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6874 size = AOP_SIZE (result);
6878 if (AOP_TYPE (left) == AOP_CRY)
6880 if (AOP_TYPE (right) == AOP_LIT)
6882 // c = bit & literal;
6885 // lit>>1 != 0 => result = 1
6886 if (AOP_TYPE (result) == AOP_CRY)
6889 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6891 continueIfTrue (ifx);
6894 emitcode ("setb", "c");
6901 // lit == 0, result = left
6902 if (size && sameRegs (AOP (result), AOP (left)))
6904 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6908 // lit == 1, result = not(left)
6909 if (size && sameRegs (AOP (result), AOP (left)))
6911 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6916 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6917 emitcode ("cpl", "c");
6926 symbol *tlbl = newiTempLabel (NULL);
6927 if (AOP_TYPE (right) == AOP_CRY)
6930 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6934 int sizer = AOP_SIZE (right);
6936 // if val>>1 != 0, result = 1
6937 emitcode ("setb", "c");
6940 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
6942 // test the msb of the lsb
6943 emitcode ("anl", "a,#0xfe");
6944 emitcode ("jnz", "%05d$", tlbl->key + 100);
6948 emitcode ("rrc", "a");
6950 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6951 emitcode ("cpl", "c");
6952 emitcode ("", "%05d$:", (tlbl->key + 100));
6959 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6960 genIfxJump (ifx, "c", left, right, result);
6964 /* if left is same as result */
6965 if (sameRegs (AOP (result), AOP (left)))
6967 for (; size--; offset++)
6969 if (AOP_TYPE (right) == AOP_LIT)
6971 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6974 /* dummy read of volatile operand */
6975 if (isOperandVolatile (left, FALSE))
6976 MOVA (aopGet (left, offset, FALSE, FALSE));
6980 else if (IS_AOP_PREG (left))
6982 MOVA (aopGet (left, offset, FALSE, TRUE));
6983 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6984 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6988 emitcode ("xrl", "%s,%s",
6989 aopGet (left, offset, FALSE, TRUE),
6990 aopGet (right, offset, FALSE, FALSE));
6995 if (AOP_TYPE (left) == AOP_ACC)
6998 emitcode("mov", "a,b");
6999 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7003 MOVA (aopGet (right, offset, FALSE, FALSE));
7004 if (IS_AOP_PREG (left))
7006 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7007 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7010 emitcode ("xrl", "%s,a",
7011 aopGet (left, offset, FALSE, TRUE));
7018 // left & result in different registers
7019 if (AOP_TYPE (result) == AOP_CRY)
7022 // if(size), result in bit
7023 // if(!size && ifx), conditional oper: if(left ^ right)
7024 symbol *tlbl = newiTempLabel (NULL);
7025 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7027 emitcode ("setb", "c");
7030 if ((AOP_TYPE (right) == AOP_LIT) &&
7031 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7033 MOVA (aopGet (left, offset, FALSE, FALSE));
7037 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7039 emitcode("mov", "a,b");
7040 emitcode ("xrl", "a,%s",
7041 aopGet (right, offset, FALSE, FALSE));
7043 MOVA (aopGet (right, offset, FALSE, FALSE));
7044 emitcode ("xrl", "a,%s",
7045 aopGet (left, offset, FALSE, FALSE));
7048 emitcode ("jnz", "%05d$", tlbl->key + 100);
7054 emitcode ("", "%05d$:", tlbl->key + 100);
7058 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7062 for (; (size--); offset++)
7065 // result = left & right
7066 if (AOP_TYPE (right) == AOP_LIT)
7068 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7072 aopGet (left, offset, FALSE, FALSE),
7074 isOperandVolatile (result, FALSE));
7078 // faster than result <- left, anl result,right
7079 // and better if result is SFR
7080 if (AOP_TYPE (left) == AOP_ACC)
7083 emitcode("mov", "a,b");
7084 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7088 MOVA (aopGet (right, offset, FALSE, FALSE));
7089 emitcode ("xrl", "a,%s",
7090 aopGet (left, offset, FALSE, TRUE));
7092 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7098 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7099 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7100 freeAsmop (result, NULL, ic, TRUE);
7103 /*-----------------------------------------------------------------*/
7104 /* genInline - write the inline code out */
7105 /*-----------------------------------------------------------------*/
7107 genInline (iCode * ic)
7109 char *buffer, *bp, *bp1;
7111 D(emitcode ("; genInline",""));
7113 _G.inLine += (!options.asmpeep);
7115 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7116 strcpy (buffer, IC_INLINE (ic));
7118 /* emit each line as a code */
7129 /* Add \n for labels, not dirs such as c:\mydir */
7130 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7144 /* emitcode("",buffer); */
7145 _G.inLine -= (!options.asmpeep);
7148 /*-----------------------------------------------------------------*/
7149 /* genRRC - rotate right with carry */
7150 /*-----------------------------------------------------------------*/
7154 operand *left, *result;
7155 int size, offset = 0;
7158 D(emitcode ("; genRRC",""));
7160 /* rotate right with carry */
7161 left = IC_LEFT (ic);
7162 result = IC_RESULT (ic);
7163 aopOp (left, ic, FALSE);
7164 aopOp (result, ic, FALSE);
7166 /* move it to the result */
7167 size = AOP_SIZE (result);
7169 if (size == 1) { /* special case for 1 byte */
7170 l = aopGet (left, offset, FALSE, FALSE);
7172 emitcode ("rr", "a");
7175 /* no need to clear carry, bit7 will be written later */
7178 l = aopGet (left, offset, FALSE, FALSE);
7180 emitcode ("rrc", "a");
7181 if (AOP_SIZE (result) > 1)
7182 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7184 /* now we need to put the carry into the
7185 highest order byte of the result */
7186 if (AOP_SIZE (result) > 1)
7188 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7191 emitcode ("mov", "acc.7,c");
7193 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7194 freeAsmop (left, NULL, ic, TRUE);
7195 freeAsmop (result, NULL, ic, TRUE);
7198 /*-----------------------------------------------------------------*/
7199 /* genRLC - generate code for rotate left with carry */
7200 /*-----------------------------------------------------------------*/
7204 operand *left, *result;
7205 int size, offset = 0;
7208 D(emitcode ("; genRLC",""));
7210 /* rotate right with carry */
7211 left = IC_LEFT (ic);
7212 result = IC_RESULT (ic);
7213 aopOp (left, ic, FALSE);
7214 aopOp (result, ic, FALSE);
7216 /* move it to the result */
7217 size = AOP_SIZE (result);
7221 l = aopGet (left, offset, FALSE, FALSE);
7223 if (size == 0) { /* special case for 1 byte */
7227 emitcode("rlc","a"); /* bit0 will be written later */
7228 if (AOP_SIZE (result) > 1)
7229 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7232 l = aopGet (left, offset, FALSE, FALSE);
7234 emitcode ("rlc", "a");
7235 if (AOP_SIZE (result) > 1)
7236 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7239 /* now we need to put the carry into the
7240 highest order byte of the result */
7241 if (AOP_SIZE (result) > 1)
7243 l = aopGet (result, 0, FALSE, FALSE);
7246 emitcode ("mov", "acc.0,c");
7248 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7249 freeAsmop (left, NULL, ic, TRUE);
7250 freeAsmop (result, NULL, ic, TRUE);
7253 /*-----------------------------------------------------------------*/
7254 /* genGetHbit - generates code get highest order bit */
7255 /*-----------------------------------------------------------------*/
7257 genGetHbit (iCode * ic)
7259 operand *left, *result;
7261 D(emitcode ("; genGetHbit",""));
7263 left = IC_LEFT (ic);
7264 result = IC_RESULT (ic);
7265 aopOp (left, ic, FALSE);
7266 aopOp (result, ic, FALSE);
7268 /* get the highest order byte into a */
7269 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7270 if (AOP_TYPE (result) == AOP_CRY)
7272 emitcode ("rlc", "a");
7277 emitcode ("rl", "a");
7278 emitcode ("anl", "a,#0x01");
7283 freeAsmop (left, NULL, ic, TRUE);
7284 freeAsmop (result, NULL, ic, TRUE);
7287 /*-----------------------------------------------------------------*/
7288 /* genSwap - generates code to swap nibbles or bytes */
7289 /*-----------------------------------------------------------------*/
7291 genSwap (iCode * ic)
7293 operand *left, *result;
7295 D(emitcode ("; genSwap",""));
7297 left = IC_LEFT (ic);
7298 result = IC_RESULT (ic);
7299 aopOp (left, ic, FALSE);
7300 aopOp (result, ic, FALSE);
7302 switch (AOP_SIZE (left))
7304 case 1: /* swap nibbles in byte */
7305 MOVA (aopGet (left, 0, FALSE, FALSE));
7306 emitcode ("swap", "a");
7307 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7309 case 2: /* swap bytes in word */
7310 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7312 MOVA (aopGet (left, 0, FALSE, FALSE));
7313 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7314 0, isOperandVolatile (result, FALSE));
7315 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7317 else if (operandsEqu (left, result))
7320 bool pushedB = FALSE, leftInB = FALSE;
7322 MOVA (aopGet (left, 0, FALSE, FALSE));
7323 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7326 emitcode ("mov", "b,a");
7330 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7331 0, isOperandVolatile (result, FALSE));
7332 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7339 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7340 0, isOperandVolatile (result, FALSE));
7341 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7342 1, isOperandVolatile (result, FALSE));
7346 wassertl(FALSE, "unsupported SWAP operand size");
7349 freeAsmop (left, NULL, ic, TRUE);
7350 freeAsmop (result, NULL, ic, TRUE);
7354 /*-----------------------------------------------------------------*/
7355 /* AccRol - rotate left accumulator by known count */
7356 /*-----------------------------------------------------------------*/
7358 AccRol (int shCount)
7360 shCount &= 0x0007; // shCount : 0..7
7367 emitcode ("rl", "a");
7370 emitcode ("rl", "a");
7371 emitcode ("rl", "a");
7374 emitcode ("swap", "a");
7375 emitcode ("rr", "a");
7378 emitcode ("swap", "a");
7381 emitcode ("swap", "a");
7382 emitcode ("rl", "a");
7385 emitcode ("rr", "a");
7386 emitcode ("rr", "a");
7389 emitcode ("rr", "a");
7394 /*-----------------------------------------------------------------*/
7395 /* AccLsh - left shift accumulator by known count */
7396 /*-----------------------------------------------------------------*/
7398 AccLsh (int shCount)
7403 emitcode ("add", "a,acc");
7404 else if (shCount == 2)
7406 emitcode ("add", "a,acc");
7407 emitcode ("add", "a,acc");
7411 /* rotate left accumulator */
7413 /* and kill the lower order bits */
7414 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7419 /*-----------------------------------------------------------------*/
7420 /* AccRsh - right shift accumulator by known count */
7421 /*-----------------------------------------------------------------*/
7423 AccRsh (int shCount)
7430 emitcode ("rrc", "a");
7434 /* rotate right accumulator */
7435 AccRol (8 - shCount);
7436 /* and kill the higher order bits */
7437 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7442 /*-----------------------------------------------------------------*/
7443 /* AccSRsh - signed right shift accumulator by known count */
7444 /*-----------------------------------------------------------------*/
7446 AccSRsh (int shCount)
7453 emitcode ("mov", "c,acc.7");
7454 emitcode ("rrc", "a");
7456 else if (shCount == 2)
7458 emitcode ("mov", "c,acc.7");
7459 emitcode ("rrc", "a");
7460 emitcode ("mov", "c,acc.7");
7461 emitcode ("rrc", "a");
7465 tlbl = newiTempLabel (NULL);
7466 /* rotate right accumulator */
7467 AccRol (8 - shCount);
7468 /* and kill the higher order bits */
7469 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7470 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7471 emitcode ("orl", "a,#0x%02x",
7472 (unsigned char) ~SRMask[shCount]);
7473 emitcode ("", "%05d$:", tlbl->key + 100);
7478 /*-----------------------------------------------------------------*/
7479 /* shiftR1Left2Result - shift right one byte from left to result */
7480 /*-----------------------------------------------------------------*/
7482 shiftR1Left2Result (operand * left, int offl,
7483 operand * result, int offr,
7484 int shCount, int sign)
7486 MOVA (aopGet (left, offl, FALSE, FALSE));
7487 /* shift right accumulator */
7492 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7495 /*-----------------------------------------------------------------*/
7496 /* shiftL1Left2Result - shift left one byte from left to result */
7497 /*-----------------------------------------------------------------*/
7499 shiftL1Left2Result (operand * left, int offl,
7500 operand * result, int offr, int shCount)
7503 l = aopGet (left, offl, FALSE, FALSE);
7505 /* shift left accumulator */
7507 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7510 /*-----------------------------------------------------------------*/
7511 /* movLeft2Result - move byte from left to result */
7512 /*-----------------------------------------------------------------*/
7514 movLeft2Result (operand * left, int offl,
7515 operand * result, int offr, int sign)
7518 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7520 l = aopGet (left, offl, FALSE, FALSE);
7522 if (*l == '@' && (IS_AOP_PREG (result)))
7524 emitcode ("mov", "a,%s", l);
7525 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7530 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7533 /* MSB sign in acc.7 ! */
7534 if (getDataSize (left) == offl + 1)
7536 emitcode ("mov", "a,%s", l);
7537 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7544 /*-----------------------------------------------------------------*/
7545 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7546 /*-----------------------------------------------------------------*/
7550 emitcode ("rrc", "a");
7551 emitcode ("xch", "a,%s", x);
7552 emitcode ("rrc", "a");
7553 emitcode ("xch", "a,%s", x);
7556 /*-----------------------------------------------------------------*/
7557 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7558 /*-----------------------------------------------------------------*/
7562 emitcode ("xch", "a,%s", x);
7563 emitcode ("rlc", "a");
7564 emitcode ("xch", "a,%s", x);
7565 emitcode ("rlc", "a");
7568 /*-----------------------------------------------------------------*/
7569 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7570 /*-----------------------------------------------------------------*/
7574 emitcode ("xch", "a,%s", x);
7575 emitcode ("add", "a,acc");
7576 emitcode ("xch", "a,%s", x);
7577 emitcode ("rlc", "a");
7580 /*-----------------------------------------------------------------*/
7581 /* AccAXLsh - left shift a:x by known count (0..7) */
7582 /*-----------------------------------------------------------------*/
7584 AccAXLsh (char *x, int shCount)
7599 case 5: // AAAAABBB:CCCCCDDD
7601 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7603 emitcode ("anl", "a,#0x%02x",
7604 SLMask[shCount]); // BBB00000:CCCCCDDD
7606 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7608 AccRol (shCount); // DDDCCCCC:BBB00000
7610 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7612 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7614 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7616 emitcode ("anl", "a,#0x%02x",
7617 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7619 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7621 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7624 case 6: // AAAAAABB:CCCCCCDD
7625 emitcode ("anl", "a,#0x%02x",
7626 SRMask[shCount]); // 000000BB:CCCCCCDD
7627 emitcode ("mov", "c,acc.0"); // c = B
7628 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7630 AccAXRrl1 (x); // BCCCCCCD:D000000B
7631 AccAXRrl1 (x); // BBCCCCCC:DD000000
7633 emitcode("rrc","a");
7634 emitcode("xch","a,%s", x);
7635 emitcode("rrc","a");
7636 emitcode("mov","c,acc.0"); //<< get correct bit
7637 emitcode("xch","a,%s", x);
7639 emitcode("rrc","a");
7640 emitcode("xch","a,%s", x);
7641 emitcode("rrc","a");
7642 emitcode("xch","a,%s", x);
7645 case 7: // a:x <<= 7
7647 emitcode ("anl", "a,#0x%02x",
7648 SRMask[shCount]); // 0000000B:CCCCCCCD
7650 emitcode ("mov", "c,acc.0"); // c = B
7652 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7654 AccAXRrl1 (x); // BCCCCCCC:D0000000
7662 /*-----------------------------------------------------------------*/
7663 /* AccAXRsh - right shift a:x known count (0..7) */
7664 /*-----------------------------------------------------------------*/
7666 AccAXRsh (char *x, int shCount)
7674 AccAXRrl1 (x); // 0->a:x
7679 AccAXRrl1 (x); // 0->a:x
7682 AccAXRrl1 (x); // 0->a:x
7687 case 5: // AAAAABBB:CCCCCDDD = a:x
7689 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7691 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7693 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7695 emitcode ("anl", "a,#0x%02x",
7696 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7698 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7700 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7702 emitcode ("anl", "a,#0x%02x",
7703 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7705 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7707 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7709 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7712 case 6: // AABBBBBB:CCDDDDDD
7714 emitcode ("mov", "c,acc.7");
7715 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7717 emitcode ("mov", "c,acc.7");
7718 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7720 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7722 emitcode ("anl", "a,#0x%02x",
7723 SRMask[shCount]); // 000000AA:BBBBBBCC
7726 case 7: // ABBBBBBB:CDDDDDDD
7728 emitcode ("mov", "c,acc.7"); // c = A
7730 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7732 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7734 emitcode ("anl", "a,#0x%02x",
7735 SRMask[shCount]); // 0000000A:BBBBBBBC
7743 /*-----------------------------------------------------------------*/
7744 /* AccAXRshS - right shift signed a:x known count (0..7) */
7745 /*-----------------------------------------------------------------*/
7747 AccAXRshS (char *x, int shCount)
7755 emitcode ("mov", "c,acc.7");
7756 AccAXRrl1 (x); // s->a:x
7760 emitcode ("mov", "c,acc.7");
7761 AccAXRrl1 (x); // s->a:x
7763 emitcode ("mov", "c,acc.7");
7764 AccAXRrl1 (x); // s->a:x
7769 case 5: // AAAAABBB:CCCCCDDD = a:x
7771 tlbl = newiTempLabel (NULL);
7772 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7774 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7776 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7778 emitcode ("anl", "a,#0x%02x",
7779 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7781 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7783 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7785 emitcode ("anl", "a,#0x%02x",
7786 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7788 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7790 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7792 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7794 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7795 emitcode ("orl", "a,#0x%02x",
7796 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7798 emitcode ("", "%05d$:", tlbl->key + 100);
7799 break; // SSSSAAAA:BBBCCCCC
7801 case 6: // AABBBBBB:CCDDDDDD
7803 tlbl = newiTempLabel (NULL);
7804 emitcode ("mov", "c,acc.7");
7805 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7807 emitcode ("mov", "c,acc.7");
7808 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7810 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7812 emitcode ("anl", "a,#0x%02x",
7813 SRMask[shCount]); // 000000AA:BBBBBBCC
7815 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7816 emitcode ("orl", "a,#0x%02x",
7817 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7819 emitcode ("", "%05d$:", tlbl->key + 100);
7821 case 7: // ABBBBBBB:CDDDDDDD
7823 tlbl = newiTempLabel (NULL);
7824 emitcode ("mov", "c,acc.7"); // c = A
7826 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7828 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7830 emitcode ("anl", "a,#0x%02x",
7831 SRMask[shCount]); // 0000000A:BBBBBBBC
7833 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7834 emitcode ("orl", "a,#0x%02x",
7835 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7837 emitcode ("", "%05d$:", tlbl->key + 100);
7844 /*-----------------------------------------------------------------*/
7845 /* shiftL2Left2Result - shift left two bytes from left to result */
7846 /*-----------------------------------------------------------------*/
7848 shiftL2Left2Result (operand * left, int offl,
7849 operand * result, int offr, int shCount)
7851 if (sameRegs (AOP (result), AOP (left)) &&
7852 ((offl + MSB16) == offr))
7854 /* don't crash result[offr] */
7855 MOVA (aopGet (left, offl, FALSE, FALSE));
7856 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7860 movLeft2Result (left, offl, result, offr, 0);
7861 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7863 /* ax << shCount (x = lsb(result)) */
7864 AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount);
7865 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7869 /*-----------------------------------------------------------------*/
7870 /* shiftR2Left2Result - shift right two bytes from left to result */
7871 /*-----------------------------------------------------------------*/
7873 shiftR2Left2Result (operand * left, int offl,
7874 operand * result, int offr,
7875 int shCount, int sign)
7877 if (sameRegs (AOP (result), AOP (left)) &&
7878 ((offl + MSB16) == offr))
7880 /* don't crash result[offr] */
7881 MOVA (aopGet (left, offl, FALSE, FALSE));
7882 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
7886 movLeft2Result (left, offl, result, offr, 0);
7887 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
7889 /* a:x >> shCount (x = lsb(result)) */
7891 AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount);
7893 AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount);
7894 if (getDataSize (result) > 1)
7895 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
7898 /*-----------------------------------------------------------------*/
7899 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7900 /*-----------------------------------------------------------------*/
7902 shiftLLeftOrResult (operand * left, int offl,
7903 operand * result, int offr, int shCount)
7905 MOVA (aopGet (left, offl, FALSE, FALSE));
7906 /* shift left accumulator */
7908 /* or with result */
7909 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7910 /* back to result */
7911 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7914 /*-----------------------------------------------------------------*/
7915 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7916 /*-----------------------------------------------------------------*/
7918 shiftRLeftOrResult (operand * left, int offl,
7919 operand * result, int offr, int shCount)
7921 MOVA (aopGet (left, offl, FALSE, FALSE));
7922 /* shift right accumulator */
7924 /* or with result */
7925 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
7926 /* back to result */
7927 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7930 /*-----------------------------------------------------------------*/
7931 /* genlshOne - left shift a one byte quantity by known count */
7932 /*-----------------------------------------------------------------*/
7934 genlshOne (operand * result, operand * left, int shCount)
7936 D(emitcode ("; genlshOne",""));
7938 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7941 /*-----------------------------------------------------------------*/
7942 /* genlshTwo - left shift two bytes by known amount != 0 */
7943 /*-----------------------------------------------------------------*/
7945 genlshTwo (operand * result, operand * left, int shCount)
7949 D(emitcode ("; genlshTwo",""));
7951 size = getDataSize (result);
7953 /* if shCount >= 8 */
7961 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
7963 movLeft2Result (left, LSB, result, MSB16, 0);
7965 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
7968 /* 1 <= shCount <= 7 */
7972 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7974 shiftL2Left2Result (left, LSB, result, LSB, shCount);
7978 /*-----------------------------------------------------------------*/
7979 /* shiftLLong - shift left one long from left to result */
7980 /* offl = LSB or MSB16 */
7981 /*-----------------------------------------------------------------*/
7983 shiftLLong (operand * left, operand * result, int offr)
7986 int size = AOP_SIZE (result);
7988 if (size >= LSB + offr)
7990 l = aopGet (left, LSB, FALSE, FALSE);
7992 emitcode ("add", "a,acc");
7993 if (sameRegs (AOP (left), AOP (result)) &&
7994 size >= MSB16 + offr && offr != LSB)
7995 emitcode ("xch", "a,%s",
7996 aopGet (left, LSB + offr, FALSE, FALSE));
7998 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8001 if (size >= MSB16 + offr)
8003 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8005 l = aopGet (left, MSB16, FALSE, FALSE);
8008 emitcode ("rlc", "a");
8009 if (sameRegs (AOP (left), AOP (result)) &&
8010 size >= MSB24 + offr && offr != LSB)
8011 emitcode ("xch", "a,%s",
8012 aopGet (left, MSB16 + offr, FALSE, FALSE));
8014 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8017 if (size >= MSB24 + offr)
8019 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8021 l = aopGet (left, MSB24, FALSE, FALSE);
8024 emitcode ("rlc", "a");
8025 if (sameRegs (AOP (left), AOP (result)) &&
8026 size >= MSB32 + offr && offr != LSB)
8027 emitcode ("xch", "a,%s",
8028 aopGet (left, MSB24 + offr, FALSE, FALSE));
8030 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8033 if (size > MSB32 + offr)
8035 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8037 l = aopGet (left, MSB32, FALSE, FALSE);
8040 emitcode ("rlc", "a");
8041 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8044 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8047 /*-----------------------------------------------------------------*/
8048 /* genlshFour - shift four byte by a known amount != 0 */
8049 /*-----------------------------------------------------------------*/
8051 genlshFour (operand * result, operand * left, int shCount)
8055 D(emitcode ("; genlshFour",""));
8057 size = AOP_SIZE (result);
8059 /* if shifting more that 3 bytes */
8064 /* lowest order of left goes to the highest
8065 order of the destination */
8066 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8068 movLeft2Result (left, LSB, result, MSB32, 0);
8069 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8070 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8071 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8075 /* more than two bytes */
8076 else if (shCount >= 16)
8078 /* lower order two bytes goes to higher order two bytes */
8080 /* if some more remaining */
8082 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8085 movLeft2Result (left, MSB16, result, MSB32, 0);
8086 movLeft2Result (left, LSB, result, MSB24, 0);
8088 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8089 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8093 /* if more than 1 byte */
8094 else if (shCount >= 8)
8096 /* lower order three bytes goes to higher order three bytes */
8101 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8103 movLeft2Result (left, LSB, result, MSB16, 0);
8109 movLeft2Result (left, MSB24, result, MSB32, 0);
8110 movLeft2Result (left, MSB16, result, MSB24, 0);
8111 movLeft2Result (left, LSB, result, MSB16, 0);
8112 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8114 else if (shCount == 1)
8115 shiftLLong (left, result, MSB16);
8118 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8119 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8120 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8121 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8126 /* 1 <= shCount <= 7 */
8127 else if (shCount <= 2)
8129 shiftLLong (left, result, LSB);
8131 shiftLLong (result, result, LSB);
8133 /* 3 <= shCount <= 7, optimize */
8136 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8137 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8138 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8142 /*-----------------------------------------------------------------*/
8143 /* genLeftShiftLiteral - left shifting by known count */
8144 /*-----------------------------------------------------------------*/
8146 genLeftShiftLiteral (operand * left,
8151 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8154 D(emitcode ("; genLeftShiftLiteral",""));
8156 freeAsmop (right, NULL, ic, TRUE);
8158 aopOp (left, ic, FALSE);
8159 aopOp (result, ic, FALSE);
8161 size = getSize (operandType (result));
8164 emitcode ("; shift left ", "result %d, left %d", size,
8168 /* I suppose that the left size >= result size */
8173 movLeft2Result (left, size, result, size, 0);
8177 else if (shCount >= (size * 8))
8179 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8185 genlshOne (result, left, shCount);
8189 genlshTwo (result, left, shCount);
8193 genlshFour (result, left, shCount);
8196 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8197 "*** ack! mystery literal shift!\n");
8201 freeAsmop (left, NULL, ic, TRUE);
8202 freeAsmop (result, NULL, ic, TRUE);
8205 /*-----------------------------------------------------------------*/
8206 /* genLeftShift - generates code for left shifting */
8207 /*-----------------------------------------------------------------*/
8209 genLeftShift (iCode * ic)
8211 operand *left, *right, *result;
8214 symbol *tlbl, *tlbl1;
8217 D(emitcode ("; genLeftShift",""));
8219 right = IC_RIGHT (ic);
8220 left = IC_LEFT (ic);
8221 result = IC_RESULT (ic);
8223 aopOp (right, ic, FALSE);
8225 /* if the shift count is known then do it
8226 as efficiently as possible */
8227 if (AOP_TYPE (right) == AOP_LIT)
8229 genLeftShiftLiteral (left, right, result, ic);
8233 /* shift count is unknown then we have to form
8234 a loop get the loop count in B : Note: we take
8235 only the lower order byte since shifting
8236 more that 32 bits make no sense anyway, ( the
8237 largest size of an object can be only 32 bits ) */
8240 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8241 emitcode ("inc", "b");
8242 freeAsmop (right, NULL, ic, TRUE);
8243 aopOp (left, ic, FALSE);
8244 aopOp (result, ic, FALSE);
8246 /* now move the left to the result if they are not the same */
8247 if (!sameRegs (AOP (left), AOP (result)) &&
8248 AOP_SIZE (result) > 1)
8251 size = AOP_SIZE (result);
8255 l = aopGet (left, offset, FALSE, TRUE);
8256 if (*l == '@' && (IS_AOP_PREG (result)))
8259 emitcode ("mov", "a,%s", l);
8260 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8263 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8268 tlbl = newiTempLabel (NULL);
8269 size = AOP_SIZE (result);
8271 tlbl1 = newiTempLabel (NULL);
8273 /* if it is only one byte then */
8276 symbol *tlbl1 = newiTempLabel (NULL);
8278 l = aopGet (left, 0, FALSE, FALSE);
8280 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8281 emitcode ("", "%05d$:", tlbl->key + 100);
8282 emitcode ("add", "a,acc");
8283 emitcode ("", "%05d$:", tlbl1->key + 100);
8284 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8286 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8290 reAdjustPreg (AOP (result));
8292 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8293 emitcode ("", "%05d$:", tlbl->key + 100);
8294 l = aopGet (result, offset, FALSE, FALSE);
8296 emitcode ("add", "a,acc");
8297 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8300 l = aopGet (result, offset, FALSE, FALSE);
8302 emitcode ("rlc", "a");
8303 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8305 reAdjustPreg (AOP (result));
8307 emitcode ("", "%05d$:", tlbl1->key + 100);
8308 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8311 freeAsmop (left, NULL, ic, TRUE);
8312 freeAsmop (result, NULL, ic, TRUE);
8315 /*-----------------------------------------------------------------*/
8316 /* genrshOne - right shift a one byte quantity by known count */
8317 /*-----------------------------------------------------------------*/
8319 genrshOne (operand * result, operand * left,
8320 int shCount, int sign)
8322 D(emitcode ("; genrshOne",""));
8324 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8327 /*-----------------------------------------------------------------*/
8328 /* genrshTwo - right shift two bytes by known amount != 0 */
8329 /*-----------------------------------------------------------------*/
8331 genrshTwo (operand * result, operand * left,
8332 int shCount, int sign)
8334 D(emitcode ("; genrshTwo",""));
8336 /* if shCount >= 8 */
8341 shiftR1Left2Result (left, MSB16, result, LSB,
8344 movLeft2Result (left, MSB16, result, LSB, sign);
8345 addSign (result, MSB16, sign);
8348 /* 1 <= shCount <= 7 */
8350 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8353 /*-----------------------------------------------------------------*/
8354 /* shiftRLong - shift right one long from left to result */
8355 /* offl = LSB or MSB16 */
8356 /*-----------------------------------------------------------------*/
8358 shiftRLong (operand * left, int offl,
8359 operand * result, int sign)
8361 int isSameRegs=sameRegs(AOP(left),AOP(result));
8363 if (isSameRegs && offl>1) {
8364 // we are in big trouble, but this shouldn't happen
8365 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8368 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8373 emitcode ("rlc", "a");
8374 emitcode ("subb", "a,acc");
8376 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8378 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8379 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8382 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8387 emitcode ("clr", "c");
8389 emitcode ("mov", "c,acc.7");
8392 emitcode ("rrc", "a");
8394 if (isSameRegs && offl==MSB16) {
8395 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8397 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8398 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8401 emitcode ("rrc", "a");
8402 if (isSameRegs && offl==1) {
8403 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8405 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8406 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8408 emitcode ("rrc", "a");
8409 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8413 MOVA (aopGet (left, LSB, FALSE, FALSE));
8414 emitcode ("rrc", "a");
8415 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8419 /*-----------------------------------------------------------------*/
8420 /* genrshFour - shift four byte by a known amount != 0 */
8421 /*-----------------------------------------------------------------*/
8423 genrshFour (operand * result, operand * left,
8424 int shCount, int sign)
8426 D(emitcode ("; genrshFour",""));
8428 /* if shifting more that 3 bytes */
8433 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8435 movLeft2Result (left, MSB32, result, LSB, sign);
8436 addSign (result, MSB16, sign);
8438 else if (shCount >= 16)
8442 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8445 movLeft2Result (left, MSB24, result, LSB, 0);
8446 movLeft2Result (left, MSB32, result, MSB16, sign);
8448 addSign (result, MSB24, sign);
8450 else if (shCount >= 8)
8454 shiftRLong (left, MSB16, result, sign);
8455 else if (shCount == 0)
8457 movLeft2Result (left, MSB16, result, LSB, 0);
8458 movLeft2Result (left, MSB24, result, MSB16, 0);
8459 movLeft2Result (left, MSB32, result, MSB24, sign);
8460 addSign (result, MSB32, sign);
8464 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8465 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8466 /* the last shift is signed */
8467 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8468 addSign (result, MSB32, sign);
8472 { /* 1 <= shCount <= 7 */
8475 shiftRLong (left, LSB, result, sign);
8477 shiftRLong (result, LSB, result, sign);
8481 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8482 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8483 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8488 /*-----------------------------------------------------------------*/
8489 /* genRightShiftLiteral - right shifting by known count */
8490 /*-----------------------------------------------------------------*/
8492 genRightShiftLiteral (operand * left,
8498 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8501 D(emitcode ("; genRightShiftLiteral",""));
8503 freeAsmop (right, NULL, ic, TRUE);
8505 aopOp (left, ic, FALSE);
8506 aopOp (result, ic, FALSE);
8509 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8513 size = getDataSize (left);
8514 /* test the LEFT size !!! */
8516 /* I suppose that the left size >= result size */
8519 size = getDataSize (result);
8521 movLeft2Result (left, size, result, size, 0);
8524 else if (shCount >= (size * 8))
8527 /* get sign in acc.7 */
8528 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8530 addSign (result, LSB, sign);
8537 genrshOne (result, left, shCount, sign);
8541 genrshTwo (result, left, shCount, sign);
8545 genrshFour (result, left, shCount, sign);
8551 freeAsmop (left, NULL, ic, TRUE);
8552 freeAsmop (result, NULL, ic, TRUE);
8555 /*-----------------------------------------------------------------*/
8556 /* genSignedRightShift - right shift of signed number */
8557 /*-----------------------------------------------------------------*/
8559 genSignedRightShift (iCode * ic)
8561 operand *right, *left, *result;
8564 symbol *tlbl, *tlbl1;
8567 D(emitcode ("; genSignedRightShift",""));
8569 /* we do it the hard way put the shift count in b
8570 and loop thru preserving the sign */
8572 right = IC_RIGHT (ic);
8573 left = IC_LEFT (ic);
8574 result = IC_RESULT (ic);
8576 aopOp (right, ic, FALSE);
8579 if (AOP_TYPE (right) == AOP_LIT)
8581 genRightShiftLiteral (left, right, result, ic, 1);
8584 /* shift count is unknown then we have to form
8585 a loop get the loop count in B : Note: we take
8586 only the lower order byte since shifting
8587 more that 32 bits make no sense anyway, ( the
8588 largest size of an object can be only 32 bits ) */
8591 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8592 emitcode ("inc", "b");
8593 freeAsmop (right, NULL, ic, TRUE);
8594 aopOp (left, ic, FALSE);
8595 aopOp (result, ic, FALSE);
8597 /* now move the left to the result if they are not the
8599 if (!sameRegs (AOP (left), AOP (result)) &&
8600 AOP_SIZE (result) > 1)
8603 size = AOP_SIZE (result);
8607 l = aopGet (left, offset, FALSE, TRUE);
8608 if (*l == '@' && IS_AOP_PREG (result))
8611 emitcode ("mov", "a,%s", l);
8612 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8615 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8620 /* mov the highest order bit to OVR */
8621 tlbl = newiTempLabel (NULL);
8622 tlbl1 = newiTempLabel (NULL);
8624 size = AOP_SIZE (result);
8626 MOVA (aopGet (left, offset, FALSE, FALSE));
8627 emitcode ("rlc", "a");
8628 emitcode ("mov", "ov,c");
8629 /* if it is only one byte then */
8632 l = aopGet (left, 0, FALSE, FALSE);
8634 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8635 emitcode ("", "%05d$:", tlbl->key + 100);
8636 emitcode ("mov", "c,ov");
8637 emitcode ("rrc", "a");
8638 emitcode ("", "%05d$:", tlbl1->key + 100);
8639 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8641 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8645 reAdjustPreg (AOP (result));
8646 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8647 emitcode ("", "%05d$:", tlbl->key + 100);
8648 emitcode ("mov", "c,ov");
8651 l = aopGet (result, offset, FALSE, FALSE);
8653 emitcode ("rrc", "a");
8654 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8656 reAdjustPreg (AOP (result));
8657 emitcode ("", "%05d$:", tlbl1->key + 100);
8658 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8662 freeAsmop (left, NULL, ic, TRUE);
8663 freeAsmop (result, NULL, ic, TRUE);
8666 /*-----------------------------------------------------------------*/
8667 /* genRightShift - generate code for right shifting */
8668 /*-----------------------------------------------------------------*/
8670 genRightShift (iCode * ic)
8672 operand *right, *left, *result;
8676 symbol *tlbl, *tlbl1;
8679 D(emitcode ("; genRightShift",""));
8681 /* if signed then we do it the hard way preserve the
8682 sign bit moving it inwards */
8683 letype = getSpec (operandType (IC_LEFT (ic)));
8685 if (!SPEC_USIGN (letype))
8687 genSignedRightShift (ic);
8691 /* signed & unsigned types are treated the same : i.e. the
8692 signed is NOT propagated inwards : quoting from the
8693 ANSI - standard : "for E1 >> E2, is equivalent to division
8694 by 2**E2 if unsigned or if it has a non-negative value,
8695 otherwise the result is implementation defined ", MY definition
8696 is that the sign does not get propagated */
8698 right = IC_RIGHT (ic);
8699 left = IC_LEFT (ic);
8700 result = IC_RESULT (ic);
8702 aopOp (right, ic, FALSE);
8704 /* if the shift count is known then do it
8705 as efficiently as possible */
8706 if (AOP_TYPE (right) == AOP_LIT)
8708 genRightShiftLiteral (left, right, result, ic, 0);
8712 /* shift count is unknown then we have to form
8713 a loop get the loop count in B : Note: we take
8714 only the lower order byte since shifting
8715 more that 32 bits make no sense anyway, ( the
8716 largest size of an object can be only 32 bits ) */
8719 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8720 emitcode ("inc", "b");
8721 freeAsmop (right, NULL, ic, TRUE);
8722 aopOp (left, ic, FALSE);
8723 aopOp (result, ic, FALSE);
8725 /* now move the left to the result if they are not the
8727 if (!sameRegs (AOP (left), AOP (result)) &&
8728 AOP_SIZE (result) > 1)
8731 size = AOP_SIZE (result);
8735 l = aopGet (left, offset, FALSE, TRUE);
8736 if (*l == '@' && IS_AOP_PREG (result))
8739 emitcode ("mov", "a,%s", l);
8740 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8743 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8748 tlbl = newiTempLabel (NULL);
8749 tlbl1 = newiTempLabel (NULL);
8750 size = AOP_SIZE (result);
8753 /* if it is only one byte then */
8756 l = aopGet (left, 0, FALSE, FALSE);
8758 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8759 emitcode ("", "%05d$:", tlbl->key + 100);
8761 emitcode ("rrc", "a");
8762 emitcode ("", "%05d$:", tlbl1->key + 100);
8763 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8765 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8769 reAdjustPreg (AOP (result));
8770 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8771 emitcode ("", "%05d$:", tlbl->key + 100);
8775 l = aopGet (result, offset, FALSE, FALSE);
8777 emitcode ("rrc", "a");
8778 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8780 reAdjustPreg (AOP (result));
8782 emitcode ("", "%05d$:", tlbl1->key + 100);
8783 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8787 freeAsmop (left, NULL, ic, TRUE);
8788 freeAsmop (result, NULL, ic, TRUE);
8791 /*-----------------------------------------------------------------*/
8792 /* emitPtrByteGet - emits code to get a byte into A through a */
8793 /* pointer register (R0, R1, or DPTR). The */
8794 /* original value of A can be preserved in B. */
8795 /*-----------------------------------------------------------------*/
8797 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8804 emitcode ("mov", "b,a");
8805 emitcode ("mov", "a,@%s", rname);
8810 emitcode ("mov", "b,a");
8811 emitcode ("movx", "a,@%s", rname);
8816 emitcode ("mov", "b,a");
8817 emitcode ("movx", "a,@dptr");
8822 emitcode ("mov", "b,a");
8823 emitcode ("clr", "a");
8824 emitcode ("movc", "a,@a+dptr");
8830 emitcode ("push", "b");
8831 emitcode ("push", "acc");
8833 emitcode ("lcall", "__gptrget");
8835 emitcode ("pop", "b");
8840 /*-----------------------------------------------------------------*/
8841 /* emitPtrByteSet - emits code to set a byte from src through a */
8842 /* pointer register (R0, R1, or DPTR). */
8843 /*-----------------------------------------------------------------*/
8845 emitPtrByteSet (char *rname, int p_type, char *src)
8854 emitcode ("mov", "@%s,a", rname);
8857 emitcode ("mov", "@%s,%s", rname, src);
8862 emitcode ("movx", "@%s,a", rname);
8867 emitcode ("movx", "@dptr,a");
8872 emitcode ("lcall", "__gptrput");
8877 /*-----------------------------------------------------------------*/
8878 /* genUnpackBits - generates code for unpacking bits */
8879 /*-----------------------------------------------------------------*/
8881 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
8883 int offset = 0; /* result byte offset */
8884 int rsize; /* result size */
8885 int rlen = 0; /* remaining bitfield length */
8886 sym_link *etype; /* bitfield type information */
8887 int blen; /* bitfield length */
8888 int bstr; /* bitfield starting bit within byte */
8891 D(emitcode ("; genUnpackBits",""));
8893 etype = getSpec (operandType (result));
8894 rsize = getSize (operandType (result));
8895 blen = SPEC_BLEN (etype);
8896 bstr = SPEC_BSTR (etype);
8898 if (ifx && blen <= 8)
8900 emitPtrByteGet (rname, ptype, FALSE);
8903 SNPRINTF (buffer, sizeof(buffer),
8905 genIfxJump (ifx, buffer, NULL, NULL, NULL);
8910 emitcode ("anl", "a,#0x%02x",
8911 (((unsigned char) -1) >> (8 - blen)) << bstr);
8912 genIfxJump (ifx, "a", NULL, NULL, NULL);
8918 /* If the bitfield length is less than a byte */
8921 emitPtrByteGet (rname, ptype, FALSE);
8923 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
8924 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8928 /* Bit field did not fit in a byte. Copy all
8929 but the partial byte at the end. */
8930 for (rlen=blen;rlen>=8;rlen-=8)
8932 emitPtrByteGet (rname, ptype, FALSE);
8933 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8935 emitcode ("inc", "%s", rname);
8938 /* Handle the partial byte at the end */
8941 emitPtrByteGet (rname, ptype, FALSE);
8942 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
8943 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8951 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
8956 /*-----------------------------------------------------------------*/
8957 /* genDataPointerGet - generates code when ptr offset is known */
8958 /*-----------------------------------------------------------------*/
8960 genDataPointerGet (operand * left,
8966 int size, offset = 0;
8968 D(emitcode ("; genDataPointerGet",""));
8970 aopOp (result, ic, TRUE);
8972 /* get the string representation of the name */
8973 l = aopGet (left, 0, FALSE, TRUE);
8974 size = AOP_SIZE (result);
8978 sprintf (buffer, "(%s + %d)", l + 1, offset);
8980 sprintf (buffer, "%s", l + 1);
8981 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
8984 freeAsmop (left, NULL, ic, TRUE);
8985 freeAsmop (result, NULL, ic, TRUE);
8988 /*-----------------------------------------------------------------*/
8989 /* genNearPointerGet - emitcode for near pointer fetch */
8990 /*-----------------------------------------------------------------*/
8992 genNearPointerGet (operand * left,
9001 sym_link *rtype, *retype;
9002 sym_link *ltype = operandType (left);
9005 D(emitcode ("; genNearPointerGet",""));
9007 rtype = operandType (result);
9008 retype = getSpec (rtype);
9010 aopOp (left, ic, FALSE);
9012 /* if left is rematerialisable and
9013 result is not bitfield variable type and
9014 the left is pointer to data space i.e
9015 lower 128 bytes of space */
9016 if (AOP_TYPE (left) == AOP_IMMD &&
9017 !IS_BITFIELD (retype) &&
9018 DCL_TYPE (ltype) == POINTER)
9020 genDataPointerGet (left, result, ic);
9024 /* if the value is already in a pointer register
9025 then don't need anything more */
9026 if (!AOP_INPREG (AOP (left)))
9028 if (IS_AOP_PREG (left))
9030 // Aha, it is a pointer, just in disguise.
9031 rname = aopGet (left, 0, FALSE, FALSE);
9034 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9035 __FILE__, __LINE__);
9040 emitcode ("mov", "a%s,%s", rname + 1, rname);
9041 rname++; // skip the '@'.
9046 /* otherwise get a free pointer register */
9048 preg = getFreePtr (ic, &aop, FALSE);
9049 emitcode ("mov", "%s,%s",
9051 aopGet (left, 0, FALSE, TRUE));
9056 rname = aopGet (left, 0, FALSE, FALSE);
9058 //aopOp (result, ic, FALSE);
9059 aopOp (result, ic, result?TRUE:FALSE);
9061 /* if bitfield then unpack the bits */
9062 if (IS_BITFIELD (retype))
9063 genUnpackBits (result, rname, POINTER, ifx);
9066 /* we have can just get the values */
9067 int size = AOP_SIZE (result);
9072 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9075 emitcode ("mov", "a,@%s", rname);
9077 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9081 sprintf (buffer, "@%s", rname);
9082 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9086 emitcode ("inc", "%s", rname);
9090 /* now some housekeeping stuff */
9091 if (aop) /* we had to allocate for this iCode */
9093 if (pi) { /* post increment present */
9094 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9096 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9100 /* we did not allocate which means left
9101 already in a pointer register, then
9102 if size > 0 && this could be used again
9103 we have to point it back to where it
9105 if ((AOP_SIZE (result) > 1 &&
9106 !OP_SYMBOL (left)->remat &&
9107 (OP_SYMBOL (left)->liveTo > ic->seq ||
9111 int size = AOP_SIZE (result) - 1;
9113 emitcode ("dec", "%s", rname);
9117 if (ifx && !ifx->generated)
9119 genIfxJump (ifx, "a", left, NULL, result);
9123 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9124 freeAsmop (left, NULL, ic, TRUE);
9125 if (pi) pi->generated = 1;
9128 /*-----------------------------------------------------------------*/
9129 /* genPagedPointerGet - emitcode for paged pointer fetch */
9130 /*-----------------------------------------------------------------*/
9132 genPagedPointerGet (operand * left,
9141 sym_link *rtype, *retype;
9143 D(emitcode ("; genPagedPointerGet",""));
9145 rtype = operandType (result);
9146 retype = getSpec (rtype);
9148 aopOp (left, ic, FALSE);
9150 /* if the value is already in a pointer register
9151 then don't need anything more */
9152 if (!AOP_INPREG (AOP (left)))
9154 /* otherwise get a free pointer register */
9156 preg = getFreePtr (ic, &aop, FALSE);
9157 emitcode ("mov", "%s,%s",
9159 aopGet (left, 0, FALSE, TRUE));
9163 rname = aopGet (left, 0, FALSE, FALSE);
9165 aopOp (result, ic, FALSE);
9167 /* if bitfield then unpack the bits */
9168 if (IS_BITFIELD (retype))
9169 genUnpackBits (result, rname, PPOINTER, ifx);
9172 /* we have can just get the values */
9173 int size = AOP_SIZE (result);
9179 emitcode ("movx", "a,@%s", rname);
9181 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9186 emitcode ("inc", "%s", rname);
9190 /* now some housekeeping stuff */
9191 if (aop) /* we had to allocate for this iCode */
9193 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9194 freeAsmop (NULL, aop, ic, TRUE);
9198 /* we did not allocate which means left
9199 already in a pointer register, then
9200 if size > 0 && this could be used again
9201 we have to point it back to where it
9203 if ((AOP_SIZE (result) > 1 &&
9204 !OP_SYMBOL (left)->remat &&
9205 (OP_SYMBOL (left)->liveTo > ic->seq ||
9209 int size = AOP_SIZE (result) - 1;
9211 emitcode ("dec", "%s", rname);
9215 if (ifx && !ifx->generated)
9217 genIfxJump (ifx, "a", left, NULL, result);
9221 freeAsmop (left, NULL, ic, TRUE);
9222 freeAsmop (result, NULL, ic, TRUE);
9223 if (pi) pi->generated = 1;
9227 /*--------------------------------------------------------------------*/
9228 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9229 /*--------------------------------------------------------------------*/
9231 loadDptrFromOperand (operand *op, bool loadBToo)
9233 if (AOP_TYPE (op) != AOP_STR)
9235 /* if this is rematerializable */
9236 if (AOP_TYPE (op) == AOP_IMMD)
9238 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9241 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9242 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9245 wassertl(FALSE, "need pointerCode");
9246 emitcode ("", "; mov b,???");
9247 /* genPointerGet and genPointerSet originally did different
9248 ** things for this case. Both seem wrong.
9249 ** from genPointerGet:
9250 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9251 ** from genPointerSet:
9252 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9257 else if (AOP_TYPE (op) == AOP_DPTR)
9261 MOVA (aopGet (op, 0, FALSE, FALSE));
9262 emitcode ("push", "acc");
9263 MOVA (aopGet (op, 1, FALSE, FALSE));
9264 emitcode ("push", "acc");
9265 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9266 emitcode ("pop", "dph");
9267 emitcode ("pop", "dpl");
9271 MOVA (aopGet (op, 0, FALSE, FALSE));
9272 emitcode ("push", "acc");
9273 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9274 emitcode ("pop", "dpl");
9278 { /* we need to get it byte by byte */
9279 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9280 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9282 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9287 /*-----------------------------------------------------------------*/
9288 /* genFarPointerGet - gget value from far space */
9289 /*-----------------------------------------------------------------*/
9291 genFarPointerGet (operand * left,
9292 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9295 sym_link *retype = getSpec (operandType (result));
9297 D(emitcode ("; genFarPointerGet",""));
9299 aopOp (left, ic, FALSE);
9300 loadDptrFromOperand (left, FALSE);
9302 /* so dptr now contains the address */
9303 aopOp (result, ic, FALSE);
9305 /* if bit then unpack */
9306 if (IS_BITFIELD (retype))
9307 genUnpackBits (result, "dptr", FPOINTER, ifx);
9310 size = AOP_SIZE (result);
9315 emitcode ("movx", "a,@dptr");
9317 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9319 emitcode ("inc", "dptr");
9323 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9325 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9326 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9330 if (ifx && !ifx->generated)
9332 genIfxJump (ifx, "a", left, NULL, result);
9335 freeAsmop (left, NULL, ic, TRUE);
9336 freeAsmop (result, NULL, ic, TRUE);
9339 /*-----------------------------------------------------------------*/
9340 /* genCodePointerGet - gget value from code space */
9341 /*-----------------------------------------------------------------*/
9343 genCodePointerGet (operand * left,
9344 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9347 sym_link *retype = getSpec (operandType (result));
9349 D(emitcode ("; genCodePointerGet",""));
9351 aopOp (left, ic, FALSE);
9352 loadDptrFromOperand (left, FALSE);
9354 /* so dptr now contains the address */
9355 aopOp (result, ic, FALSE);
9357 /* if bit then unpack */
9358 if (IS_BITFIELD (retype))
9359 genUnpackBits (result, "dptr", CPOINTER, ifx);
9362 size = AOP_SIZE (result);
9369 emitcode ("clr", "a");
9370 emitcode ("movc", "a,@a+dptr");
9372 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9373 emitcode ("inc", "dptr");
9377 emitcode ("mov", "a,#0x%02x", offset);
9378 emitcode ("movc", "a,@a+dptr");
9380 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9385 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9387 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9388 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9392 if (ifx && !ifx->generated)
9394 genIfxJump (ifx, "a", left, NULL, result);
9397 freeAsmop (left, NULL, ic, TRUE);
9398 freeAsmop (result, NULL, ic, TRUE);
9401 /*-----------------------------------------------------------------*/
9402 /* genGenPointerGet - gget value from generic pointer space */
9403 /*-----------------------------------------------------------------*/
9405 genGenPointerGet (operand * left,
9406 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9409 sym_link *retype = getSpec (operandType (result));
9411 D(emitcode ("; genGenPointerGet",""));
9413 aopOp (left, ic, FALSE);
9414 loadDptrFromOperand (left, TRUE);
9416 /* so dptr know contains the address */
9417 aopOp (result, ic, FALSE);
9419 /* if bit then unpack */
9420 if (IS_BITFIELD (retype))
9421 genUnpackBits (result, "dptr", GPOINTER, ifx);
9424 size = AOP_SIZE (result);
9429 emitcode ("lcall", "__gptrget");
9431 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9433 emitcode ("inc", "dptr");
9437 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9439 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9440 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9444 if (ifx && !ifx->generated)
9446 genIfxJump (ifx, "a", left, NULL, result);
9450 freeAsmop (left, NULL, ic, TRUE);
9451 freeAsmop (result, NULL, ic, TRUE);
9454 /*-----------------------------------------------------------------*/
9455 /* genPointerGet - generate code for pointer get */
9456 /*-----------------------------------------------------------------*/
9458 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9460 operand *left, *result;
9461 sym_link *type, *etype;
9464 D(emitcode ("; genPointerGet",""));
9466 left = IC_LEFT (ic);
9467 result = IC_RESULT (ic);
9469 if (getSize (operandType (result))>1)
9472 /* depending on the type of pointer we need to
9473 move it to the correct pointer register */
9474 type = operandType (left);
9475 etype = getSpec (type);
9476 /* if left is of type of pointer then it is simple */
9477 if (IS_PTR (type) && !IS_FUNC (type->next))
9478 p_type = DCL_TYPE (type);
9481 /* we have to go by the storage class */
9482 p_type = PTR_TYPE (SPEC_OCLS (etype));
9485 /* special case when cast remat */
9486 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9487 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9488 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9489 type = operandType (left);
9490 p_type = DCL_TYPE (type);
9492 /* now that we have the pointer type we assign
9493 the pointer values */
9499 genNearPointerGet (left, result, ic, pi, ifx);
9503 genPagedPointerGet (left, result, ic, pi, ifx);
9507 genFarPointerGet (left, result, ic, pi, ifx);
9511 genCodePointerGet (left, result, ic, pi, ifx);
9515 genGenPointerGet (left, result, ic, pi, ifx);
9523 /*-----------------------------------------------------------------*/
9524 /* genPackBits - generates code for packed bit storage */
9525 /*-----------------------------------------------------------------*/
9527 genPackBits (sym_link * etype,
9529 char *rname, int p_type)
9531 int offset = 0; /* source byte offset */
9532 int rlen = 0; /* remaining bitfield length */
9533 int blen; /* bitfield length */
9534 int bstr; /* bitfield starting bit within byte */
9535 int litval; /* source literal value (if AOP_LIT) */
9536 unsigned char mask; /* bitmask within current byte */
9538 D(emitcode ("; genPackBits",""));
9540 blen = SPEC_BLEN (etype);
9541 bstr = SPEC_BSTR (etype);
9543 /* If the bitfield length is less than a byte */
9546 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9547 (unsigned char) (0xFF >> (8 - bstr)));
9549 if (AOP_TYPE (right) == AOP_LIT)
9551 /* Case with a bitfield length <8 and literal source
9553 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9555 litval &= (~mask) & 0xff;
9556 emitPtrByteGet (rname, p_type, FALSE);
9557 if ((mask|litval)!=0xff)
9558 emitcode ("anl","a,#0x%02x", mask);
9560 emitcode ("orl","a,#0x%02x", litval);
9564 if ((blen==1) && (p_type!=GPOINTER))
9566 /* Case with a bitfield length == 1 and no generic pointer
9568 if (AOP_TYPE (right) == AOP_CRY)
9569 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9572 MOVA (aopGet (right, 0, FALSE, FALSE));
9573 emitcode ("rrc","a");
9575 emitPtrByteGet (rname, p_type, FALSE);
9576 emitcode ("mov","acc.%d,c",bstr);
9581 /* Case with a bitfield length < 8 and arbitrary source
9583 MOVA (aopGet (right, 0, FALSE, FALSE));
9584 /* shift and mask source value */
9586 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9589 /* transfer A to B and get next byte */
9590 emitPtrByteGet (rname, p_type, TRUE);
9592 emitcode ("anl", "a,#0x%02x", mask);
9593 emitcode ("orl", "a,b");
9594 if (p_type == GPOINTER)
9595 emitcode ("pop", "b");
9601 emitPtrByteSet (rname, p_type, "a");
9605 /* Bit length is greater than 7 bits. In this case, copy */
9606 /* all except the partial byte at the end */
9607 for (rlen=blen;rlen>=8;rlen-=8)
9609 emitPtrByteSet (rname, p_type,
9610 aopGet (right, offset++, FALSE, TRUE) );
9612 emitcode ("inc", "%s", rname);
9615 /* If there was a partial byte at the end */
9618 mask = (((unsigned char) -1 << rlen) & 0xff);
9620 if (AOP_TYPE (right) == AOP_LIT)
9622 /* Case with partial byte and literal source
9624 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9625 litval >>= (blen-rlen);
9626 litval &= (~mask) & 0xff;
9627 emitPtrByteGet (rname, p_type, FALSE);
9628 if ((mask|litval)!=0xff)
9629 emitcode ("anl","a,#0x%02x", mask);
9631 emitcode ("orl","a,#0x%02x", litval);
9636 /* Case with partial byte and arbitrary source
9638 MOVA (aopGet (right, offset++, FALSE, FALSE));
9639 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9642 /* transfer A to B and get next byte */
9643 emitPtrByteGet (rname, p_type, TRUE);
9645 emitcode ("anl", "a,#0x%02x", mask);
9646 emitcode ("orl", "a,b");
9647 if (p_type == GPOINTER)
9648 emitcode ("pop", "b");
9652 emitPtrByteSet (rname, p_type, "a");
9658 /*-----------------------------------------------------------------*/
9659 /* genDataPointerSet - remat pointer to data space */
9660 /*-----------------------------------------------------------------*/
9662 genDataPointerSet (operand * right,
9666 int size, offset = 0;
9667 char *l, buffer[256];
9669 D(emitcode ("; genDataPointerSet",""));
9671 aopOp (right, ic, FALSE);
9673 l = aopGet (result, 0, FALSE, TRUE);
9674 size = AOP_SIZE (right);
9678 sprintf (buffer, "(%s + %d)", l + 1, offset);
9680 sprintf (buffer, "%s", l + 1);
9681 emitcode ("mov", "%s,%s", buffer,
9682 aopGet (right, offset++, FALSE, FALSE));
9685 freeAsmop (right, NULL, ic, TRUE);
9686 freeAsmop (result, NULL, ic, TRUE);
9689 /*-----------------------------------------------------------------*/
9690 /* genNearPointerSet - emitcode for near pointer put */
9691 /*-----------------------------------------------------------------*/
9693 genNearPointerSet (operand * right,
9701 sym_link *retype, *letype;
9702 sym_link *ptype = operandType (result);
9704 D(emitcode ("; genNearPointerSet",""));
9706 retype = getSpec (operandType (right));
9707 letype = getSpec (ptype);
9708 aopOp (result, ic, FALSE);
9710 /* if the result is rematerializable &
9711 in data space & not a bit variable */
9712 if (AOP_TYPE (result) == AOP_IMMD &&
9713 DCL_TYPE (ptype) == POINTER &&
9714 !IS_BITVAR (retype) &&
9715 !IS_BITVAR (letype))
9717 genDataPointerSet (right, result, ic);
9721 /* if the value is already in a pointer register
9722 then don't need anything more */
9723 if (!AOP_INPREG (AOP (result)))
9726 //AOP_TYPE (result) == AOP_STK
9730 // Aha, it is a pointer, just in disguise.
9731 rname = aopGet (result, 0, FALSE, FALSE);
9734 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9735 __FILE__, __LINE__);
9740 emitcode ("mov", "a%s,%s", rname + 1, rname);
9741 rname++; // skip the '@'.
9746 /* otherwise get a free pointer register */
9748 preg = getFreePtr (ic, &aop, FALSE);
9749 emitcode ("mov", "%s,%s",
9751 aopGet (result, 0, FALSE, TRUE));
9757 rname = aopGet (result, 0, FALSE, FALSE);
9760 aopOp (right, ic, FALSE);
9762 /* if bitfield then unpack the bits */
9763 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9764 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9767 /* we have can just get the values */
9768 int size = AOP_SIZE (right);
9773 l = aopGet (right, offset, FALSE, TRUE);
9777 emitcode ("mov", "@%s,a", rname);
9780 emitcode ("mov", "@%s,%s", rname, l);
9782 emitcode ("inc", "%s", rname);
9787 /* now some housekeeping stuff */
9788 if (aop) /* we had to allocate for this iCode */
9791 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9792 freeAsmop (NULL, aop, ic, TRUE);
9796 /* we did not allocate which means left
9797 already in a pointer register, then
9798 if size > 0 && this could be used again
9799 we have to point it back to where it
9801 if ((AOP_SIZE (right) > 1 &&
9802 !OP_SYMBOL (result)->remat &&
9803 (OP_SYMBOL (result)->liveTo > ic->seq ||
9807 int size = AOP_SIZE (right) - 1;
9809 emitcode ("dec", "%s", rname);
9814 if (pi) pi->generated = 1;
9815 freeAsmop (result, NULL, ic, TRUE);
9816 freeAsmop (right, NULL, ic, TRUE);
9819 /*-----------------------------------------------------------------*/
9820 /* genPagedPointerSet - emitcode for Paged pointer put */
9821 /*-----------------------------------------------------------------*/
9823 genPagedPointerSet (operand * right,
9831 sym_link *retype, *letype;
9833 D(emitcode ("; genPagedPointerSet",""));
9835 retype = getSpec (operandType (right));
9836 letype = getSpec (operandType (result));
9838 aopOp (result, ic, FALSE);
9840 /* if the value is already in a pointer register
9841 then don't need anything more */
9842 if (!AOP_INPREG (AOP (result)))
9844 /* otherwise get a free pointer register */
9846 preg = getFreePtr (ic, &aop, FALSE);
9847 emitcode ("mov", "%s,%s",
9849 aopGet (result, 0, FALSE, TRUE));
9853 rname = aopGet (result, 0, FALSE, FALSE);
9855 aopOp (right, ic, FALSE);
9857 /* if bitfield then unpack the bits */
9858 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9859 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
9862 /* we have can just get the values */
9863 int size = AOP_SIZE (right);
9868 l = aopGet (right, offset, FALSE, TRUE);
9871 emitcode ("movx", "@%s,a", rname);
9874 emitcode ("inc", "%s", rname);
9880 /* now some housekeeping stuff */
9881 if (aop) /* we had to allocate for this iCode */
9884 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9885 freeAsmop (NULL, aop, ic, TRUE);
9889 /* we did not allocate which means left
9890 already in a pointer register, then
9891 if size > 0 && this could be used again
9892 we have to point it back to where it
9894 if (AOP_SIZE (right) > 1 &&
9895 !OP_SYMBOL (result)->remat &&
9896 (OP_SYMBOL (result)->liveTo > ic->seq ||
9899 int size = AOP_SIZE (right) - 1;
9901 emitcode ("dec", "%s", rname);
9906 if (pi) pi->generated = 1;
9907 freeAsmop (result, NULL, ic, TRUE);
9908 freeAsmop (right, NULL, ic, TRUE);
9913 /*-----------------------------------------------------------------*/
9914 /* genFarPointerSet - set value from far space */
9915 /*-----------------------------------------------------------------*/
9917 genFarPointerSet (operand * right,
9918 operand * result, iCode * ic, iCode * pi)
9921 sym_link *retype = getSpec (operandType (right));
9922 sym_link *letype = getSpec (operandType (result));
9924 D(emitcode ("; genFarPointerSet",""));
9926 aopOp (result, ic, FALSE);
9927 loadDptrFromOperand (result, FALSE);
9929 /* so dptr know contains the address */
9930 aopOp (right, ic, FALSE);
9932 /* if bit then unpack */
9933 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9934 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
9937 size = AOP_SIZE (right);
9942 char *l = aopGet (right, offset++, FALSE, FALSE);
9944 emitcode ("movx", "@dptr,a");
9946 emitcode ("inc", "dptr");
9949 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9950 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9951 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
9954 freeAsmop (result, NULL, ic, TRUE);
9955 freeAsmop (right, NULL, ic, TRUE);
9958 /*-----------------------------------------------------------------*/
9959 /* genGenPointerSet - set value from generic pointer space */
9960 /*-----------------------------------------------------------------*/
9962 genGenPointerSet (operand * right,
9963 operand * result, iCode * ic, iCode * pi)
9966 sym_link *retype = getSpec (operandType (right));
9967 sym_link *letype = getSpec (operandType (result));
9969 D(emitcode ("; genGenPointerSet",""));
9971 aopOp (result, ic, FALSE);
9972 loadDptrFromOperand (result, TRUE);
9974 /* so dptr know contains the address */
9975 aopOp (right, ic, FALSE);
9977 /* if bit then unpack */
9978 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9979 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
9982 size = AOP_SIZE (right);
9987 char *l = aopGet (right, offset++, FALSE, FALSE);
9989 emitcode ("lcall", "__gptrput");
9991 emitcode ("inc", "dptr");
9995 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
9996 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
9997 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10000 freeAsmop (result, NULL, ic, TRUE);
10001 freeAsmop (right, NULL, ic, TRUE);
10004 /*-----------------------------------------------------------------*/
10005 /* genPointerSet - stores the value into a pointer location */
10006 /*-----------------------------------------------------------------*/
10008 genPointerSet (iCode * ic, iCode *pi)
10010 operand *right, *result;
10011 sym_link *type, *etype;
10014 D(emitcode ("; genPointerSet",""));
10016 right = IC_RIGHT (ic);
10017 result = IC_RESULT (ic);
10019 /* depending on the type of pointer we need to
10020 move it to the correct pointer register */
10021 type = operandType (result);
10022 etype = getSpec (type);
10023 /* if left is of type of pointer then it is simple */
10024 if (IS_PTR (type) && !IS_FUNC (type->next))
10026 p_type = DCL_TYPE (type);
10030 /* we have to go by the storage class */
10031 p_type = PTR_TYPE (SPEC_OCLS (etype));
10034 /* special case when cast remat */
10035 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10036 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10037 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10038 type = operandType (result);
10039 p_type = DCL_TYPE (type);
10041 /* now that we have the pointer type we assign
10042 the pointer values */
10048 genNearPointerSet (right, result, ic, pi);
10052 genPagedPointerSet (right, result, ic, pi);
10056 genFarPointerSet (right, result, ic, pi);
10060 genGenPointerSet (right, result, ic, pi);
10064 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10065 "genPointerSet: illegal pointer type");
10070 /*-----------------------------------------------------------------*/
10071 /* genIfx - generate code for Ifx statement */
10072 /*-----------------------------------------------------------------*/
10074 genIfx (iCode * ic, iCode * popIc)
10076 operand *cond = IC_COND (ic);
10080 D(emitcode ("; genIfx",""));
10082 aopOp (cond, ic, FALSE);
10084 /* get the value into acc */
10085 if (AOP_TYPE (cond) != AOP_CRY)
10090 if (AOP(cond)->aopu.aop_dir)
10091 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10093 /* the result is now in the accumulator or a directly addressable bit */
10094 freeAsmop (cond, NULL, ic, TRUE);
10096 /* if there was something to be popped then do it */
10100 /* if the condition is a bit variable */
10102 genIfxJump(ic, dup, NULL, NULL, NULL);
10103 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10104 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10105 else if (isbit && !IS_ITEMP (cond))
10106 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10108 genIfxJump (ic, "a", NULL, NULL, NULL);
10113 /*-----------------------------------------------------------------*/
10114 /* genAddrOf - generates code for address of */
10115 /*-----------------------------------------------------------------*/
10117 genAddrOf (iCode * ic)
10119 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10122 D(emitcode ("; genAddrOf",""));
10124 aopOp (IC_RESULT (ic), ic, FALSE);
10126 /* if the operand is on the stack then we
10127 need to get the stack offset of this
10131 /* if it has an offset then we need to compute
10135 emitcode ("mov", "a,%s", SYM_BP (sym));
10136 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10137 ((char) (sym->stack - _G.nRegsSaved)) :
10138 ((char) sym->stack)) & 0xff);
10139 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10143 /* we can just move _bp */
10144 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10146 /* fill the result with zero */
10147 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10152 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10158 /* object not on stack then we need the name */
10159 size = AOP_SIZE (IC_RESULT (ic));
10164 char s[SDCC_NAME_MAX];
10166 sprintf (s, "#(%s >> %d)",
10170 sprintf (s, "#%s", sym->rname);
10171 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10175 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10179 /*-----------------------------------------------------------------*/
10180 /* genFarFarAssign - assignment when both are in far space */
10181 /*-----------------------------------------------------------------*/
10183 genFarFarAssign (operand * result, operand * right, iCode * ic)
10185 int size = AOP_SIZE (right);
10189 D(emitcode ("; genFarFarAssign",""));
10191 /* first push the right side on to the stack */
10194 l = aopGet (right, offset++, FALSE, FALSE);
10196 emitcode ("push", "acc");
10199 freeAsmop (right, NULL, ic, FALSE);
10200 /* now assign DPTR to result */
10201 aopOp (result, ic, FALSE);
10202 size = AOP_SIZE (result);
10205 emitcode ("pop", "acc");
10206 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10208 freeAsmop (result, NULL, ic, FALSE);
10212 /*-----------------------------------------------------------------*/
10213 /* genAssign - generate code for assignment */
10214 /*-----------------------------------------------------------------*/
10216 genAssign (iCode * ic)
10218 operand *result, *right;
10220 unsigned long lit = 0L;
10222 D(emitcode("; genAssign",""));
10224 result = IC_RESULT (ic);
10225 right = IC_RIGHT (ic);
10227 /* if they are the same */
10228 if (operandsEqu (result, right) &&
10229 !isOperandVolatile (result, FALSE) &&
10230 !isOperandVolatile (right, FALSE))
10233 aopOp (right, ic, FALSE);
10235 /* special case both in far space */
10236 if (AOP_TYPE (right) == AOP_DPTR &&
10237 IS_TRUE_SYMOP (result) &&
10238 isOperandInFarSpace (result))
10241 genFarFarAssign (result, right, ic);
10245 aopOp (result, ic, TRUE);
10247 /* if they are the same registers */
10248 if (sameRegs (AOP (right), AOP (result)) &&
10249 !isOperandVolatile (result, FALSE) &&
10250 !isOperandVolatile (right, FALSE))
10253 /* if the result is a bit */
10254 if (AOP_TYPE (result) == AOP_CRY)
10257 /* if the right size is a literal then
10258 we know what the value is */
10259 if (AOP_TYPE (right) == AOP_LIT)
10261 if (((int) operandLitValue (right)))
10262 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10264 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10268 /* the right is also a bit variable */
10269 if (AOP_TYPE (right) == AOP_CRY)
10271 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10272 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10276 /* we need to or */
10278 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10282 /* bit variables done */
10284 size = AOP_SIZE (result);
10286 if (AOP_TYPE (right) == AOP_LIT)
10287 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10289 (AOP_TYPE (result) != AOP_REG) &&
10290 (AOP_TYPE (right) == AOP_LIT) &&
10291 !IS_FLOAT (operandType (right)) &&
10294 while ((size) && (lit))
10297 aopGet (right, offset, FALSE, FALSE),
10299 isOperandVolatile (result, FALSE));
10304 emitcode ("clr", "a");
10307 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10316 aopGet (right, offset, FALSE, FALSE),
10318 isOperandVolatile (result, FALSE));
10324 freeAsmop (right, NULL, ic, TRUE);
10325 freeAsmop (result, NULL, ic, TRUE);
10328 /*-----------------------------------------------------------------*/
10329 /* genJumpTab - generates code for jump table */
10330 /*-----------------------------------------------------------------*/
10332 genJumpTab (iCode * ic)
10334 symbol *jtab,*jtablo,*jtabhi;
10336 unsigned int count;
10338 D(emitcode ("; genJumpTab",""));
10340 count = elementsInSet( IC_JTLABELS (ic) );
10344 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10345 if the switch argument is in a register.
10346 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10347 /* (MB) What if peephole converts ljmp to sjmp or ret ???
10348 How will multiply by three be updated ???*/
10349 aopOp (IC_JTCOND (ic), ic, FALSE);
10350 /* get the condition into accumulator */
10351 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10353 /* multiply by three */
10354 emitcode ("add", "a,acc");
10355 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10356 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10358 jtab = newiTempLabel (NULL);
10359 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10360 emitcode ("jmp", "@a+dptr");
10361 emitcode ("", "%05d$:", jtab->key + 100);
10362 /* now generate the jump labels */
10363 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10364 jtab = setNextItem (IC_JTLABELS (ic)))
10365 emitcode ("ljmp", "%05d$", jtab->key + 100);
10369 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10370 if the switch argument is in a register.
10371 For n>6 this algorithm may be more compact */
10372 jtablo = newiTempLabel (NULL);
10373 jtabhi = newiTempLabel (NULL);
10375 /* get the condition into accumulator.
10376 Using b as temporary storage, if register push/pop is needed */
10377 aopOp (IC_JTCOND (ic), ic, FALSE);
10378 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10379 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10380 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10382 // (MB) what if B is in use???
10383 wassertl(!BINUSE, "B was in use");
10384 emitcode ("mov", "b,%s", l);
10387 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10391 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10392 emitcode ("movc", "a,@a+pc");
10393 emitcode ("push", "acc");
10396 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10397 emitcode ("movc", "a,@a+pc");
10398 emitcode ("push", "acc");
10402 /* this scales up to n<=255, but needs two more bytes
10403 and changes dptr */
10404 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10405 emitcode ("movc", "a,@a+dptr");
10406 emitcode ("push", "acc");
10409 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10410 emitcode ("movc", "a,@a+dptr");
10411 emitcode ("push", "acc");
10414 emitcode ("ret", "");
10416 /* now generate jump table, LSB */
10417 emitcode ("", "%05d$:", jtablo->key + 100);
10418 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10419 jtab = setNextItem (IC_JTLABELS (ic)))
10420 emitcode (".db", "%05d$", jtab->key + 100);
10422 /* now generate jump table, MSB */
10423 emitcode ("", "%05d$:", jtabhi->key + 100);
10424 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10425 jtab = setNextItem (IC_JTLABELS (ic)))
10426 emitcode (".db", "%05d$>>8", jtab->key + 100);
10430 /*-----------------------------------------------------------------*/
10431 /* genCast - gen code for casting */
10432 /*-----------------------------------------------------------------*/
10434 genCast (iCode * ic)
10436 operand *result = IC_RESULT (ic);
10437 sym_link *ctype = operandType (IC_LEFT (ic));
10438 sym_link *rtype = operandType (IC_RIGHT (ic));
10439 operand *right = IC_RIGHT (ic);
10442 D(emitcode("; genCast",""));
10444 /* if they are equivalent then do nothing */
10445 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10448 aopOp (right, ic, FALSE);
10449 aopOp (result, ic, FALSE);
10451 /* if the result is a bit (and not a bitfield) */
10452 // if (AOP_TYPE (result) == AOP_CRY)
10453 if (IS_BITVAR (OP_SYMBOL (result)->type)
10454 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10456 /* if the right size is a literal then
10457 we know what the value is */
10458 if (AOP_TYPE (right) == AOP_LIT)
10460 if (((int) operandLitValue (right)))
10461 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10463 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10468 /* the right is also a bit variable */
10469 if (AOP_TYPE (right) == AOP_CRY)
10471 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10472 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10476 /* we need to or */
10478 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10483 /* if they are the same size : or less */
10484 if (AOP_SIZE (result) <= AOP_SIZE (right))
10487 /* if they are in the same place */
10488 if (sameRegs (AOP (right), AOP (result)))
10491 /* if they in different places then copy */
10492 size = AOP_SIZE (result);
10497 aopGet (right, offset, FALSE, FALSE),
10499 isOperandVolatile (result, FALSE));
10506 /* if the result is of type pointer */
10507 if (IS_PTR (ctype))
10511 sym_link *type = operandType (right);
10512 sym_link *etype = getSpec (type);
10514 /* pointer to generic pointer */
10515 if (IS_GENPTR (ctype))
10518 p_type = DCL_TYPE (type);
10521 if (SPEC_SCLS(etype)==S_REGISTER) {
10522 // let's assume it is a generic pointer
10525 /* we have to go by the storage class */
10526 p_type = PTR_TYPE (SPEC_OCLS (etype));
10530 /* the first two bytes are known */
10531 size = GPTRSIZE - 1;
10536 aopGet (right, offset, FALSE, FALSE),
10538 isOperandVolatile (result, FALSE));
10541 /* the last byte depending on type */
10543 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10548 // pointerTypeToGPByte will have bitched.
10552 sprintf(gpValStr, "#0x%x", gpVal);
10553 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10558 /* just copy the pointers */
10559 size = AOP_SIZE (result);
10564 aopGet (right, offset, FALSE, FALSE),
10566 isOperandVolatile (result, FALSE));
10572 /* so we now know that the size of destination is greater
10573 than the size of the source */
10574 /* we move to result for the size of source */
10575 size = AOP_SIZE (right);
10580 aopGet (right, offset, FALSE, FALSE),
10582 isOperandVolatile (result, FALSE));
10586 /* now depending on the sign of the source && destination */
10587 size = AOP_SIZE (result) - AOP_SIZE (right);
10588 /* if unsigned or not an integral type */
10589 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10592 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10596 /* we need to extend the sign :{ */
10597 char *l = aopGet (right, AOP_SIZE (right) - 1,
10600 emitcode ("rlc", "a");
10601 emitcode ("subb", "a,acc");
10603 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10606 /* we are done hurray !!!! */
10609 freeAsmop (right, NULL, ic, TRUE);
10610 freeAsmop (result, NULL, ic, TRUE);
10614 /*-----------------------------------------------------------------*/
10615 /* genDjnz - generate decrement & jump if not zero instrucion */
10616 /*-----------------------------------------------------------------*/
10618 genDjnz (iCode * ic, iCode * ifx)
10620 symbol *lbl, *lbl1;
10624 D(emitcode ("; genDjnz",""));
10626 /* if the if condition has a false label
10627 then we cannot save */
10628 if (IC_FALSE (ifx))
10631 /* if the minus is not of the form
10633 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10634 !IS_OP_LITERAL (IC_RIGHT (ic)))
10637 if (operandLitValue (IC_RIGHT (ic)) != 1)
10640 /* if the size of this greater than one then no
10642 if (getSize (operandType (IC_RESULT (ic))) > 1)
10645 /* otherwise we can save BIG */
10646 lbl = newiTempLabel (NULL);
10647 lbl1 = newiTempLabel (NULL);
10649 aopOp (IC_RESULT (ic), ic, FALSE);
10651 if (AOP_NEEDSACC(IC_RESULT(ic)))
10653 /* If the result is accessed indirectly via
10654 * the accumulator, we must explicitly write
10655 * it back after the decrement.
10657 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
10659 if (strcmp(rByte, "a"))
10661 /* Something is hopelessly wrong */
10662 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10663 __FILE__, __LINE__);
10664 /* We can just give up; the generated code will be inefficient,
10665 * but what the hey.
10667 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10670 emitcode ("dec", "%s", rByte);
10671 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10672 emitcode ("jnz", "%05d$", lbl->key + 100);
10674 else if (IS_AOP_PREG (IC_RESULT (ic)))
10676 emitcode ("dec", "%s",
10677 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10678 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10679 emitcode ("jnz", "%05d$", lbl->key + 100);
10683 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
10686 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10687 emitcode ("", "%05d$:", lbl->key + 100);
10688 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10689 emitcode ("", "%05d$:", lbl1->key + 100);
10691 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10692 ifx->generated = 1;
10696 /*-----------------------------------------------------------------*/
10697 /* genReceive - generate code for a receive iCode */
10698 /*-----------------------------------------------------------------*/
10700 genReceive (iCode * ic)
10702 int size = getSize (operandType (IC_RESULT (ic)));
10705 D(emitcode ("; genReceive",""));
10707 if (ic->argreg == 1)
10708 { /* first parameter */
10709 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10710 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10711 IS_TRUE_SYMOP (IC_RESULT (ic))))
10714 int receivingA = 0;
10717 for (offset = 0; offset<size; offset++)
10718 if (!strcmp (fReturn[offset], "a"))
10723 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10725 for (offset = size-1; offset>0; offset--)
10726 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10727 emitcode("mov","a,%s", fReturn[0]);
10729 aopOp (IC_RESULT (ic), ic, FALSE);
10731 aopPut (IC_RESULT (ic), "a", offset,
10732 isOperandVolatile (IC_RESULT (ic), FALSE));
10733 for (offset = 1; offset<size; offset++)
10734 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
10735 isOperandVolatile (IC_RESULT (ic), FALSE));
10741 if (getTempRegs(tempRegs, size, ic))
10743 for (offset = 0; offset<size; offset++)
10744 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10745 aopOp (IC_RESULT (ic), ic, FALSE);
10746 for (offset = 0; offset<size; offset++)
10747 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
10748 isOperandVolatile (IC_RESULT (ic), FALSE));
10753 offset = fReturnSizeMCS51 - size;
10756 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10757 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10760 aopOp (IC_RESULT (ic), ic, FALSE);
10761 size = AOP_SIZE (IC_RESULT (ic));
10765 emitcode ("pop", "acc");
10766 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10772 aopOp (IC_RESULT (ic), ic, FALSE);
10774 assignResultValue (IC_RESULT (ic), NULL);
10777 else if (ic->argreg > 12)
10778 { /* bit parameters */
10779 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
10781 aopOp (IC_RESULT (ic), ic, FALSE);
10782 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
10783 outBitC(IC_RESULT (ic));
10787 { /* other parameters */
10789 aopOp (IC_RESULT (ic), ic, FALSE);
10790 rb1off = ic->argreg;
10793 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10798 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10801 /*-----------------------------------------------------------------*/
10802 /* genDummyRead - generate code for dummy read of volatiles */
10803 /*-----------------------------------------------------------------*/
10805 genDummyRead (iCode * ic)
10810 D(emitcode("; genDummyRead",""));
10812 op = IC_RIGHT (ic);
10813 if (op && IS_SYMOP (op))
10815 aopOp (op, ic, FALSE);
10817 /* if the result is a bit */
10818 if (AOP_TYPE (op) == AOP_CRY)
10819 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10822 /* bit variables done */
10824 size = AOP_SIZE (op);
10828 MOVA (aopGet (op, offset, FALSE, FALSE));
10833 freeAsmop (op, NULL, ic, TRUE);
10837 if (op && IS_SYMOP (op))
10839 aopOp (op, ic, FALSE);
10841 /* if the result is a bit */
10842 if (AOP_TYPE (op) == AOP_CRY)
10843 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10846 /* bit variables done */
10848 size = AOP_SIZE (op);
10852 MOVA (aopGet (op, offset, FALSE, FALSE));
10857 freeAsmop (op, NULL, ic, TRUE);
10861 /*-----------------------------------------------------------------*/
10862 /* genCritical - generate code for start of a critical sequence */
10863 /*-----------------------------------------------------------------*/
10865 genCritical (iCode *ic)
10867 symbol *tlbl = newiTempLabel (NULL);
10869 D(emitcode("; genCritical",""));
10871 if (IC_RESULT (ic))
10873 aopOp (IC_RESULT (ic), ic, TRUE);
10874 aopPut (IC_RESULT (ic), one, 0, 0);
10875 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10876 aopPut (IC_RESULT (ic), zero, 0, 0);
10877 emitcode ("", "%05d$:", (tlbl->key + 100));
10878 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10882 emitcode ("setb", "c");
10883 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
10884 emitcode ("clr", "c");
10885 emitcode ("", "%05d$:", (tlbl->key + 100));
10886 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
10890 /*-----------------------------------------------------------------*/
10891 /* genEndCritical - generate code for end of a critical sequence */
10892 /*-----------------------------------------------------------------*/
10894 genEndCritical (iCode *ic)
10896 D(emitcode("; genEndCritical",""));
10900 aopOp (IC_RIGHT (ic), ic, FALSE);
10901 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
10903 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
10904 emitcode ("mov", "ea,c");
10908 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
10909 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
10910 emitcode ("rrc", "a");
10911 emitcode ("mov", "ea,c");
10913 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
10917 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
10918 emitcode ("mov", "ea,c");
10922 /*-----------------------------------------------------------------*/
10923 /* gen51Code - generate code for 8051 based controllers */
10924 /*-----------------------------------------------------------------*/
10926 gen51Code (iCode * lic)
10930 /* int cseq = 0; */
10932 _G.currentFunc = NULL;
10933 lineHead = lineCurr = NULL;
10935 /* print the allocation information */
10936 if (allocInfo && currFunc)
10937 printAllocInfo (currFunc, codeOutFile);
10938 /* if debug information required */
10939 if (options.debug && currFunc)
10941 debugFile->writeFunction (currFunc, lic);
10943 /* stack pointer name */
10944 if (options.useXstack)
10950 for (ic = lic; ic; ic = ic->next)
10952 _G.current_iCode = ic;
10954 if (ic->lineno && cln != ic->lineno)
10958 debugFile->writeCLine (ic);
10960 if (!options.noCcodeInAsm) {
10961 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
10962 printCLine(ic->filename, ic->lineno));
10967 if (ic->seqPoint && ic->seqPoint != cseq)
10969 emitcode ("", "; sequence point %d", ic->seqPoint);
10970 cseq = ic->seqPoint;
10973 if (options.iCodeInAsm) {
10974 char regsInUse[80];
10977 for (i=0; i<8; i++) {
10978 sprintf (®sInUse[i],
10979 "%c", ic->riu & (1<<i) ? i+'0' : '-');
10982 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
10984 /* if the result is marked as
10985 spilt and rematerializable or code for
10986 this has already been generated then
10988 if (resultRemat (ic) || ic->generated)
10991 /* depending on the operation */
11011 /* IPOP happens only when trying to restore a
11012 spilt live range, if there is an ifx statement
11013 following this pop then the if statement might
11014 be using some of the registers being popped which
11015 would destory the contents of the register so
11016 we need to check for this condition and handle it */
11018 ic->next->op == IFX &&
11019 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11020 genIfx (ic->next, ic);
11038 genEndFunction (ic);
11058 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11075 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11079 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11086 /* note these two are xlated by algebraic equivalence
11087 during parsing SDCC.y */
11088 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11089 "got '>=' or '<=' shouldn't have come here");
11093 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11105 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11109 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11113 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11137 genRightShift (ic);
11140 case GET_VALUE_AT_ADDRESS:
11142 hasInc (IC_LEFT (ic), ic,
11143 getSize (operandType (IC_RESULT (ic)))),
11144 ifxForOp (IC_RESULT (ic), ic) );
11148 if (POINTER_SET (ic))
11149 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11175 addSet (&_G.sendSet, ic);
11178 case DUMMY_READ_VOLATILE:
11187 genEndCritical (ic);
11199 _G.current_iCode = NULL;
11201 /* now we are ready to call the
11202 peep hole optimizer */
11203 if (!options.nopeep)
11204 peepHole (&lineHead);
11206 /* now do the actual printing */
11207 printLine (lineHead, codeOutFile);