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 emitcode ("setb", "%s", IC_RESULT (ic)->aop->aopu.aop_dir);
1810 tlbl=newiTempLabel(NULL);
1811 l = aopGet (IC_LEFT (ic), offset++, FALSE, FALSE);
1812 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_ACC && offset == 0) ||
1813 AOP_TYPE (IC_LEFT (ic)) == AOP_REG ||
1814 IS_AOP_PREG (IC_LEFT (ic)))
1816 emitcode ("cjne", "%s,#0xFF,%05d$", l, tlbl->key + 100);
1821 emitcode ("cjne", "a,#0xFF,%05d$", tlbl->key + 100);
1823 emitcode ("", "%05d$:", tlbl->key + 100);
1824 outBitC (IC_RESULT(ic));
1828 size = AOP_SIZE (IC_RESULT (ic));
1831 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1833 emitcode ("cpl", "a");
1834 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1839 /* release the aops */
1840 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1841 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1844 /*-----------------------------------------------------------------*/
1845 /* genUminusFloat - unary minus for floating points */
1846 /*-----------------------------------------------------------------*/
1848 genUminusFloat (operand * op, operand * result)
1850 int size, offset = 0;
1853 D(emitcode ("; genUminusFloat",""));
1855 /* for this we just copy and then flip the bit */
1857 size = AOP_SIZE (op) - 1;
1862 aopGet (op, offset, FALSE, FALSE),
1864 isOperandVolatile (result, FALSE));
1868 l = aopGet (op, offset, FALSE, FALSE);
1872 emitcode ("cpl", "acc.7");
1873 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
1876 /*-----------------------------------------------------------------*/
1877 /* genUminus - unary minus code generation */
1878 /*-----------------------------------------------------------------*/
1880 genUminus (iCode * ic)
1883 sym_link *optype, *rtype;
1886 D(emitcode ("; genUminus",""));
1889 aopOp (IC_LEFT (ic), ic, FALSE);
1890 aopOp (IC_RESULT (ic), ic, TRUE);
1892 /* if both in bit space then special
1894 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1895 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1898 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1899 emitcode ("cpl", "c");
1900 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1904 optype = operandType (IC_LEFT (ic));
1905 rtype = operandType (IC_RESULT (ic));
1907 /* if float then do float stuff */
1908 if (IS_FLOAT (optype))
1910 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1914 /* otherwise subtract from zero */
1915 size = AOP_SIZE (IC_LEFT (ic));
1920 char *l = aopGet (IC_LEFT (ic), offset, FALSE, FALSE);
1921 if (!strcmp (l, "a"))
1925 emitcode ("cpl", "a");
1926 emitcode ("addc", "a,#0");
1932 emitcode ("clr", "a");
1933 emitcode ("subb", "a,%s", l);
1935 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1938 /* if any remaining bytes in the result */
1939 /* we just need to propagate the sign */
1940 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1942 emitcode ("rlc", "a");
1943 emitcode ("subb", "a,acc");
1945 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
1949 /* release the aops */
1950 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1951 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1954 /*-----------------------------------------------------------------*/
1955 /* saveRegisters - will look for a call and save the registers */
1956 /*-----------------------------------------------------------------*/
1958 saveRegisters (iCode * lic)
1965 for (ic = lic; ic; ic = ic->next)
1966 if (ic->op == CALL || ic->op == PCALL)
1971 fprintf (stderr, "found parameter push with no function call\n");
1975 /* if the registers have been saved already or don't need to be then
1979 if (IS_SYMOP(IC_LEFT(ic)) &&
1980 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1981 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
1984 /* save the registers in use at this time but skip the
1985 ones for the result */
1986 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1987 mcs51_rUmaskForOp (IC_RESULT(ic)));
1990 if (options.useXstack)
1992 int count = bitVectnBitsOn (rsave);
1996 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
1997 if (reg->type == REG_BIT)
1999 emitcode ("mov", "a,%s", reg->base);
2003 emitcode ("mov", "a,%s", reg->name);
2005 emitcode ("mov", "r0,%s", spname);
2006 emitcode ("inc", "%s", spname);// allocate before use
2007 emitcode ("movx", "@r0,a");
2008 if (bitVectBitValue (rsave, R0_IDX))
2009 emitcode ("mov", "r0,a");
2011 else if (count != 0)
2013 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2014 int nBits = bitVectnBitsOn (rsavebits);
2018 count = count - nBits + 1;
2019 /* remove all but the first bits as they are pushed all at once */
2020 rsave = bitVectCplAnd (rsave, rsavebits);
2021 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2024 if (bitVectBitValue (rsave, R0_IDX))
2026 emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2028 emitcode ("mov", "r0,%s", spname);
2030 emitcode ("add", "a,#%d", count);
2031 emitcode ("mov", "%s,a", spname);
2032 for (i = 0; i < mcs51_nRegs; i++)
2034 if (bitVectBitValue (rsave, i))
2036 regs * reg = mcs51_regWithIdx (i);
2039 emitcode ("pop", "acc");
2040 emitcode ("push", "acc");
2042 else if (reg->type == REG_BIT)
2044 emitcode ("mov", "a,%s", reg->base);
2048 emitcode ("mov", "a,%s", reg->name);
2050 emitcode ("movx", "@r0,a");
2053 emitcode ("inc", "r0");
2057 if (bitVectBitValue (rsave, R0_IDX))
2059 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
2065 bool bits_pushed = FALSE;
2066 for (i = 0; i < mcs51_nRegs; i++)
2068 if (bitVectBitValue (rsave, i))
2070 bits_pushed = pushReg (i, bits_pushed);
2076 /*-----------------------------------------------------------------*/
2077 /* unsaveRegisters - pop the pushed registers */
2078 /*-----------------------------------------------------------------*/
2080 unsaveRegisters (iCode * ic)
2085 /* restore the registers in use at this time but skip the
2086 ones for the result */
2087 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2088 mcs51_rUmaskForOp (IC_RESULT(ic)));
2090 if (options.useXstack)
2092 int count = bitVectnBitsOn (rsave);
2096 regs * reg = mcs51_regWithIdx (bitVectFirstBit (rsave));
2097 emitcode ("mov", "r0,%s", spname);
2098 emitcode ("dec", "r0");
2099 emitcode ("movx", "a,@r0");
2100 if (reg->type == REG_BIT)
2102 emitcode ("mov", "%s,a", reg->base);
2106 emitcode ("mov", "%s,a", reg->name);
2108 emitcode ("dec", "%s", spname);
2110 else if (count != 0)
2112 bitVect *rsavebits = bitVectIntersect (bitVectCopy (mcs51_allBitregs ()), rsave);
2113 int nBits = bitVectnBitsOn (rsavebits);
2117 count = count - nBits + 1;
2118 /* remove all but the first bits as they are popped all at once */
2119 rsave = bitVectCplAnd (rsave, rsavebits);
2120 rsave = bitVectSetBit (rsave, bitVectFirstBit (rsavebits));
2123 emitcode ("mov", "r0,%s", spname);
2124 for (i = mcs51_nRegs; i >= 0; i--)
2126 if (bitVectBitValue (rsave, i))
2128 regs * reg = mcs51_regWithIdx (i);
2129 emitcode ("dec", "r0");
2130 emitcode ("movx", "a,@r0");
2133 emitcode ("push", "acc");
2135 else if (reg->type == REG_BIT)
2137 emitcode ("mov", "%s,a", reg->base);
2141 emitcode ("mov", "%s,a", reg->name);
2145 emitcode ("mov", "%s,r0", spname);
2146 if (bitVectBitValue (rsave, R0_IDX))
2148 emitcode ("pop", "ar0");
2154 bool bits_popped = FALSE;
2155 for (i = mcs51_nRegs; i >= 0; i--)
2157 if (bitVectBitValue (rsave, i))
2159 bits_popped = popReg (i, bits_popped);
2166 /*-----------------------------------------------------------------*/
2168 /*-----------------------------------------------------------------*/
2170 pushSide (operand * oper, int size)
2175 char *l = aopGet (oper, offset++, FALSE, TRUE);
2176 if (AOP_TYPE (oper) != AOP_REG &&
2177 AOP_TYPE (oper) != AOP_DIR &&
2181 emitcode ("push", "acc");
2185 emitcode ("push", "%s", l);
2190 /*-----------------------------------------------------------------*/
2191 /* assignResultValue - also indicates if acc is in use afterwards */
2192 /*-----------------------------------------------------------------*/
2194 assignResultValue (operand * oper, operand * func)
2197 int size = AOP_SIZE (oper);
2198 bool accuse = FALSE;
2200 if (func && IS_BIT (OP_SYM_ETYPE (func)))
2208 accuse |= aopPut (oper, fReturn[offset], offset, isOperandVolatile (oper, FALSE));
2215 /*-----------------------------------------------------------------*/
2216 /* genXpush - pushes onto the external stack */
2217 /*-----------------------------------------------------------------*/
2219 genXpush (iCode * ic)
2221 asmop *aop = newAsmop (0);
2223 int size, offset = 0;
2225 D(emitcode ("; genXpush",""));
2227 aopOp (IC_LEFT (ic), ic, FALSE);
2228 r = getFreePtr (ic, &aop, FALSE);
2230 size = AOP_SIZE (IC_LEFT (ic));
2234 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
2235 emitcode ("mov", "%s,%s", r->name, spname);
2236 emitcode ("inc", "%s", spname); // allocate space first
2237 emitcode ("movx", "@%s,a", r->name);
2241 // allocate space first
2242 emitcode ("mov", "%s,%s", r->name, spname);
2244 emitcode ("add", "a,#%d", size);
2245 emitcode ("mov", "%s,a", spname);
2249 MOVA (aopGet (IC_LEFT (ic), offset++, FALSE, FALSE));
2250 emitcode ("movx", "@%s,a", r->name);
2251 emitcode ("inc", "%s", r->name);
2255 freeAsmop (NULL, aop, ic, TRUE);
2256 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2259 /*-----------------------------------------------------------------*/
2260 /* genIpush - generate code for pushing this gets a little complex */
2261 /*-----------------------------------------------------------------*/
2263 genIpush (iCode * ic)
2265 int size, offset = 0;
2269 D(emitcode ("; genIpush",""));
2271 /* if this is not a parm push : ie. it is spill push
2272 and spill push is always done on the local stack */
2276 /* and the item is spilt then do nothing */
2277 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2280 aopOp (IC_LEFT (ic), ic, FALSE);
2281 size = AOP_SIZE (IC_LEFT (ic));
2282 /* push it on the stack */
2285 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2291 emitcode ("push", "%s", l);
2296 /* this is a parameter push: in this case we call
2297 the routine to find the call and save those
2298 registers that need to be saved */
2301 /* if use external stack then call the external
2302 stack pushing routine */
2303 if (options.useXstack)
2309 /* then do the push */
2310 aopOp (IC_LEFT (ic), ic, FALSE);
2312 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2313 size = AOP_SIZE (IC_LEFT (ic));
2317 l = aopGet (IC_LEFT (ic), offset++, FALSE, TRUE);
2318 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2319 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2322 if (strcmp (l, prev) || *l == '@')
2324 emitcode ("push", "acc");
2328 emitcode ("push", "%s", l);
2333 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2336 /*-----------------------------------------------------------------*/
2337 /* genIpop - recover the registers: can happen only for spilling */
2338 /*-----------------------------------------------------------------*/
2340 genIpop (iCode * ic)
2344 D(emitcode ("; genIpop",""));
2346 /* if the temp was not pushed then */
2347 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2350 aopOp (IC_LEFT (ic), ic, FALSE);
2351 size = AOP_SIZE (IC_LEFT (ic));
2352 offset = (size - 1);
2354 emitcode ("pop", "%s", aopGet (IC_LEFT (ic), offset--,
2357 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2360 /*-----------------------------------------------------------------*/
2361 /* saveRBank - saves an entire register bank on the stack */
2362 /*-----------------------------------------------------------------*/
2364 saveRBank (int bank, iCode * ic, bool pushPsw)
2367 int count = mcs51_nRegs + (pushPsw ? 1 : 0);
2371 if (options.useXstack)
2375 /* Assume r0 is available for use. */
2376 r = mcs51_regWithIdx (R0_IDX);;
2381 r = getFreePtr (ic, &aop, FALSE);
2383 // allocate space first
2384 emitcode ("mov", "%s,%s", r->name, spname);
2386 emitcode ("add", "a,#%d", count);
2387 emitcode ("mov", "%s,a", spname);
2390 for (i = 0; i < mcs51_nRegs; i++)
2392 if (options.useXstack)
2394 emitcode ("mov", "a,(%s+%d)",
2395 regs8051[i].base, 8 * bank + regs8051[i].offset);
2396 emitcode ("movx", "@%s,a", r->name);
2398 emitcode ("inc", "%s", r->name);
2401 emitcode ("push", "(%s+%d)",
2402 regs8051[i].base, 8 * bank + regs8051[i].offset);
2407 if (options.useXstack)
2409 emitcode ("mov", "a,psw");
2410 emitcode ("movx", "@%s,a", r->name);
2415 emitcode ("push", "psw");
2418 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
2423 freeAsmop (NULL, aop, ic, TRUE);
2432 /*-----------------------------------------------------------------*/
2433 /* unsaveRBank - restores the register bank from stack */
2434 /*-----------------------------------------------------------------*/
2436 unsaveRBank (int bank, iCode * ic, bool popPsw)
2442 if (options.useXstack)
2446 /* Assume r0 is available for use. */
2447 r = mcs51_regWithIdx (R0_IDX);;
2452 r = getFreePtr (ic, &aop, FALSE);
2454 emitcode ("mov", "%s,%s", r->name, spname);
2459 if (options.useXstack)
2461 emitcode ("dec", "%s", r->name);
2462 emitcode ("movx", "a,@%s", r->name);
2463 emitcode ("mov", "psw,a");
2467 emitcode ("pop", "psw");
2471 for (i = (mcs51_nRegs - 1); i >= 0; i--)
2473 if (options.useXstack)
2475 emitcode ("dec", "%s", r->name);
2476 emitcode ("movx", "a,@%s", r->name);
2477 emitcode ("mov", "(%s+%d),a",
2478 regs8051[i].base, 8 * bank + regs8051[i].offset);
2482 emitcode ("pop", "(%s+%d)",
2483 regs8051[i].base, 8 * bank + regs8051[i].offset);
2487 if (options.useXstack)
2489 emitcode ("mov", "%s,%s", spname, r->name);
2494 freeAsmop (NULL, aop, ic, TRUE);
2498 /*-----------------------------------------------------------------*/
2499 /* genSend - gen code for SEND */
2500 /*-----------------------------------------------------------------*/
2501 static void genSend(set *sendSet)
2506 /* first we do all bit parameters */
2507 for (sic = setFirstItem (sendSet); sic;
2508 sic = setNextItem (sendSet))
2510 aopOp (IC_LEFT (sic), sic, FALSE);
2512 if (sic->argreg > 12)
2514 int bit = sic->argreg-13;
2516 /* if left is a literal then
2517 we know what the value is */
2518 if (AOP_TYPE (IC_LEFT (sic)) == AOP_LIT)
2520 if (((int) operandLitValue (IC_LEFT (sic))))
2521 emitcode ("setb", "b[%d]", bit);
2523 emitcode ("clr", "b[%d]", bit);
2525 else if (AOP_TYPE (IC_LEFT (sic)) == AOP_CRY)
2527 char *l = AOP (IC_LEFT (sic))->aopu.aop_dir;
2528 if (strcmp (l, "c"))
2529 emitcode ("mov", "c,%s", l);
2530 emitcode ("mov", "b[%d],c", bit);
2535 toBoolean (IC_LEFT (sic));
2536 /* set C, if a >= 1 */
2537 emitcode ("add", "a,#0xff");
2538 emitcode ("mov", "b[%d],c", bit);
2543 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2548 saveRegisters (setFirstItem (sendSet));
2549 emitcode ("mov", "bits,b");
2552 /* then we do all other parameters */
2553 for (sic = setFirstItem (sendSet); sic;
2554 sic = setNextItem (sendSet))
2556 int size, offset = 0;
2557 aopOp (IC_LEFT (sic), sic, FALSE);
2558 size = AOP_SIZE (IC_LEFT (sic));
2560 if (sic->argreg == 1)
2564 char *l = aopGet (IC_LEFT (sic), offset, FALSE, FALSE);
2565 if (strcmp (l, fReturn[offset]))
2566 emitcode ("mov", "%s,%s", fReturn[offset], l);
2570 else if (sic->argreg <= 12)
2574 emitcode ("mov","%s,%s", rb1regs[sic->argreg+offset-5],
2575 aopGet (IC_LEFT (sic), offset,FALSE, FALSE));
2579 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2583 /*-----------------------------------------------------------------*/
2584 /* selectRegBank - emit code to select the register bank */
2585 /*-----------------------------------------------------------------*/
2587 selectRegBank (short bank, bool keepFlags)
2589 /* if f.e. result is in carry */
2592 emitcode ("anl", "psw,#0xE7");
2594 emitcode ("orl", "psw,#0x%02x", (bank << 3) & 0xff);
2598 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0xff);
2602 /*-----------------------------------------------------------------*/
2603 /* genCall - generates a call statement */
2604 /*-----------------------------------------------------------------*/
2606 genCall (iCode * ic)
2610 // bool restoreBank = FALSE;
2611 bool swapBanks = FALSE;
2612 bool accuse = FALSE;
2613 bool accPushed = FALSE;
2614 bool resultInF0 = FALSE;
2616 D(emitcode("; genCall",""));
2618 dtype = operandType (IC_LEFT (ic));
2619 etype = getSpec(dtype);
2620 /* if send set is not empty then assign */
2623 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2624 genSend(reverseSet(_G.sendSet));
2626 genSend(_G.sendSet);
2632 /* if we are calling a not _naked function that is not using
2633 the same register bank then we need to save the
2634 destination registers on the stack */
2635 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2636 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2637 !IFFUNC_ISISR (dtype))
2642 /* if caller saves & we have not saved then */
2648 emitcode ("mov", "psw,#0x%02x",
2649 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2653 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2655 if (IFFUNC_CALLEESAVES(dtype))
2657 werror (E_BANKED_WITH_CALLEESAVES);
2661 char *l = (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2662 OP_SYMBOL (IC_LEFT (ic))->rname :
2663 OP_SYMBOL (IC_LEFT (ic))->name);
2665 emitcode ("mov", "r0,#%s", l);
2666 emitcode ("mov", "r1,#(%s >> 8)", l);
2667 emitcode ("mov", "r2,#(%s >> 16)", l);
2668 emitcode ("lcall", "__sdcc_banked_call");
2673 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2674 OP_SYMBOL (IC_LEFT (ic))->rname :
2675 OP_SYMBOL (IC_LEFT (ic))->name));
2680 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2683 /* if we need assign a result value */
2684 if ((IS_ITEMP (IC_RESULT (ic)) &&
2685 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2686 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2687 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2688 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2689 IS_TRUE_SYMOP (IC_RESULT (ic)))
2693 aopOp (IC_RESULT (ic), ic, FALSE);
2696 accuse = assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2698 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2701 /* adjust the stack for parameters if required */
2705 if (ic->parmBytes > 3)
2709 emitcode ("push", "acc");
2712 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2713 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2715 emitcode ("mov", "F0,c");
2719 emitcode ("mov", "a,%s", spname);
2720 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2721 emitcode ("mov", "%s,a", spname);
2723 /* unsaveRegisters from xstack needs acc, but */
2724 /* unsaveRegisters from stack needs this popped */
2725 if (accPushed && !options.useXstack)
2727 emitcode ("pop", "acc");
2732 for (i = 0; i < ic->parmBytes; i++)
2733 emitcode ("dec", "%s", spname);
2736 /* if we had saved some registers then unsave them */
2737 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2739 if (accuse && !accPushed && options.useXstack)
2741 /* xstack needs acc, but doesn't touch normal stack */
2742 emitcode ("push", "acc");
2745 unsaveRegisters (ic);
2748 // /* if register bank was saved then pop them */
2750 // unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2752 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2755 emitcode ("mov", "c,F0");
2757 aopOp (IC_RESULT (ic), ic, FALSE);
2758 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2759 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2763 emitcode ("pop", "acc");
2766 /*-----------------------------------------------------------------*/
2767 /* -10l - generates a call by pointer statement */
2768 /*-----------------------------------------------------------------*/
2770 genPcall (iCode * ic)
2774 symbol *rlbl = newiTempLabel (NULL);
2775 // bool restoreBank=FALSE;
2776 bool swapBanks = FALSE;
2777 bool resultInF0 = FALSE;
2779 D(emitcode("; genPCall",""));
2781 dtype = operandType (IC_LEFT (ic))->next;
2782 etype = getSpec(dtype);
2783 /* if caller saves & we have not saved then */
2787 /* if we are calling a not _naked function that is not using
2788 the same register bank then we need to save the
2789 destination registers on the stack */
2790 if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
2791 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2792 !IFFUNC_ISISR (dtype))
2794 // saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2795 // restoreBank=TRUE;
2797 // need caution message to user here
2800 if (IS_LITERAL(etype))
2802 /* if send set is not empty then assign */
2805 genSend(reverseSet(_G.sendSet));
2811 emitcode ("mov", "psw,#0x%02x",
2812 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2815 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2817 if (IFFUNC_CALLEESAVES(dtype))
2819 werror (E_BANKED_WITH_CALLEESAVES);
2823 char *l = aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2);
2825 emitcode ("mov", "r0,#%s", l);
2826 emitcode ("mov", "r1,#(%s >> 8)", l);
2827 emitcode ("mov", "r2,#(%s >> 16)", l);
2828 emitcode ("lcall", "__sdcc_banked_call");
2833 emitcode ("lcall", "%s", aopLiteralLong (OP_VALUE (IC_LEFT (ic)), 0, 2));
2838 if (IFFUNC_ISBANKEDCALL (dtype) && !SPEC_STAT(getSpec(dtype)))
2840 if (IFFUNC_CALLEESAVES(dtype))
2842 werror (E_BANKED_WITH_CALLEESAVES);
2846 aopOp (IC_LEFT (ic), ic, FALSE);
2850 emitcode ("mov", "ar0,%s", aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2851 emitcode ("mov", "ar1,%s", aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2852 emitcode ("mov", "ar2,%s", aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2856 int reg = ((FUNC_REGBANK(dtype)) << 3) & 0xff;
2857 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 0, FALSE, FALSE));
2858 emitcode ("mov", "0x%02x,%s", reg++, aopGet(IC_LEFT (ic), 1, FALSE, FALSE));
2859 emitcode ("mov", "0x%02x,%s", reg, aopGet(IC_LEFT (ic), 2, FALSE, FALSE));
2862 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2864 /* if send set is not empty then assign */
2867 genSend(reverseSet(_G.sendSet));
2873 emitcode ("mov", "psw,#0x%02x",
2874 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2878 emitcode ("lcall", "__sdcc_banked_call");
2883 /* push the return address on to the stack */
2884 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2885 emitcode ("push", "acc");
2886 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2887 emitcode ("push", "acc");
2889 /* now push the calling address */
2890 aopOp (IC_LEFT (ic), ic, FALSE);
2892 pushSide (IC_LEFT (ic), FPTRSIZE);
2894 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2896 /* if send set is not empty the assign */
2899 genSend(reverseSet(_G.sendSet));
2905 emitcode ("mov", "psw,#0x%02x",
2906 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2910 emitcode ("ret", "");
2911 emitcode ("", "%05d$:", (rlbl->key + 100));
2916 selectRegBank (FUNC_REGBANK(currFunc->type), IS_BIT (etype));
2919 /* if we need assign a result value */
2920 if ((IS_ITEMP (IC_RESULT (ic)) &&
2921 !IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))) &&
2922 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2923 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2924 IS_TRUE_SYMOP (IC_RESULT (ic)))
2928 aopOp (IC_RESULT (ic), ic, FALSE);
2931 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2933 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2936 /* adjust the stack for parameters if required */
2940 if (ic->parmBytes > 3)
2942 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))) &&
2943 IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2945 emitcode ("mov", "F0,c");
2949 emitcode ("mov", "a,%s", spname);
2950 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2951 emitcode ("mov", "%s,a", spname);
2954 for (i = 0; i < ic->parmBytes; i++)
2955 emitcode ("dec", "%s", spname);
2959 // /* if register bank was saved then unsave them */
2961 // unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2963 /* if we had saved some registers then unsave them */
2964 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2965 unsaveRegisters (ic);
2967 if (IS_BIT (OP_SYM_ETYPE (IC_RESULT (ic))))
2970 emitcode ("mov", "c,F0");
2972 aopOp (IC_RESULT (ic), ic, FALSE);
2973 assignResultValue (IC_RESULT (ic), IC_LEFT (ic));
2974 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2978 /*-----------------------------------------------------------------*/
2979 /* resultRemat - result is rematerializable */
2980 /*-----------------------------------------------------------------*/
2982 resultRemat (iCode * ic)
2984 if (SKIP_IC (ic) || ic->op == IFX)
2987 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2989 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2990 if (sym->remat && !POINTER_SET (ic))
2997 #if defined(__BORLANDC__) || defined(_MSC_VER)
2998 #define STRCASECMP stricmp
3000 #define STRCASECMP strcasecmp
3003 /*-----------------------------------------------------------------*/
3004 /* inExcludeList - return 1 if the string is in exclude Reg list */
3005 /*-----------------------------------------------------------------*/
3007 regsCmp(void *p1, void *p2)
3009 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
3013 inExcludeList (char *s)
3015 const char *p = setFirstItem(options.excludeRegsSet);
3017 if (p == NULL || STRCASECMP(p, "none") == 0)
3021 return isinSetWith(options.excludeRegsSet, s, regsCmp);
3024 /*-----------------------------------------------------------------*/
3025 /* genFunction - generated code for function entry */
3026 /*-----------------------------------------------------------------*/
3028 genFunction (iCode * ic)
3030 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3032 bool switchedPSW = FALSE;
3033 int calleesaves_saved_register = -1;
3034 int stackAdjust = sym->stack;
3035 int accIsFree = sym->recvSize < 4;
3036 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
3037 bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
3040 /* create the function header */
3041 emitcode (";", "-----------------------------------------");
3042 emitcode (";", " function %s", sym->name);
3043 emitcode (";", "-----------------------------------------");
3045 emitcode ("", "%s:", sym->rname);
3046 ftype = operandType (IC_LEFT (ic));
3047 _G.currentFunc = sym;
3049 if (IFFUNC_ISNAKED(ftype))
3051 emitcode(";", "naked function: no prologue.");
3055 /* here we need to generate the equates for the
3056 register bank if required */
3057 if (FUNC_REGBANK (ftype) != rbank)
3061 rbank = FUNC_REGBANK (ftype);
3062 for (i = 0; i < mcs51_nRegs; i++)
3064 if (regs8051[i].type != REG_BIT)
3066 if (strcmp (regs8051[i].base, "0") == 0)
3067 emitcode ("", "%s = 0x%02x",
3069 8 * rbank + regs8051[i].offset);
3071 emitcode ("", "%s = %s + 0x%02x",
3074 8 * rbank + regs8051[i].offset);
3079 /* if this is an interrupt service routine then
3080 save acc, b, dpl, dph */
3081 if (IFFUNC_ISISR (sym->type))
3084 if (!inExcludeList ("acc"))
3085 emitcode ("push", "acc");
3086 if (!inExcludeList ("b"))
3087 emitcode ("push", "b");
3088 if (!inExcludeList ("dpl"))
3089 emitcode ("push", "dpl");
3090 if (!inExcludeList ("dph"))
3091 emitcode ("push", "dph");
3092 /* if this isr has no bank i.e. is going to
3093 run with bank 0 , then we need to save more
3095 if (!FUNC_REGBANK (sym->type))
3098 /* if this function does not call any other
3099 function then we can be economical and
3100 save only those registers that are used */
3101 if (!IFFUNC_HASFCALL(sym->type))
3105 /* if any registers used */
3108 bool bits_pushed = FALSE;
3109 /* save the registers used */
3110 for (i = 0; i < sym->regsUsed->size; i++)
3112 if (bitVectBitValue (sym->regsUsed, i))
3113 bits_pushed = pushReg (i, bits_pushed);
3120 /* this function has a function call. We cannot
3121 determines register usage so we will have to push the
3123 saveRBank (0, ic, FALSE);
3124 if (options.parms_in_bank1) {
3126 for (i=0; i < 8 ; i++ ) {
3127 emitcode ("push","%s",rb1regs[i]);
3134 /* This ISR uses a non-zero bank.
3136 * We assume that the bank is available for our
3139 * However, if this ISR calls a function which uses some
3140 * other bank, we must save that bank entirely.
3142 unsigned long banksToSave = 0;
3144 if (IFFUNC_HASFCALL(sym->type))
3147 #define MAX_REGISTER_BANKS 4
3152 for (i = ic; i; i = i->next)
3154 if (i->op == ENDFUNCTION)
3156 /* we got to the end OK. */
3164 dtype = operandType (IC_LEFT(i));
3166 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3168 /* Mark this bank for saving. */
3169 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3171 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3175 banksToSave |= (1 << FUNC_REGBANK(dtype));
3178 /* And note that we don't need to do it in
3186 /* This is a mess; we have no idea what
3187 * register bank the called function might
3190 * The only thing I can think of to do is
3191 * throw a warning and hope.
3193 werror(W_FUNCPTR_IN_USING_ISR);
3197 if (banksToSave && options.useXstack)
3199 /* Since we aren't passing it an ic,
3200 * saveRBank will assume r0 is available to abuse.
3202 * So switch to our (trashable) bank now, so
3203 * the caller's R0 isn't trashed.
3205 emitcode ("push", "psw");
3206 emitcode ("mov", "psw,#0x%02x",
3207 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3211 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3213 if (banksToSave & (1 << ix))
3215 saveRBank(ix, NULL, FALSE);
3219 // TODO: this needs a closer look
3220 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3223 /* Set the register bank to the desired value if nothing else */
3224 /* has done so yet. */
3227 emitcode ("push", "psw");
3228 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3233 /* This is a non-ISR function. The caller has already switched register */
3234 /* banks, if necessary, so just handle the callee-saves option. */
3236 /* if callee-save to be used for this function
3237 then save the registers being used in this function */
3238 if (IFFUNC_CALLEESAVES(sym->type))
3242 /* if any registers used */
3245 bool bits_pushed = FALSE;
3246 /* save the registers used */
3247 for (i = 0; i < sym->regsUsed->size; i++)
3249 if (bitVectBitValue (sym->regsUsed, i))
3251 /* remember one saved register for later usage */
3252 if (calleesaves_saved_register < 0)
3253 calleesaves_saved_register = i;
3254 bits_pushed = pushReg (i, bits_pushed);
3265 if (options.useXstack)
3267 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3269 emitcode ("mov", "r0,%s", spname);
3270 emitcode ("inc", "%s", spname);
3271 emitcode ("xch", "a,_bpx");
3272 emitcode ("movx", "@r0,a");
3273 emitcode ("inc", "r0");
3274 emitcode ("mov", "a,r0");
3275 emitcode ("xch", "a,_bpx");
3279 emitcode ("push", "_bp"); /* save the callers stack */
3280 emitcode ("mov", "_bp,sp");
3285 if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3287 /* set up the stack */
3288 emitcode ("push", "_bp"); /* save the callers stack */
3289 emitcode ("mov", "_bp,sp");
3294 /* For some cases it is worthwhile to perform a RECEIVE iCode */
3295 /* before setting up the stack frame completely. */
3296 if (ric && ric->argreg == 1 && IC_RESULT (ric))
3298 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
3302 if (rsym && rsym->regType == REG_CND)
3304 if (rsym && (rsym->accuse || rsym->ruonly))
3306 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
3307 rsym = rsym->usl.spillLoc;
3310 /* If the RECEIVE operand immediately spills to the first entry on the */
3311 /* stack, we can push it directly (since sp = _bp + 1 at this point) */
3312 /* rather than the usual @r0/r1 machinations. */
3313 if (!options.useXstack && rsym && rsym->onStack && rsym->stack == 1)
3317 _G.current_iCode = ric;
3318 D(emitcode ("; genReceive",""));
3319 for (ofs=0; ofs < sym->recvSize; ofs++)
3321 if (!strcmp (fReturn[ofs], "a"))
3322 emitcode ("push", "acc");
3324 emitcode ("push", fReturn[ofs]);
3326 stackAdjust -= sym->recvSize;
3329 assert (stackAdjust>=0);
3332 _G.current_iCode = ic;
3336 /* If the RECEIVE operand is 4 registers, we can do the moves now */
3337 /* to free up the accumulator. */
3338 else if (rsym && rsym->nRegs && sym->recvSize == 4)
3342 _G.current_iCode = ric;
3343 D(emitcode ("; genReceive",""));
3344 for (ofs=0; ofs < sym->recvSize; ofs++)
3346 emitcode ("mov", "%s,%s", rsym->regs[ofs]->name, fReturn[ofs]);
3348 _G.current_iCode = ic;
3354 /* adjust the stack for the function */
3357 int i = stackAdjust;
3359 werror (W_STACK_OVERFLOW, sym->name);
3361 if (i > 3 && accIsFree)
3363 emitcode ("mov", "a,sp");
3364 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3365 emitcode ("mov", "sp,a");
3369 /* The accumulator is not free, so we will need another register */
3370 /* to clobber. No need to worry about a possible conflict with */
3371 /* the above early RECEIVE optimizations since they would have */
3372 /* freed the accumulator if they were generated. */
3374 if (IFFUNC_CALLEESAVES(sym->type))
3376 /* if it's a callee-saves function we need a saved register */
3377 if (calleesaves_saved_register >= 0)
3379 emitcode ("mov", "%s,a", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3380 emitcode ("mov", "a,sp");
3381 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3382 emitcode ("mov", "sp,a");
3383 emitcode ("mov", "a,%s", mcs51_regWithIdx (calleesaves_saved_register)->dname);
3386 /* do it the hard way */
3388 emitcode ("inc", "sp");
3392 /* not callee-saves, we can clobber r0 */
3393 emitcode ("mov", "r0,a");
3394 emitcode ("mov", "a,sp");
3395 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
3396 emitcode ("mov", "sp,a");
3397 emitcode ("mov", "a,r0");
3402 emitcode ("inc", "sp");
3407 char i = ((char) sym->xstack & 0xff);
3409 if (i > 3 && accIsFree)
3411 emitcode ("mov", "a,_spx");
3412 emitcode ("add", "a,#0x%02x", i);
3413 emitcode ("mov", "_spx,a");
3417 emitcode ("push", "acc");
3418 emitcode ("mov", "a,_spx");
3419 emitcode ("add", "a,#0x%02x", i);
3420 emitcode ("mov", "_spx,a");
3421 emitcode ("pop", "acc");
3426 emitcode ("inc", "_spx");
3430 /* if critical function then turn interrupts off */
3431 if (IFFUNC_ISCRITICAL (ftype))
3433 symbol *tlbl = newiTempLabel (NULL);
3434 emitcode ("setb", "c");
3435 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
3436 emitcode ("clr", "c");
3437 emitcode ("", "%05d$:", (tlbl->key + 100));
3438 emitcode ("push", "psw"); /* save old ea via c in psw */
3442 /*-----------------------------------------------------------------*/
3443 /* genEndFunction - generates epilogue for functions */
3444 /*-----------------------------------------------------------------*/
3446 genEndFunction (iCode * ic)
3448 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3449 lineNode *lnp = lineCurr;
3451 bitVect *regsUsedPrologue;
3452 bitVect *regsUnneeded;
3455 _G.currentFunc = NULL;
3456 if (IFFUNC_ISNAKED(sym->type))
3458 emitcode(";", "naked function: no epilogue.");
3459 if (options.debug && currFunc)
3460 debugFile->writeEndFunction (currFunc, ic, 0);
3464 if (IFFUNC_ISCRITICAL (sym->type))
3466 if (IS_BIT (OP_SYM_ETYPE (IC_LEFT (ic))))
3468 emitcode ("rlc", "a"); /* save c in a */
3469 emitcode ("pop", "psw"); /* restore ea via c in psw */
3470 emitcode ("mov", "ea,c");
3471 emitcode ("rrc", "a"); /* restore c from a */
3475 emitcode ("pop", "psw"); /* restore ea via c in psw */
3476 emitcode ("mov", "ea,c");
3480 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3482 if (options.useXstack)
3486 emitcode ("mov", "sp,_bp");
3487 emitcode ("pop", "_bp");
3489 if (sym->xstack || FUNC_HASSTACKPARM(sym->type))
3491 emitcode ("xch", "a,_bpx");
3492 emitcode ("mov", "r0,a");
3493 emitcode ("dec", "r0");
3494 emitcode ("movx", "a,@r0");
3495 emitcode ("xch", "a,_bpx");
3496 emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
3499 else if (sym->stack || FUNC_HASSTACKPARM(sym->type))
3501 emitcode ("mov", "sp,_bp");
3502 emitcode ("pop", "_bp");
3506 /* restore the register bank */
3507 if ( /* FUNC_REGBANK (sym->type) || */ IFFUNC_ISISR (sym->type))
3509 if (/* !FUNC_REGBANK (sym->type) || */ !IFFUNC_ISISR (sym->type)
3510 || !options.useXstack)
3512 /* Special case of ISR using non-zero bank with useXstack
3515 emitcode ("pop", "psw");
3519 if (IFFUNC_ISISR (sym->type))
3522 /* now we need to restore the registers */
3523 /* if this isr has no bank i.e. is going to
3524 run with bank 0 , then we need to save more
3526 if (!FUNC_REGBANK (sym->type))
3528 /* if this function does not call any other
3529 function then we can be economical and
3530 save only those registers that are used */
3531 if (!IFFUNC_HASFCALL(sym->type))
3535 /* if any registers used */
3538 bool bits_popped = FALSE;
3539 /* save the registers used */
3540 for (i = sym->regsUsed->size; i >= 0; i--)
3542 if (bitVectBitValue (sym->regsUsed, i))
3543 bits_popped = popReg (i, bits_popped);
3549 if (options.parms_in_bank1) {
3551 for (i = 7 ; i >= 0 ; i-- ) {
3552 emitcode ("pop","%s",rb1regs[i]);
3555 /* this function has a function call cannot
3556 determines register usage so we will have to pop the
3558 unsaveRBank (0, ic, FALSE);
3563 /* This ISR uses a non-zero bank.
3565 * Restore any register banks saved by genFunction
3568 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3571 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3573 if (savedBanks & (1 << ix))
3575 unsaveRBank(ix, NULL, FALSE);
3579 if (options.useXstack)
3581 /* Restore bank AFTER calling unsaveRBank,
3582 * since it can trash r0.
3584 emitcode ("pop", "psw");
3588 if (!inExcludeList ("dph"))
3589 emitcode ("pop", "dph");
3590 if (!inExcludeList ("dpl"))
3591 emitcode ("pop", "dpl");
3592 if (!inExcludeList ("b"))
3593 emitcode ("pop", "b");
3594 if (!inExcludeList ("acc"))
3595 emitcode ("pop", "acc");
3597 /* if debug then send end of function */
3598 if (options.debug && currFunc)
3600 debugFile->writeEndFunction (currFunc, ic, 1);
3603 emitcode ("reti", "");
3607 if (IFFUNC_CALLEESAVES(sym->type))
3611 /* if any registers used */
3614 /* save the registers used */
3615 for (i = sym->regsUsed->size; i >= 0; i--)
3617 if (bitVectBitValue (sym->regsUsed, i) ||
3618 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3619 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
3622 else if (mcs51_ptrRegReq)
3624 emitcode ("pop", "%s", mcs51_regWithIdx (R1_IDX)->dname);
3625 emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
3630 /* if debug then send end of function */
3631 if (options.debug && currFunc)
3633 debugFile->writeEndFunction (currFunc, ic, 1);
3636 if (IFFUNC_ISBANKEDCALL (sym->type) && !SPEC_STAT(getSpec(sym->type)))
3638 emitcode ("ljmp", "__sdcc_banked_ret");
3642 emitcode ("ret", "");
3646 if (!port->peep.getRegsRead || !port->peep.getRegsWritten || options.nopeep)
3649 /* If this was an interrupt handler using bank 0 that called another */
3650 /* function, then all registers must be saved; nothing to optimized. */
3651 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)
3652 && !FUNC_REGBANK(sym->type))
3655 /* There are no push/pops to optimize if not callee-saves or ISR */
3656 if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type)))
3659 /* If there were stack parameters, we cannot optimize without also */
3660 /* fixing all of the stack offsets; this is too dificult to consider. */
3661 if (FUNC_HASSTACKPARM(sym->type))
3664 /* Compute the registers actually used */
3665 regsUsed = newBitVect (mcs51_nRegs);
3666 regsUsedPrologue = newBitVect (mcs51_nRegs);
3669 if (lnp->ic && lnp->ic->op == FUNCTION)
3670 regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp));
3672 regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp));
3674 if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev
3675 && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION)
3682 if (bitVectBitValue (regsUsedPrologue, CND_IDX)
3683 && !bitVectBitValue (regsUsed, CND_IDX))
3685 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3686 if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK (sym->type)
3687 && !sym->stack && !FUNC_ISCRITICAL (sym->type))
3688 bitVectUnSetBit (regsUsed, CND_IDX);
3691 regsUsed = bitVectUnion (regsUsed, regsUsedPrologue);
3693 /* If this was an interrupt handler that called another function */
3694 /* function, then assume A, B, DPH, & DPL may be modified by it. */
3695 if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type))
3697 regsUsed = bitVectSetBit (regsUsed, DPL_IDX);
3698 regsUsed = bitVectSetBit (regsUsed, DPH_IDX);
3699 regsUsed = bitVectSetBit (regsUsed, B_IDX);
3700 regsUsed = bitVectSetBit (regsUsed, A_IDX);
3701 regsUsed = bitVectSetBit (regsUsed, CND_IDX);
3704 /* Remove the unneeded push/pops */
3705 regsUnneeded = newBitVect (mcs51_nRegs);
3708 if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION))
3710 if (!strncmp(lnp->line, "push", 4))
3712 idx = bitVectFirstBit (port->peep.getRegsRead(lnp));
3713 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3715 connectLine (lnp->prev, lnp->next);
3716 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3719 if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3))
3721 idx = bitVectFirstBit (port->peep.getRegsWritten(lnp));
3722 if (idx>=0 && !bitVectBitValue (regsUsed, idx))
3724 connectLine (lnp->prev, lnp->next);
3725 regsUnneeded = bitVectSetBit (regsUnneeded, idx);
3732 for (idx = 0; idx < regsUnneeded->size; idx++)
3733 if (bitVectBitValue (regsUnneeded, idx))
3734 emitcode ("", ";\teliminated unneeded push/pop %s", mcs51_regWithIdx (idx)->dname);
3736 freeBitVect (regsUnneeded);
3737 freeBitVect (regsUsed);
3738 freeBitVect (regsUsedPrologue);
3741 /*-----------------------------------------------------------------*/
3742 /* genRet - generate code for return statement */
3743 /*-----------------------------------------------------------------*/
3747 int size, offset = 0, pushed = 0;
3749 D(emitcode ("; genRet",""));
3751 /* if we have no return value then
3752 just generate the "ret" */
3756 /* we have something to return then
3757 move the return value into place */
3758 aopOp (IC_LEFT (ic), ic, FALSE);
3759 size = AOP_SIZE (IC_LEFT (ic));
3762 if (IS_BIT(_G.currentFunc->etype))
3764 movc (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
3771 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3774 l = aopGet (IC_LEFT (ic), offset++,
3776 emitcode ("push", "%s", l);
3781 l = aopGet (IC_LEFT (ic), offset,
3783 if (strcmp (fReturn[offset], l))
3784 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3791 if (strcmp (fReturn[pushed], "a"))
3792 emitcode ("pop", fReturn[pushed]);
3794 emitcode ("pop", "acc");
3796 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3799 /* generate a jump to the return label
3800 if the next is not the return statement */
3801 if (!(ic->next && ic->next->op == LABEL &&
3802 IC_LABEL (ic->next) == returnLabel))
3804 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
3808 /*-----------------------------------------------------------------*/
3809 /* genLabel - generates a label */
3810 /*-----------------------------------------------------------------*/
3812 genLabel (iCode * ic)
3814 /* special case never generate */
3815 if (IC_LABEL (ic) == entryLabel)
3818 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3821 /*-----------------------------------------------------------------*/
3822 /* genGoto - generates a ljmp */
3823 /*-----------------------------------------------------------------*/
3825 genGoto (iCode * ic)
3827 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
3830 /*-----------------------------------------------------------------*/
3831 /* findLabelBackwards: walks back through the iCode chain looking */
3832 /* for the given label. Returns number of iCode instructions */
3833 /* between that label and given ic. */
3834 /* Returns zero if label not found. */
3835 /*-----------------------------------------------------------------*/
3837 findLabelBackwards (iCode * ic, int key)
3846 /* If we have any pushes or pops, we cannot predict the distance.
3847 I don't like this at all, this should be dealt with in the
3849 if (ic->op == IPUSH || ic->op == IPOP) {
3853 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3862 /*-----------------------------------------------------------------*/
3863 /* genPlusIncr :- does addition with increment if possible */
3864 /*-----------------------------------------------------------------*/
3866 genPlusIncr (iCode * ic)
3868 unsigned int icount;
3869 unsigned int size = getDataSize (IC_RESULT (ic));
3871 /* will try to generate an increment */
3872 /* if the right side is not a literal
3874 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3877 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3879 D(emitcode ("; genPlusIncr",""));
3881 /* if increment >=16 bits in register or direct space */
3882 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
3883 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3884 !isOperandVolatile (IC_RESULT (ic), FALSE) &&
3892 /* If the next instruction is a goto and the goto target
3893 * is < 10 instructions previous to this, we can generate
3894 * jumps straight to that target.
3896 if (ic->next && ic->next->op == GOTO
3897 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3898 && labelRange <= 10)
3900 emitcode (";", "tail increment optimized");
3901 tlbl = IC_LABEL (ic->next);
3906 tlbl = newiTempLabel (NULL);
3909 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
3910 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3911 IS_AOP_PREG (IC_RESULT (ic)))
3912 emitcode ("cjne", "%s,#0x00,%05d$",
3913 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3917 emitcode ("clr", "a");
3918 emitcode ("cjne", "a,%s,%05d$",
3919 aopGet (IC_RESULT (ic), LSB, FALSE, FALSE),
3923 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
3926 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3927 IS_AOP_PREG (IC_RESULT (ic)))
3928 emitcode ("cjne", "%s,#0x00,%05d$",
3929 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3932 emitcode ("cjne", "a,%s,%05d$",
3933 aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE),
3936 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
3940 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3941 IS_AOP_PREG (IC_RESULT (ic)))
3942 emitcode ("cjne", "%s,#0x00,%05d$",
3943 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3947 emitcode ("cjne", "a,%s,%05d$",
3948 aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE),
3951 emitcode ("inc", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
3956 emitcode ("", "%05d$:", tlbl->key + 100);
3961 /* if result is dptr */
3962 if ((AOP_TYPE (IC_RESULT (ic)) == AOP_STR) &&
3963 (AOP_SIZE (IC_RESULT (ic)) == 2) &&
3964 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[0], "dpl", 4) &&
3965 !strncmp(AOP (IC_RESULT (ic))->aopu.aop_str[1], "dph", 4))
3967 if (aopGetUsesAcc (IC_LEFT (ic), 0))
3973 if ((AOP_TYPE (IC_LEFT (ic)) != AOP_DIR) && (icount > 5))
3976 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 0, FALSE, FALSE), 0, FALSE);
3977 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), 1, FALSE, FALSE), 1, FALSE);
3979 emitcode ("inc", "dptr");
3984 /* if the literal value of the right hand side
3985 is greater than 4 then it is not worth it */
3989 /* if the sizes are greater than 1 then we cannot */
3990 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3991 AOP_SIZE (IC_LEFT (ic)) > 1)
3994 /* we can if the aops of the left & result match or
3995 if they are in registers and the registers are the
3997 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4002 MOVA (aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4003 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
4004 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4010 emitcode ("inc", "%s", aopGet (IC_LEFT (ic), 0, FALSE, FALSE));
4019 /*-----------------------------------------------------------------*/
4020 /* outBitAcc - output a bit in acc */
4021 /*-----------------------------------------------------------------*/
4023 outBitAcc (operand * result)
4025 symbol *tlbl = newiTempLabel (NULL);
4026 /* if the result is a bit */
4027 if (AOP_TYPE (result) == AOP_CRY)
4029 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4033 emitcode ("jz", "%05d$", tlbl->key + 100);
4034 emitcode ("mov", "a,%s", one);
4035 emitcode ("", "%05d$:", tlbl->key + 100);
4040 /*-----------------------------------------------------------------*/
4041 /* genPlusBits - generates code for addition of two bits */
4042 /*-----------------------------------------------------------------*/
4044 genPlusBits (iCode * ic)
4046 D(emitcode ("; genPlusBits",""));
4048 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4050 symbol *lbl = newiTempLabel (NULL);
4051 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4052 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4053 emitcode ("cpl", "c");
4054 emitcode ("", "%05d$:", (lbl->key + 100));
4055 outBitC (IC_RESULT (ic));
4059 emitcode ("clr", "a");
4060 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4061 emitcode ("rlc", "a");
4062 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4063 emitcode ("addc", "a,#0x00");
4064 outAcc (IC_RESULT (ic));
4069 /* This is the original version of this code.
4071 * This is being kept around for reference,
4072 * because I am not entirely sure I got it right...
4075 adjustArithmeticResult (iCode * ic)
4077 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4078 AOP_SIZE (IC_LEFT (ic)) == 3 &&
4079 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4080 aopPut (IC_RESULT (ic),
4081 aopGet (IC_LEFT (ic)), 2, FALSE, FALSE),
4083 isOperandVolatile (IC_RESULT (ic), FALSE));
4085 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4086 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
4087 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4088 aopPut (IC_RESULT (ic),
4089 aopGet (IC_RIGHT (ic)), 2, FALSE, FALSE),
4091 isOperandVolatile (IC_RESULT (ic), FALSE));
4093 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
4094 AOP_SIZE (IC_LEFT (ic)) < 3 &&
4095 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
4096 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4097 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4100 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4101 aopPut (IC_RESULT (ic), buffer, 2, isOperandVolatile (IC_RESULT (ic), FALSE));
4105 /* This is the pure and virtuous version of this code.
4106 * I'm pretty certain it's right, but not enough to toss the old
4110 adjustArithmeticResult (iCode * ic)
4112 if (opIsGptr (IC_RESULT (ic)) &&
4113 opIsGptr (IC_LEFT (ic)) &&
4114 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4116 aopPut (IC_RESULT (ic),
4117 aopGet (IC_LEFT (ic), GPTRSIZE - 1, FALSE, FALSE),
4119 isOperandVolatile (IC_RESULT (ic), FALSE));
4122 if (opIsGptr (IC_RESULT (ic)) &&
4123 opIsGptr (IC_RIGHT (ic)) &&
4124 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4126 aopPut (IC_RESULT (ic),
4127 aopGet (IC_RIGHT (ic), GPTRSIZE - 1, FALSE, FALSE),
4129 isOperandVolatile (IC_RESULT (ic), FALSE));
4132 if (opIsGptr (IC_RESULT (ic)) &&
4133 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
4134 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
4135 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
4136 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
4139 sprintf (buffer, "#%d", pointerTypeToGPByte (pointerCode (getSpec (operandType (IC_LEFT (ic)))), NULL, NULL));
4140 aopPut (IC_RESULT (ic), buffer, GPTRSIZE - 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4145 /*-----------------------------------------------------------------*/
4146 /* genPlus - generates code for addition */
4147 /*-----------------------------------------------------------------*/
4149 genPlus (iCode * ic)
4151 int size, offset = 0;
4154 operand *leftOp, *rightOp;
4157 /* special cases :- */
4159 D(emitcode ("; genPlus",""));
4161 aopOp (IC_LEFT (ic), ic, FALSE);
4162 aopOp (IC_RIGHT (ic), ic, FALSE);
4163 aopOp (IC_RESULT (ic), ic, TRUE);
4165 /* if literal, literal on the right or
4166 if left requires ACC or right is already
4168 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4169 (AOP_NEEDSACC (IC_LEFT (ic))) ||
4170 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4172 operand *t = IC_RIGHT (ic);
4173 IC_RIGHT (ic) = IC_LEFT (ic);
4177 /* if both left & right are in bit
4179 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4180 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4186 /* if left in bit space & right literal */
4187 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4188 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4190 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4191 /* if result in bit space */
4192 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4194 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4195 emitcode ("cpl", "c");
4196 outBitC (IC_RESULT (ic));
4200 size = getDataSize (IC_RESULT (ic));
4203 MOVA (aopGet (IC_RIGHT (ic), offset, FALSE, FALSE));
4204 emitcode ("addc", "a,#00");
4205 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4211 /* if I can do an increment instead
4212 of add then GOOD for ME */
4213 if (genPlusIncr (ic) == TRUE)
4216 size = getDataSize (IC_RESULT (ic));
4217 leftOp = IC_LEFT(ic);
4218 rightOp = IC_RIGHT(ic);
4221 /* if this is an add for an array access
4222 at a 256 byte boundary */
4224 && AOP_TYPE (op) == AOP_IMMD
4226 && IS_SPEC (OP_SYM_ETYPE (op))
4227 && SPEC_ABSA (OP_SYM_ETYPE (op))
4228 && (SPEC_ADDR (OP_SYM_ETYPE (op)) & 0xff) == 0
4231 D(emitcode ("; genPlus aligned array",""));
4232 aopPut (IC_RESULT (ic),
4233 aopGet (rightOp, 0, FALSE, FALSE),
4235 isOperandVolatile (IC_RESULT (ic), FALSE));
4237 if( 1 == getDataSize (IC_RIGHT (ic)) )
4239 aopPut (IC_RESULT (ic),
4240 aopGet (leftOp, 1, FALSE, FALSE),
4242 isOperandVolatile (IC_RESULT (ic), FALSE));
4246 MOVA (aopGet (IC_LEFT (ic), 1, FALSE, FALSE));
4247 emitcode ("add", "a,%s", aopGet (rightOp, 1, FALSE, FALSE));
4248 aopPut (IC_RESULT (ic), "a", 1, isOperandVolatile (IC_RESULT (ic), FALSE));
4253 /* if the lower bytes of a literal are zero skip the addition */
4254 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT )
4256 while ((0 == ((unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) & (0xff << skip_bytes*8))) &&
4257 (skip_bytes+1 < size))
4262 D(emitcode ("; genPlus shortcut",""));
4267 if( offset >= skip_bytes )
4269 if (aopGetUsesAcc (leftOp, offset) && aopGetUsesAcc (rightOp, offset))
4272 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4274 emitcode("xch", "a,b");
4275 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4276 emitcode (add, "a,b");
4279 else if (aopGetUsesAcc (leftOp, offset))
4281 MOVA (aopGet (leftOp, offset, FALSE, TRUE));
4282 emitcode (add, "a,%s", aopGet (rightOp, offset, FALSE, TRUE));
4286 MOVA (aopGet (rightOp, offset, FALSE, TRUE));
4287 emitcode (add, "a,%s", aopGet (leftOp, offset, FALSE, TRUE));
4289 aopPut (IC_RESULT (ic), "a", offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4290 add = "addc"; /* further adds must propagate carry */
4294 if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
4295 isOperandVolatile (IC_RESULT (ic), FALSE))
4298 aopPut (IC_RESULT (ic),
4299 aopGet (leftOp, offset, FALSE, FALSE),
4301 isOperandVolatile (IC_RESULT (ic), FALSE));
4307 adjustArithmeticResult (ic);
4310 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4311 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4312 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4315 /*-----------------------------------------------------------------*/
4316 /* genMinusDec :- does subtraction with decrement if possible */
4317 /*-----------------------------------------------------------------*/
4319 genMinusDec (iCode * ic)
4321 unsigned int icount;
4322 unsigned int size = getDataSize (IC_RESULT (ic));
4324 /* will try to generate an increment */
4325 /* if the right side is not a literal
4327 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4330 /* if the literal value of the right hand side
4331 is greater than 4 then it is not worth it */
4332 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4335 D(emitcode ("; genMinusDec",""));
4337 /* if decrement >=16 bits in register or direct space */
4338 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR) &&
4339 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4347 /* If the next instruction is a goto and the goto target
4348 * is <= 10 instructions previous to this, we can generate
4349 * jumps straight to that target.
4351 if (ic->next && ic->next->op == GOTO
4352 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4353 && labelRange <= 10)
4355 emitcode (";", "tail decrement optimized");
4356 tlbl = IC_LABEL (ic->next);
4361 tlbl = newiTempLabel (NULL);
4365 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), LSB, FALSE, FALSE));
4366 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4367 IS_AOP_PREG (IC_RESULT (ic)))
4368 emitcode ("cjne", "%s,#0xff,%05d$"
4369 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4373 emitcode ("mov", "a,#0xff");
4374 emitcode ("cjne", "a,%s,%05d$"
4375 ,aopGet (IC_RESULT (ic), LSB, FALSE, FALSE)
4378 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE));
4381 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4382 IS_AOP_PREG (IC_RESULT (ic)))
4383 emitcode ("cjne", "%s,#0xff,%05d$"
4384 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4388 emitcode ("cjne", "a,%s,%05d$"
4389 ,aopGet (IC_RESULT (ic), MSB16, FALSE, FALSE)
4392 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE));
4396 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4397 IS_AOP_PREG (IC_RESULT (ic)))
4398 emitcode ("cjne", "%s,#0xff,%05d$"
4399 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4403 emitcode ("cjne", "a,%s,%05d$"
4404 ,aopGet (IC_RESULT (ic), MSB24, FALSE, FALSE)
4407 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), MSB32, FALSE, FALSE));
4411 emitcode ("", "%05d$:", tlbl->key + 100);
4416 /* if the sizes are greater than 1 then we cannot */
4417 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4418 AOP_SIZE (IC_LEFT (ic)) > 1)
4421 /* we can if the aops of the left & result match or
4422 if they are in registers and the registers are the
4424 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4428 emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
4436 /*-----------------------------------------------------------------*/
4437 /* addSign - complete with sign */
4438 /*-----------------------------------------------------------------*/
4440 addSign (operand * result, int offset, int sign)
4442 int size = (getDataSize (result) - offset);
4447 emitcode ("rlc", "a");
4448 emitcode ("subb", "a,acc");
4450 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
4454 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4458 /*-----------------------------------------------------------------*/
4459 /* genMinusBits - generates code for subtraction of two bits */
4460 /*-----------------------------------------------------------------*/
4462 genMinusBits (iCode * ic)
4464 symbol *lbl = newiTempLabel (NULL);
4466 D(emitcode ("; genMinusBits",""));
4468 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4470 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4471 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4472 emitcode ("cpl", "c");
4473 emitcode ("", "%05d$:", (lbl->key + 100));
4474 outBitC (IC_RESULT (ic));
4478 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4479 emitcode ("subb", "a,acc");
4480 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4481 emitcode ("inc", "a");
4482 emitcode ("", "%05d$:", (lbl->key + 100));
4483 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
4484 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4488 /*-----------------------------------------------------------------*/
4489 /* genMinus - generates code for subtraction */
4490 /*-----------------------------------------------------------------*/
4492 genMinus (iCode * ic)
4494 int size, offset = 0;
4496 D(emitcode ("; genMinus",""));
4498 aopOp (IC_LEFT (ic), ic, FALSE);
4499 aopOp (IC_RIGHT (ic), ic, FALSE);
4500 aopOp (IC_RESULT (ic), ic, TRUE);
4502 /* special cases :- */
4503 /* if both left & right are in bit space */
4504 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4505 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4511 /* if I can do an decrement instead
4512 of subtract then GOOD for ME */
4513 if (genMinusDec (ic) == TRUE)
4516 size = getDataSize (IC_RESULT (ic));
4518 /* if literal, add a,#-lit, else normal subb */
4519 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4521 unsigned long lit = 0L;
4522 bool useCarry = FALSE;
4524 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4529 if (useCarry || ((lit >> (offset * 8)) & 0x0FFL))
4531 MOVA (aopGet (IC_LEFT (ic), offset, FALSE, FALSE));
4532 if (!offset && !size && lit== (unsigned long) -1)
4534 emitcode ("dec", "a");
4538 /* first add without previous c */
4539 emitcode ("add", "a,#0x%02x",
4540 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4545 emitcode ("addc", "a,#0x%02x",
4546 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4548 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4552 /* no need to add zeroes */
4553 if (!sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
4555 aopPut (IC_RESULT (ic), aopGet (IC_LEFT (ic), offset, FALSE, FALSE),
4556 offset, isOperandVolatile (IC_RESULT (ic), FALSE));
4564 operand *leftOp, *rightOp;
4566 leftOp = IC_LEFT(ic);
4567 rightOp = IC_RIGHT(ic);
4571 if (aopGetUsesAcc(rightOp, offset)) {
4572 if (aopGetUsesAcc(leftOp, offset)) {
4575 MOVA (aopGet (rightOp, offset, FALSE, FALSE));
4577 emitcode ("mov", "b,a");
4580 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4581 emitcode ("subb", "a,b");
4584 wassertl(!aopGetUsesAcc(leftOp, offset), "accumulator clash");
4585 MOVA (aopGet(rightOp, offset, FALSE, TRUE));
4587 emitcode( "setb", "c");
4589 emitcode("subb", "a,%s", aopGet(leftOp, offset, FALSE, TRUE));
4590 emitcode("cpl", "a");
4593 MOVA (aopGet (leftOp, offset, FALSE, FALSE));
4596 emitcode ("subb", "a,%s",
4597 aopGet(rightOp, offset, FALSE, TRUE));
4600 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
4605 adjustArithmeticResult (ic);
4608 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4609 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4610 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4614 /*-----------------------------------------------------------------*/
4615 /* genMultbits :- multiplication of bits */
4616 /*-----------------------------------------------------------------*/
4618 genMultbits (operand * left,
4622 D(emitcode ("; genMultbits",""));
4624 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4625 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4629 /*-----------------------------------------------------------------*/
4630 /* genMultOneByte : 8*8=8/16 bit multiplication */
4631 /*-----------------------------------------------------------------*/
4633 genMultOneByte (operand * left,
4638 int size = AOP_SIZE (result);
4639 bool runtimeSign, compiletimeSign;
4640 bool lUnsigned, rUnsigned, pushedB;
4642 D(emitcode ("; genMultOneByte",""));
4644 if (size < 1 || size > 2)
4646 /* this should never happen */
4647 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4648 AOP_SIZE(result), __FILE__, lineno);
4652 /* (if two literals: the value is computed before) */
4653 /* if one literal, literal on the right */
4654 if (AOP_TYPE (left) == AOP_LIT)
4659 /* emitcode (";", "swapped left and right"); */
4661 /* if no literal, unsigned on the right: shorter code */
4662 if ( AOP_TYPE (right) != AOP_LIT
4663 && SPEC_USIGN (getSpec (operandType (left))))
4670 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4671 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4675 if (size == 1 /* no, this is not a bug; with a 1 byte result there's
4676 no need to take care about the signedness! */
4677 || (lUnsigned && rUnsigned))
4679 /* just an unsigned 8 * 8 = 8 multiply
4681 /* emitcode (";","unsigned"); */
4682 /* TODO: check for accumulator clash between left & right aops? */
4684 if (AOP_TYPE (right) == AOP_LIT)
4686 /* moving to accumulator first helps peepholes */
4687 MOVA (aopGet (left, 0, FALSE, FALSE));
4688 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4692 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4693 MOVA (aopGet (left, 0, FALSE, FALSE));
4696 emitcode ("mul", "ab");
4697 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4699 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4705 /* we have to do a signed multiply */
4706 /* emitcode (";", "signed"); */
4708 /* now sign adjust for both left & right */
4710 /* let's see what's needed: */
4711 /* apply negative sign during runtime */
4712 runtimeSign = FALSE;
4713 /* negative sign from literals */
4714 compiletimeSign = FALSE;
4718 if (AOP_TYPE(left) == AOP_LIT)
4720 /* signed literal */
4721 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4723 compiletimeSign = TRUE;
4726 /* signed but not literal */
4732 if (AOP_TYPE(right) == AOP_LIT)
4734 /* signed literal */
4735 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4737 compiletimeSign ^= TRUE;
4740 /* signed but not literal */
4744 /* initialize F0, which stores the runtime sign */
4747 if (compiletimeSign)
4748 emitcode ("setb", "F0"); /* set sign flag */
4750 emitcode ("clr", "F0"); /* reset sign flag */
4753 /* save the signs of the operands */
4754 if (AOP_TYPE(right) == AOP_LIT)
4756 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
4758 if (!rUnsigned && val < 0)
4759 emitcode ("mov", "b,#0x%02x", -val);
4761 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
4763 else /* ! literal */
4765 if (rUnsigned) /* emitcode (";", "signed"); */
4767 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4770 MOVA (aopGet (right, 0, FALSE, FALSE));
4771 lbl = newiTempLabel (NULL);
4772 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4773 emitcode ("cpl", "F0"); /* complement sign flag */
4774 emitcode ("cpl", "a"); /* 2's complement */
4775 emitcode ("inc", "a");
4776 emitcode ("", "%05d$:", (lbl->key + 100));
4777 emitcode ("mov", "b,a");
4781 if (AOP_TYPE(left) == AOP_LIT)
4783 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4785 if (!lUnsigned && val < 0)
4786 emitcode ("mov", "a,#0x%02x", -val);
4788 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
4790 else /* ! literal */
4792 MOVA (aopGet (left, 0, FALSE, FALSE));
4796 lbl = newiTempLabel (NULL);
4797 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
4798 emitcode ("cpl", "F0"); /* complement sign flag */
4799 emitcode ("cpl", "a"); /* 2's complement */
4800 emitcode ("inc", "a");
4801 emitcode ("", "%05d$:", (lbl->key + 100));
4805 /* now the multiplication */
4806 emitcode ("mul", "ab");
4807 if (runtimeSign || compiletimeSign)
4809 lbl = newiTempLabel (NULL);
4811 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
4812 emitcode ("cpl", "a"); /* lsb 2's complement */
4814 emitcode ("inc", "a"); /* inc doesn't set carry flag */
4817 emitcode ("add", "a,#1"); /* this sets carry flag */
4818 emitcode ("xch", "a,b");
4819 emitcode ("cpl", "a"); /* msb 2's complement */
4820 emitcode ("addc", "a,#0");
4821 emitcode ("xch", "a,b");
4823 emitcode ("", "%05d$:", (lbl->key + 100));
4825 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4827 aopPut (result, "b", 1, isOperandVolatile (result, FALSE));
4832 /*-----------------------------------------------------------------*/
4833 /* genMult - generates code for multiplication */
4834 /*-----------------------------------------------------------------*/
4836 genMult (iCode * ic)
4838 operand *left = IC_LEFT (ic);
4839 operand *right = IC_RIGHT (ic);
4840 operand *result = IC_RESULT (ic);
4842 D(emitcode ("; genMult",""));
4844 /* assign the amsops */
4845 aopOp (left, ic, FALSE);
4846 aopOp (right, ic, FALSE);
4847 aopOp (result, ic, TRUE);
4849 /* special cases first */
4851 if (AOP_TYPE (left) == AOP_CRY &&
4852 AOP_TYPE (right) == AOP_CRY)
4854 genMultbits (left, right, result);
4858 /* if both are of size == 1 */
4859 #if 0 // one of them can be a sloc shared with the result
4860 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
4862 if (getSize(operandType(left)) == 1 &&
4863 getSize(operandType(right)) == 1)
4866 genMultOneByte (left, right, result);
4870 /* should have been converted to function call */
4871 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
4872 getSize(OP_SYMBOL(right)->type));
4876 freeAsmop (result, NULL, ic, TRUE);
4877 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4878 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4881 /*-----------------------------------------------------------------*/
4882 /* genDivbits :- division of bits */
4883 /*-----------------------------------------------------------------*/
4885 genDivbits (operand * left,
4892 D(emitcode ("; genDivbits",""));
4896 /* the result must be bit */
4897 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4898 l = aopGet (left, 0, FALSE, FALSE);
4902 emitcode ("div", "ab");
4903 emitcode ("rrc", "a");
4907 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
4910 /*-----------------------------------------------------------------*/
4911 /* genDivOneByte : 8 bit division */
4912 /*-----------------------------------------------------------------*/
4914 genDivOneByte (operand * left,
4918 bool lUnsigned, rUnsigned, pushedB;
4919 bool runtimeSign, compiletimeSign;
4923 D(emitcode ("; genDivOneByte",""));
4925 /* Why is it necessary that genDivOneByte() can return an int result?
4928 volatile unsigned char uc;
4929 volatile signed char sc1, sc2;
4942 In all cases a one byte result would overflow, the following cast to int
4943 would return the wrong result.
4945 Two possible solution:
4946 a) cast operands to int, if ((unsigned) / (signed)) or
4947 ((signed) / (signed))
4948 b) return an 16 bit signed int; this is what we're doing here!
4951 size = AOP_SIZE (result) - 1;
4953 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
4954 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
4958 /* signed or unsigned */
4959 if (lUnsigned && rUnsigned)
4961 /* unsigned is easy */
4962 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
4963 MOVA (aopGet (left, 0, FALSE, FALSE));
4964 emitcode ("div", "ab");
4965 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
4967 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
4973 /* signed is a little bit more difficult */
4975 /* now sign adjust for both left & right */
4977 /* let's see what's needed: */
4978 /* apply negative sign during runtime */
4979 runtimeSign = FALSE;
4980 /* negative sign from literals */
4981 compiletimeSign = FALSE;
4985 if (AOP_TYPE(left) == AOP_LIT)
4987 /* signed literal */
4988 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
4990 compiletimeSign = TRUE;
4993 /* signed but not literal */
4999 if (AOP_TYPE(right) == AOP_LIT)
5001 /* signed literal */
5002 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5004 compiletimeSign ^= TRUE;
5007 /* signed but not literal */
5011 /* initialize F0, which stores the runtime sign */
5014 if (compiletimeSign)
5015 emitcode ("setb", "F0"); /* set sign flag */
5017 emitcode ("clr", "F0"); /* reset sign flag */
5020 /* save the signs of the operands */
5021 if (AOP_TYPE(right) == AOP_LIT)
5023 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
5025 if (!rUnsigned && val < 0)
5026 emitcode ("mov", "b,#0x%02x", -val);
5028 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5030 else /* ! literal */
5033 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5036 MOVA (aopGet (right, 0, FALSE, FALSE));
5037 lbl = newiTempLabel (NULL);
5038 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5039 emitcode ("cpl", "F0"); /* complement sign flag */
5040 emitcode ("cpl", "a"); /* 2's complement */
5041 emitcode ("inc", "a");
5042 emitcode ("", "%05d$:", (lbl->key + 100));
5043 emitcode ("mov", "b,a");
5047 if (AOP_TYPE(left) == AOP_LIT)
5049 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5051 if (!lUnsigned && val < 0)
5052 emitcode ("mov", "a,#0x%02x", -val);
5054 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5056 else /* ! literal */
5058 MOVA (aopGet (left, 0, FALSE, FALSE));
5062 lbl = newiTempLabel (NULL);
5063 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5064 emitcode ("cpl", "F0"); /* complement sign flag */
5065 emitcode ("cpl", "a"); /* 2's complement */
5066 emitcode ("inc", "a");
5067 emitcode ("", "%05d$:", (lbl->key + 100));
5071 /* now the division */
5072 emitcode ("div", "ab");
5074 if (runtimeSign || compiletimeSign)
5076 lbl = newiTempLabel (NULL);
5078 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5079 emitcode ("cpl", "a"); /* lsb 2's complement */
5080 emitcode ("inc", "a");
5081 emitcode ("", "%05d$:", (lbl->key + 100));
5083 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5086 /* msb is 0x00 or 0xff depending on the sign */
5089 emitcode ("mov", "c,F0");
5090 emitcode ("subb", "a,acc");
5092 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5094 else /* compiletimeSign */
5096 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5101 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5103 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5109 /*-----------------------------------------------------------------*/
5110 /* genDiv - generates code for division */
5111 /*-----------------------------------------------------------------*/
5115 operand *left = IC_LEFT (ic);
5116 operand *right = IC_RIGHT (ic);
5117 operand *result = IC_RESULT (ic);
5119 D(emitcode ("; genDiv",""));
5121 /* assign the amsops */
5122 aopOp (left, ic, FALSE);
5123 aopOp (right, ic, FALSE);
5124 aopOp (result, ic, TRUE);
5126 /* special cases first */
5128 if (AOP_TYPE (left) == AOP_CRY &&
5129 AOP_TYPE (right) == AOP_CRY)
5131 genDivbits (left, right, result);
5135 /* if both are of size == 1 */
5136 if (AOP_SIZE (left) == 1 &&
5137 AOP_SIZE (right) == 1)
5139 genDivOneByte (left, right, result);
5143 /* should have been converted to function call */
5146 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5147 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5148 freeAsmop (result, NULL, ic, TRUE);
5151 /*-----------------------------------------------------------------*/
5152 /* genModbits :- modulus of bits */
5153 /*-----------------------------------------------------------------*/
5155 genModbits (operand * left,
5162 D(emitcode ("; genModbits",""));
5166 /* the result must be bit */
5167 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5168 l = aopGet (left, 0, FALSE, FALSE);
5172 emitcode ("div", "ab");
5173 emitcode ("mov", "a,b");
5174 emitcode ("rrc", "a");
5178 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
5181 /*-----------------------------------------------------------------*/
5182 /* genModOneByte : 8 bit modulus */
5183 /*-----------------------------------------------------------------*/
5185 genModOneByte (operand * left,
5189 bool lUnsigned, rUnsigned, pushedB;
5190 bool runtimeSign, compiletimeSign;
5194 D(emitcode ("; genModOneByte",""));
5196 size = AOP_SIZE (result) - 1;
5198 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
5199 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
5201 /* if right is a literal, check it for 2^n */
5202 if (AOP_TYPE(right) == AOP_LIT)
5204 unsigned char val = abs((int) operandLitValue(right));
5205 symbol *lbl2 = NULL;
5209 case 1: /* sometimes it makes sense (on tricky code and hardware)... */
5218 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5219 "modulus of unsigned char by 2^n literal shouldn't be processed here");
5220 /* because iCode should have been changed to genAnd */
5221 /* see file "SDCCopt.c", function "convertToFcall()" */
5223 MOVA (aopGet (left, 0, FALSE, FALSE));
5224 emitcode ("mov", "c,acc.7");
5225 emitcode ("anl", "a,#0x%02x", val - 1);
5226 lbl = newiTempLabel (NULL);
5227 emitcode ("jz", "%05d$", (lbl->key + 100));
5228 emitcode ("jnc", "%05d$", (lbl->key + 100));
5229 emitcode ("orl", "a,#0x%02x", 0xff ^ (val - 1));
5235 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5237 aopPut (result, "#0xff", offs2++, isOperandVolatile (result, FALSE));
5238 lbl2 = newiTempLabel (NULL);
5239 emitcode ("sjmp", "%05d$", (lbl2->key + 100));
5241 emitcode ("", "%05d$:", (lbl->key + 100));
5242 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5244 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5247 emitcode ("", "%05d$:", (lbl2->key + 100));
5258 /* signed or unsigned */
5259 if (lUnsigned && rUnsigned)
5261 /* unsigned is easy */
5262 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5263 MOVA (aopGet (left, 0, FALSE, FALSE));
5264 emitcode ("div", "ab");
5265 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5267 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5273 /* signed is a little bit more difficult */
5275 /* now sign adjust for both left & right */
5277 /* modulus: sign of the right operand has no influence on the result! */
5278 if (AOP_TYPE(right) == AOP_LIT)
5280 signed char val = (char) operandLitValue(right);
5282 if (!rUnsigned && val < 0)
5283 emitcode ("mov", "b,#0x%02x", -val);
5285 emitcode ("mov", "b,#0x%02x", (unsigned char) val);
5287 else /* not literal */
5290 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
5293 MOVA (aopGet (right, 0, FALSE, FALSE));
5294 lbl = newiTempLabel (NULL);
5295 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5296 emitcode ("cpl", "a"); /* 2's complement */
5297 emitcode ("inc", "a");
5298 emitcode ("", "%05d$:", (lbl->key + 100));
5299 emitcode ("mov", "b,a");
5303 /* let's see what's needed: */
5304 /* apply negative sign during runtime */
5305 runtimeSign = FALSE;
5306 /* negative sign from literals */
5307 compiletimeSign = FALSE;
5309 /* sign adjust left side */
5310 if (AOP_TYPE(left) == AOP_LIT)
5312 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
5314 if (!lUnsigned && val < 0)
5316 compiletimeSign = TRUE; /* set sign flag */
5317 emitcode ("mov", "a,#0x%02x", -val);
5320 emitcode ("mov", "a,#0x%02x", (unsigned char) val);
5322 else /* ! literal */
5324 MOVA (aopGet (left, 0, FALSE, FALSE));
5329 emitcode ("clr", "F0"); /* clear sign flag */
5331 lbl = newiTempLabel (NULL);
5332 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
5333 emitcode ("setb", "F0"); /* set sign flag */
5334 emitcode ("cpl", "a"); /* 2's complement */
5335 emitcode ("inc", "a");
5336 emitcode ("", "%05d$:", (lbl->key + 100));
5340 /* now the modulus */
5341 emitcode ("div", "ab");
5343 if (runtimeSign || compiletimeSign)
5345 emitcode ("mov", "a,b");
5346 lbl = newiTempLabel (NULL);
5348 emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
5349 emitcode ("cpl", "a"); /* 2's complement */
5350 emitcode ("inc", "a");
5351 emitcode ("", "%05d$:", (lbl->key + 100));
5353 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5356 /* msb is 0x00 or 0xff depending on the sign */
5359 emitcode ("mov", "c,F0");
5360 emitcode ("subb", "a,acc");
5362 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
5364 else /* compiletimeSign */
5366 aopPut (result, "#0xff", offset++, isOperandVolatile (result, FALSE));
5371 aopPut (result, "b", 0, isOperandVolatile (result, FALSE));
5373 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
5379 /*-----------------------------------------------------------------*/
5380 /* genMod - generates code for division */
5381 /*-----------------------------------------------------------------*/
5385 operand *left = IC_LEFT (ic);
5386 operand *right = IC_RIGHT (ic);
5387 operand *result = IC_RESULT (ic);
5389 D(emitcode ("; genMod",""));
5391 /* assign the asmops */
5392 aopOp (left, ic, FALSE);
5393 aopOp (right, ic, FALSE);
5394 aopOp (result, ic, TRUE);
5396 /* special cases first */
5398 if (AOP_TYPE (left) == AOP_CRY &&
5399 AOP_TYPE (right) == AOP_CRY)
5401 genModbits (left, right, result);
5405 /* if both are of size == 1 */
5406 if (AOP_SIZE (left) == 1 &&
5407 AOP_SIZE (right) == 1)
5409 genModOneByte (left, right, result);
5413 /* should have been converted to function call */
5417 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5418 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5419 freeAsmop (result, NULL, ic, TRUE);
5422 /*-----------------------------------------------------------------*/
5423 /* genIfxJump :- will create a jump depending on the ifx */
5424 /*-----------------------------------------------------------------*/
5426 genIfxJump (iCode * ic, char *jval, operand *left, operand *right, operand *result)
5429 symbol *tlbl = newiTempLabel (NULL);
5432 D(emitcode ("; genIfxJump",""));
5434 /* if true label then we jump if condition
5438 jlbl = IC_TRUE (ic);
5439 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5440 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5444 /* false label is present */
5445 jlbl = IC_FALSE (ic);
5446 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5447 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5449 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5450 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
5452 emitcode (inst, "%05d$", tlbl->key + 100);
5453 freeForBranchAsmop (result);
5454 freeForBranchAsmop (right);
5455 freeForBranchAsmop (left);
5456 emitcode ("ljmp", "%05d$", jlbl->key + 100);
5457 emitcode ("", "%05d$:", tlbl->key + 100);
5459 /* mark the icode as generated */
5463 /*-----------------------------------------------------------------*/
5464 /* genCmp :- greater or less than comparison */
5465 /*-----------------------------------------------------------------*/
5467 genCmp (operand * left, operand * right,
5468 operand * result, iCode * ifx, int sign, iCode *ic)
5470 int size, offset = 0;
5471 unsigned long lit = 0L;
5474 D(emitcode ("; genCmp",""));
5476 /* if left & right are bit variables */
5477 if (AOP_TYPE (left) == AOP_CRY &&
5478 AOP_TYPE (right) == AOP_CRY)
5480 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5481 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5485 /* subtract right from left if at the
5486 end the carry flag is set then we know that
5487 left is greater than right */
5488 size = max (AOP_SIZE (left), AOP_SIZE (right));
5490 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5491 if ((size == 1) && !sign &&
5492 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
5494 symbol *lbl = newiTempLabel (NULL);
5495 emitcode ("cjne", "%s,%s,%05d$",
5496 aopGet (left, offset, FALSE, FALSE),
5497 aopGet (right, offset, FALSE, FALSE),
5499 emitcode ("", "%05d$:", lbl->key + 100);
5503 if (AOP_TYPE (right) == AOP_LIT)
5505 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5506 /* optimize if(x < 0) or if(x >= 0) */
5515 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
5516 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5518 genIfxJump (ifx, "acc.7", left, right, result);
5519 freeAsmop (right, NULL, ic, TRUE);
5520 freeAsmop (left, NULL, ic, TRUE);
5525 emitcode ("rlc", "a");
5533 bool pushedB = FALSE;
5534 rightInB = aopGetUsesAcc(right, offset);
5538 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5540 MOVA (aopGet (left, offset, FALSE, FALSE));
5541 if (sign && size == 0)
5543 emitcode ("xrl", "a,#0x80");
5544 if (AOP_TYPE (right) == AOP_LIT)
5546 unsigned long lit = (unsigned long)
5547 floatFromVal (AOP (right)->aopu.aop_lit);
5548 emitcode ("subb", "a,#0x%02x",
5549 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5557 emitcode ("mov", "b,%s", aopGet (right, offset, FALSE, FALSE));
5559 emitcode ("xrl", "b,#0x80");
5560 emitcode ("subb", "a,b");
5566 emitcode ("subb", "a,b");
5568 emitcode ("subb", "a,%s", aopGet (right, offset, FALSE, FALSE));
5578 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5579 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5580 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5586 /* if the result is used in the next
5587 ifx conditional branch then generate
5588 code a little differently */
5590 genIfxJump (ifx, "c", NULL, NULL, result);
5593 /* leave the result in acc */
5597 /*-----------------------------------------------------------------*/
5598 /* genCmpGt :- greater than comparison */
5599 /*-----------------------------------------------------------------*/
5601 genCmpGt (iCode * ic, iCode * ifx)
5603 operand *left, *right, *result;
5604 sym_link *letype, *retype;
5607 D(emitcode ("; genCmpGt",""));
5609 left = IC_LEFT (ic);
5610 right = IC_RIGHT (ic);
5611 result = IC_RESULT (ic);
5613 letype = getSpec (operandType (left));
5614 retype = getSpec (operandType (right));
5615 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5616 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5617 /* assign the amsops */
5618 aopOp (left, ic, FALSE);
5619 aopOp (right, ic, FALSE);
5620 aopOp (result, ic, TRUE);
5622 genCmp (right, left, result, ifx, sign, ic);
5624 freeAsmop (result, NULL, ic, TRUE);
5627 /*-----------------------------------------------------------------*/
5628 /* genCmpLt - less than comparisons */
5629 /*-----------------------------------------------------------------*/
5631 genCmpLt (iCode * ic, iCode * ifx)
5633 operand *left, *right, *result;
5634 sym_link *letype, *retype;
5637 D(emitcode ("; genCmpLt",""));
5639 left = IC_LEFT (ic);
5640 right = IC_RIGHT (ic);
5641 result = IC_RESULT (ic);
5643 letype = getSpec (operandType (left));
5644 retype = getSpec (operandType (right));
5645 sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) ||
5646 (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype))));
5647 /* assign the amsops */
5648 aopOp (left, ic, FALSE);
5649 aopOp (right, ic, FALSE);
5650 aopOp (result, ic, TRUE);
5652 genCmp (left, right, result, ifx, sign, ic);
5654 freeAsmop (result, NULL, ic, TRUE);
5657 /*-----------------------------------------------------------------*/
5658 /* gencjneshort - compare and jump if not equal */
5659 /*-----------------------------------------------------------------*/
5661 gencjneshort (operand * left, operand * right, symbol * lbl)
5663 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5665 unsigned long lit = 0L;
5667 /* if the left side is a literal or
5668 if the right is in a pointer register and left
5670 if ((AOP_TYPE (left) == AOP_LIT) ||
5671 (AOP_TYPE (left) == AOP_IMMD) ||
5672 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5679 if (AOP_TYPE (right) == AOP_LIT)
5680 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5682 /* if the right side is a literal then anything goes */
5683 if (AOP_TYPE (right) == AOP_LIT &&
5684 AOP_TYPE (left) != AOP_DIR &&
5685 AOP_TYPE (left) != AOP_IMMD)
5689 emitcode ("cjne", "%s,%s,%05d$",
5690 aopGet (left, offset, FALSE, FALSE),
5691 aopGet (right, offset, FALSE, FALSE),
5697 /* if the right side is in a register or in direct space or
5698 if the left is a pointer register & right is not */
5699 else if (AOP_TYPE (right) == AOP_REG ||
5700 AOP_TYPE (right) == AOP_DIR ||
5701 AOP_TYPE (right) == AOP_LIT ||
5702 AOP_TYPE (right) == AOP_IMMD ||
5703 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5704 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5708 MOVA (aopGet (left, offset, FALSE, FALSE));
5709 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5710 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5711 emitcode ("jnz", "%05d$", lbl->key + 100);
5713 emitcode ("cjne", "a,%s,%05d$",
5714 aopGet (right, offset, FALSE, TRUE),
5721 /* right is a pointer reg need both a & b */
5725 //if B in use: push B; mov B,left; mov A,right; clrc; subb A,B; pop B; jnz
5726 wassertl(!BINUSE, "B was in use");
5727 l = aopGet (left, offset, FALSE, FALSE);
5728 if (strcmp (l, "b"))
5729 emitcode ("mov", "b,%s", l);
5730 MOVA (aopGet (right, offset, FALSE, FALSE));
5731 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
5737 /*-----------------------------------------------------------------*/
5738 /* gencjne - compare and jump if not equal */
5739 /*-----------------------------------------------------------------*/
5741 gencjne (operand * left, operand * right, symbol * lbl)
5743 symbol *tlbl = newiTempLabel (NULL);
5745 gencjneshort (left, right, lbl);
5747 emitcode ("mov", "a,%s", one);
5748 emitcode ("sjmp", "%05d$", tlbl->key + 100);
5749 emitcode ("", "%05d$:", lbl->key + 100);
5750 emitcode ("clr", "a");
5751 emitcode ("", "%05d$:", tlbl->key + 100);
5754 /*-----------------------------------------------------------------*/
5755 /* genCmpEq - generates code for equal to */
5756 /*-----------------------------------------------------------------*/
5758 genCmpEq (iCode * ic, iCode * ifx)
5760 operand *left, *right, *result;
5762 D(emitcode ("; genCmpEq",""));
5764 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5765 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5766 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5768 /* if literal, literal on the right or
5769 if the right is in a pointer register and left
5771 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5772 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5774 operand *t = IC_RIGHT (ic);
5775 IC_RIGHT (ic) = IC_LEFT (ic);
5779 if (ifx && !AOP_SIZE (result))
5782 /* if they are both bit variables */
5783 if (AOP_TYPE (left) == AOP_CRY &&
5784 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5786 if (AOP_TYPE (right) == AOP_LIT)
5788 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5791 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5792 emitcode ("cpl", "c");
5796 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5800 emitcode ("clr", "c");
5802 /* AOP_TYPE(right) == AOP_CRY */
5806 symbol *lbl = newiTempLabel (NULL);
5807 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5808 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5809 emitcode ("cpl", "c");
5810 emitcode ("", "%05d$:", (lbl->key + 100));
5812 /* if true label then we jump if condition
5814 tlbl = newiTempLabel (NULL);
5817 emitcode ("jnc", "%05d$", tlbl->key + 100);
5818 freeForBranchAsmop (result);
5819 freeForBranchAsmop (right);
5820 freeForBranchAsmop (left);
5821 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5825 emitcode ("jc", "%05d$", tlbl->key + 100);
5826 freeForBranchAsmop (result);
5827 freeForBranchAsmop (right);
5828 freeForBranchAsmop (left);
5829 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5831 emitcode ("", "%05d$:", tlbl->key + 100);
5835 tlbl = newiTempLabel (NULL);
5836 gencjneshort (left, right, tlbl);
5839 freeForBranchAsmop (result);
5840 freeForBranchAsmop (right);
5841 freeForBranchAsmop (left);
5842 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
5843 emitcode ("", "%05d$:", tlbl->key + 100);
5847 symbol *lbl = newiTempLabel (NULL);
5848 emitcode ("sjmp", "%05d$", lbl->key + 100);
5849 emitcode ("", "%05d$:", tlbl->key + 100);
5850 freeForBranchAsmop (result);
5851 freeForBranchAsmop (right);
5852 freeForBranchAsmop (left);
5853 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
5854 emitcode ("", "%05d$:", lbl->key + 100);
5857 /* mark the icode as generated */
5862 /* if they are both bit variables */
5863 if (AOP_TYPE (left) == AOP_CRY &&
5864 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5866 if (AOP_TYPE (right) == AOP_LIT)
5868 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5871 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5872 emitcode ("cpl", "c");
5876 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5880 emitcode ("clr", "c");
5882 /* AOP_TYPE(right) == AOP_CRY */
5886 symbol *lbl = newiTempLabel (NULL);
5887 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5888 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5889 emitcode ("cpl", "c");
5890 emitcode ("", "%05d$:", (lbl->key + 100));
5893 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5900 genIfxJump (ifx, "c", left, right, result);
5903 /* if the result is used in an arithmetic operation
5904 then put the result in place */
5909 gencjne (left, right, newiTempLabel (NULL));
5910 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5912 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
5917 genIfxJump (ifx, "a", left, right, result);
5920 /* if the result is used in an arithmetic operation
5921 then put the result in place */
5922 if (AOP_TYPE (result) != AOP_CRY)
5924 /* leave the result in acc */
5928 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5929 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5930 freeAsmop (result, NULL, ic, TRUE);
5933 /*-----------------------------------------------------------------*/
5934 /* ifxForOp - returns the icode containing the ifx for operand */
5935 /*-----------------------------------------------------------------*/
5937 ifxForOp (operand * op, iCode * ic)
5939 /* if true symbol then needs to be assigned */
5940 if (IS_TRUE_SYMOP (op))
5943 /* if this has register type condition and
5944 the next instruction is ifx with the same operand
5945 and live to of the operand is upto the ifx only then */
5947 ic->next->op == IFX &&
5948 IC_COND (ic->next)->key == op->key &&
5949 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5955 /*-----------------------------------------------------------------*/
5956 /* hasInc - operand is incremented before any other use */
5957 /*-----------------------------------------------------------------*/
5959 hasInc (operand *op, iCode *ic,int osize)
5961 sym_link *type = operandType(op);
5962 sym_link *retype = getSpec (type);
5963 iCode *lic = ic->next;
5966 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5967 if (!IS_SYMOP(op)) return NULL;
5969 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5970 if (IS_AGGREGATE(type->next)) return NULL;
5971 if (osize != (isize = getSize(type->next))) return NULL;
5974 /* if operand of the form op = op + <sizeof *op> */
5975 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5976 isOperandEqual(IC_RESULT(lic),op) &&
5977 isOperandLiteral(IC_RIGHT(lic)) &&
5978 operandLitValue(IC_RIGHT(lic)) == isize) {
5981 /* if the operand used or deffed */
5982 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
5985 /* if GOTO or IFX */
5986 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5992 /*-----------------------------------------------------------------*/
5993 /* genAndOp - for && operation */
5994 /*-----------------------------------------------------------------*/
5996 genAndOp (iCode * ic)
5998 operand *left, *right, *result;
6001 D(emitcode ("; genAndOp",""));
6003 /* note here that && operations that are in an
6004 if statement are taken away by backPatchLabels
6005 only those used in arthmetic operations remain */
6006 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6007 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6008 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6010 /* if both are bit variables */
6011 if (AOP_TYPE (left) == AOP_CRY &&
6012 AOP_TYPE (right) == AOP_CRY)
6014 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6015 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
6020 tlbl = newiTempLabel (NULL);
6022 emitcode ("jz", "%05d$", tlbl->key + 100);
6024 emitcode ("", "%05d$:", tlbl->key + 100);
6028 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6029 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6030 freeAsmop (result, NULL, ic, TRUE);
6034 /*-----------------------------------------------------------------*/
6035 /* genOrOp - for || operation */
6036 /*-----------------------------------------------------------------*/
6038 genOrOp (iCode * ic)
6040 operand *left, *right, *result;
6043 D(emitcode ("; genOrOp",""));
6045 /* note here that || operations that are in an
6046 if statement are taken away by backPatchLabels
6047 only those used in arthmetic operations remain */
6048 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6049 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6050 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
6052 /* if both are bit variables */
6053 if (AOP_TYPE (left) == AOP_CRY &&
6054 AOP_TYPE (right) == AOP_CRY)
6056 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6057 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6062 tlbl = newiTempLabel (NULL);
6064 emitcode ("jnz", "%05d$", tlbl->key + 100);
6066 emitcode ("", "%05d$:", tlbl->key + 100);
6070 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6071 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6072 freeAsmop (result, NULL, ic, TRUE);
6075 /*-----------------------------------------------------------------*/
6076 /* isLiteralBit - test if lit == 2^n */
6077 /*-----------------------------------------------------------------*/
6079 isLiteralBit (unsigned long lit)
6081 unsigned long pw[32] =
6082 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6083 0x100L, 0x200L, 0x400L, 0x800L,
6084 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6085 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6086 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6087 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6088 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6091 for (idx = 0; idx < 32; idx++)
6097 /*-----------------------------------------------------------------*/
6098 /* continueIfTrue - */
6099 /*-----------------------------------------------------------------*/
6101 continueIfTrue (iCode * ic)
6104 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6108 /*-----------------------------------------------------------------*/
6110 /*-----------------------------------------------------------------*/
6112 jumpIfTrue (iCode * ic)
6115 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6119 /*-----------------------------------------------------------------*/
6120 /* jmpTrueOrFalse - */
6121 /*-----------------------------------------------------------------*/
6123 jmpTrueOrFalse (iCode * ic, symbol * tlbl, operand *left, operand *right, operand *result)
6125 // ugly but optimized by peephole
6128 symbol *nlbl = newiTempLabel (NULL);
6129 emitcode ("sjmp", "%05d$", nlbl->key + 100);
6130 emitcode ("", "%05d$:", tlbl->key + 100);
6131 freeForBranchAsmop (result);
6132 freeForBranchAsmop (right);
6133 freeForBranchAsmop (left);
6134 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
6135 emitcode ("", "%05d$:", nlbl->key + 100);
6139 freeForBranchAsmop (result);
6140 freeForBranchAsmop (right);
6141 freeForBranchAsmop (left);
6142 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
6143 emitcode ("", "%05d$:", tlbl->key + 100);
6148 /*-----------------------------------------------------------------*/
6149 /* genAnd - code for and */
6150 /*-----------------------------------------------------------------*/
6152 genAnd (iCode * ic, iCode * ifx)
6154 operand *left, *right, *result;
6155 int size, offset = 0;
6156 unsigned long lit = 0L;
6160 D(emitcode ("; genAnd",""));
6162 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6163 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6164 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6167 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6169 AOP_TYPE (left), AOP_TYPE (right));
6170 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6172 AOP_SIZE (left), AOP_SIZE (right));
6175 /* if left is a literal & right is not then exchange them */
6176 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6177 AOP_NEEDSACC (left))
6179 operand *tmp = right;
6184 /* if result = right then exchange left and right */
6185 if (sameRegs (AOP (result), AOP (right)))
6187 operand *tmp = right;
6192 /* if right is bit then exchange them */
6193 if (AOP_TYPE (right) == AOP_CRY &&
6194 AOP_TYPE (left) != AOP_CRY)
6196 operand *tmp = right;
6200 if (AOP_TYPE (right) == AOP_LIT)
6201 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6203 size = AOP_SIZE (result);
6206 // result = bit & yy;
6207 if (AOP_TYPE (left) == AOP_CRY)
6209 // c = bit & literal;
6210 if (AOP_TYPE (right) == AOP_LIT)
6214 if (size && sameRegs (AOP (result), AOP (left)))
6217 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6222 if (size && (AOP_TYPE (result) == AOP_CRY))
6224 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6227 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6232 emitcode ("clr", "c");
6237 if (AOP_TYPE (right) == AOP_CRY)
6240 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6241 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6246 MOVA (aopGet (right, 0, FALSE, FALSE));
6248 emitcode ("rrc", "a");
6249 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6257 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6258 genIfxJump (ifx, "c", left, right, result);
6262 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6263 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6264 if ((AOP_TYPE (right) == AOP_LIT) &&
6265 (AOP_TYPE (result) == AOP_CRY) &&
6266 (AOP_TYPE (left) != AOP_CRY))
6268 int posbit = isLiteralBit (lit);
6273 MOVA (aopGet (left, posbit >> 3, FALSE, FALSE));
6277 switch (posbit & 0x07)
6279 case 0: emitcode ("rrc", "a");
6281 case 7: emitcode ("rlc", "a");
6283 default: emitcode ("mov", "c,acc.%d", posbit & 0x07);
6292 SNPRINTF (buffer, sizeof(buffer),
6293 "acc.%d", posbit & 0x07);
6294 genIfxJump (ifx, buffer, left, right, result);
6297 {// what is this case? just found it in ds390/gen.c
6298 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6305 symbol *tlbl = newiTempLabel (NULL);
6306 int sizel = AOP_SIZE (left);
6308 emitcode ("setb", "c");
6311 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6313 MOVA (aopGet (left, offset, FALSE, FALSE));
6315 if ((posbit = isLiteralBit (bytelit)) != 0)
6316 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
6319 if (bytelit != 0x0FFL)
6320 emitcode ("anl", "a,%s",
6321 aopGet (right, offset, FALSE, TRUE));
6322 emitcode ("jnz", "%05d$", tlbl->key + 100);
6327 // bit = left & literal
6330 emitcode ("clr", "c");
6331 emitcode ("", "%05d$:", tlbl->key + 100);
6333 // if(left & literal)
6337 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6339 emitcode ("", "%05d$:", tlbl->key + 100);
6347 /* if left is same as result */
6348 if (sameRegs (AOP (result), AOP (left)))
6350 for (; size--; offset++)
6352 if (AOP_TYPE (right) == AOP_LIT)
6354 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6355 if (bytelit == 0x0FF)
6357 /* dummy read of volatile operand */
6358 if (isOperandVolatile (left, FALSE))
6359 MOVA (aopGet (left, offset, FALSE, FALSE));
6363 else if (bytelit == 0)
6365 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6367 else if (IS_AOP_PREG (result))
6369 MOVA (aopGet (left, offset, FALSE, TRUE));
6370 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6371 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6374 emitcode ("anl", "%s,%s",
6375 aopGet (left, offset, FALSE, TRUE),
6376 aopGet (right, offset, FALSE, FALSE));
6380 if (AOP_TYPE (left) == AOP_ACC && offset == 0)
6382 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6386 MOVA (aopGet (right, offset, FALSE, FALSE));
6387 if (IS_AOP_PREG (result))
6389 emitcode ("anl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6390 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6393 emitcode ("anl", "%s,a",
6394 aopGet (left, offset, FALSE, TRUE));
6401 // left & result in different registers
6402 if (AOP_TYPE (result) == AOP_CRY)
6405 // if(size), result in bit
6406 // if(!size && ifx), conditional oper: if(left & right)
6407 symbol *tlbl = newiTempLabel (NULL);
6408 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6410 emitcode ("setb", "c");
6413 if ((AOP_TYPE(right)==AOP_REG || IS_AOP_PREG(right) || AOP_TYPE(right)==AOP_DIR)
6414 && AOP_TYPE(left)==AOP_ACC)
6417 emitcode("mov", "a,b");
6418 emitcode ("anl", "a,%s",
6419 aopGet (right, offset, FALSE, FALSE));
6421 if (AOP_TYPE(left)==AOP_ACC)
6425 bool pushedB = pushB ();
6426 emitcode("mov", "b,a");
6427 MOVA (aopGet (right, offset, FALSE, FALSE));
6428 emitcode("anl", "a,b");
6433 MOVA (aopGet (right, offset, FALSE, FALSE));
6434 emitcode("anl", "a,b");
6437 MOVA (aopGet (right, offset, FALSE, FALSE));
6438 emitcode ("anl", "a,%s",
6439 aopGet (left, offset, FALSE, FALSE));
6442 emitcode ("jnz", "%05d$", tlbl->key + 100);
6448 emitcode ("", "%05d$:", tlbl->key + 100);
6452 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6454 emitcode ("", "%05d$:", tlbl->key + 100);
6458 for (; (size--); offset++)
6461 // result = left & right
6462 if (AOP_TYPE (right) == AOP_LIT)
6464 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6465 if (bytelit == 0x0FF)
6468 aopGet (left, offset, FALSE, FALSE),
6470 isOperandVolatile (result, FALSE));
6473 else if (bytelit == 0)
6475 /* dummy read of volatile operand */
6476 if (isOperandVolatile (left, FALSE))
6477 MOVA (aopGet (left, offset, FALSE, FALSE));
6478 aopPut (result, zero, offset, isOperandVolatile (result, FALSE));
6481 else if (AOP_TYPE (left) == AOP_ACC)
6485 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6486 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6491 emitcode ("anl", "b,%s", aopGet (right, offset, FALSE, FALSE));
6492 aopPut (result, "b", offset, isOperandVolatile (result, FALSE));
6497 // faster than result <- left, anl result,right
6498 // and better if result is SFR
6499 if (AOP_TYPE (left) == AOP_ACC)
6502 emitcode("mov", "a,b");
6503 emitcode ("anl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6507 MOVA (aopGet (right, offset, FALSE, FALSE));
6508 emitcode ("anl", "a,%s",
6509 aopGet (left, offset, FALSE, FALSE));
6511 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6517 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6518 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6519 freeAsmop (result, NULL, ic, TRUE);
6522 /*-----------------------------------------------------------------*/
6523 /* genOr - code for or */
6524 /*-----------------------------------------------------------------*/
6526 genOr (iCode * ic, iCode * ifx)
6528 operand *left, *right, *result;
6529 int size, offset = 0;
6530 unsigned long lit = 0L;
6533 D(emitcode ("; genOr",""));
6535 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6536 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6537 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6540 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6542 AOP_TYPE (left), AOP_TYPE (right));
6543 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6545 AOP_SIZE (left), AOP_SIZE (right));
6548 /* if left is a literal & right is not then exchange them */
6549 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6550 AOP_NEEDSACC (left))
6552 operand *tmp = right;
6557 /* if result = right then exchange them */
6558 if (sameRegs (AOP (result), AOP (right)))
6560 operand *tmp = right;
6565 /* if right is bit then exchange them */
6566 if (AOP_TYPE (right) == AOP_CRY &&
6567 AOP_TYPE (left) != AOP_CRY)
6569 operand *tmp = right;
6573 if (AOP_TYPE (right) == AOP_LIT)
6574 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6576 size = AOP_SIZE (result);
6580 if (AOP_TYPE (left) == AOP_CRY)
6582 if (AOP_TYPE (right) == AOP_LIT)
6584 // c = bit | literal;
6587 // lit != 0 => result = 1
6588 if (AOP_TYPE (result) == AOP_CRY)
6591 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6593 continueIfTrue (ifx);
6596 emitcode ("setb", "c");
6600 // lit == 0 => result = left
6601 if (size && sameRegs (AOP (result), AOP (left)))
6603 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6608 if (AOP_TYPE (right) == AOP_CRY)
6611 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6612 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6617 symbol *tlbl = newiTempLabel (NULL);
6618 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6619 emitcode ("setb", "c");
6620 emitcode ("jb", "%s,%05d$",
6621 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6623 emitcode ("jnz", "%05d$", tlbl->key + 100);
6624 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6626 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6632 emitcode ("", "%05d$:", tlbl->key + 100);
6641 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6642 genIfxJump (ifx, "c", left, right, result);
6646 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6647 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6648 if ((AOP_TYPE (right) == AOP_LIT) &&
6649 (AOP_TYPE (result) == AOP_CRY) &&
6650 (AOP_TYPE (left) != AOP_CRY))
6656 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6658 continueIfTrue (ifx);
6663 // lit = 0, result = boolean(left)
6665 emitcode ("setb", "c");
6669 symbol *tlbl = newiTempLabel (NULL);
6670 emitcode ("jnz", "%05d$", tlbl->key + 100);
6672 emitcode ("", "%05d$:", tlbl->key + 100);
6676 genIfxJump (ifx, "a", left, right, result);
6684 /* if left is same as result */
6685 if (sameRegs (AOP (result), AOP (left)))
6687 for (; size--; offset++)
6689 if (AOP_TYPE (right) == AOP_LIT)
6691 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6694 /* dummy read of volatile operand */
6695 if (isOperandVolatile (left, FALSE))
6696 MOVA (aopGet (left, offset, FALSE, FALSE));
6700 else if (bytelit == 0x0FF)
6702 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6704 else if (IS_AOP_PREG (left))
6706 MOVA (aopGet (left, offset, FALSE, TRUE));
6707 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6708 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6712 emitcode ("orl", "%s,%s",
6713 aopGet (left, offset, FALSE, TRUE),
6714 aopGet (right, offset, FALSE, FALSE));
6719 if (AOP_TYPE (left) == AOP_ACC)
6722 emitcode("mov", "a,b");
6723 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6727 MOVA (aopGet (right, offset, FALSE, FALSE));
6728 if (IS_AOP_PREG (left))
6730 emitcode ("orl", "a,%s", aopGet (left, offset, FALSE, TRUE));
6731 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6735 emitcode ("orl", "%s,a",
6736 aopGet (left, offset, FALSE, TRUE));
6744 // left & result in different registers
6745 if (AOP_TYPE (result) == AOP_CRY)
6748 // if(size), result in bit
6749 // if(!size && ifx), conditional oper: if(left | right)
6750 symbol *tlbl = newiTempLabel (NULL);
6751 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6753 emitcode ("setb", "c");
6756 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6758 emitcode("mov", "a,b");
6759 emitcode ("orl", "a,%s",
6760 aopGet (right, offset, FALSE, FALSE));
6762 MOVA (aopGet (right, offset, FALSE, FALSE));
6763 emitcode ("orl", "a,%s",
6764 aopGet (left, offset, FALSE, FALSE));
6766 emitcode ("jnz", "%05d$", tlbl->key + 100);
6772 emitcode ("", "%05d$:", tlbl->key + 100);
6776 jmpTrueOrFalse (ifx, tlbl, left, right, result);
6778 emitcode ("", "%05d$:", tlbl->key + 100);
6782 for (; (size--); offset++)
6785 // result = left | right
6786 if (AOP_TYPE (right) == AOP_LIT)
6788 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6792 aopGet (left, offset, FALSE, FALSE),
6794 isOperandVolatile (result, FALSE));
6797 else if (bytelit == 0x0FF)
6799 /* dummy read of volatile operand */
6800 if (isOperandVolatile (left, FALSE))
6801 MOVA (aopGet (left, offset, FALSE, FALSE));
6802 aopPut (result, "#0xFF", offset, isOperandVolatile (result, FALSE));
6806 // faster than result <- left, anl result,right
6807 // and better if result is SFR
6808 if (AOP_TYPE (left) == AOP_ACC)
6811 emitcode("mov", "a,b");
6812 emitcode ("orl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6816 MOVA (aopGet (right, offset, FALSE, FALSE));
6817 emitcode ("orl", "a,%s",
6818 aopGet (left, offset, FALSE, FALSE));
6820 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
6826 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6827 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6828 freeAsmop (result, NULL, ic, TRUE);
6831 /*-----------------------------------------------------------------*/
6832 /* genXor - code for xclusive or */
6833 /*-----------------------------------------------------------------*/
6835 genXor (iCode * ic, iCode * ifx)
6837 operand *left, *right, *result;
6838 int size, offset = 0;
6839 unsigned long lit = 0L;
6842 D(emitcode ("; genXor",""));
6844 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
6845 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
6846 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
6849 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6851 AOP_TYPE (left), AOP_TYPE (right));
6852 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6854 AOP_SIZE (left), AOP_SIZE (right));
6857 /* if left is a literal & right is not ||
6858 if left needs acc & right does not */
6859 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
6860 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
6862 operand *tmp = right;
6867 /* if result = right then exchange them */
6868 if (sameRegs (AOP (result), AOP (right)))
6870 operand *tmp = right;
6875 /* if right is bit then exchange them */
6876 if (AOP_TYPE (right) == AOP_CRY &&
6877 AOP_TYPE (left) != AOP_CRY)
6879 operand *tmp = right;
6883 if (AOP_TYPE (right) == AOP_LIT)
6884 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6886 size = AOP_SIZE (result);
6890 if (AOP_TYPE (left) == AOP_CRY)
6892 if (AOP_TYPE (right) == AOP_LIT)
6894 // c = bit & literal;
6897 // lit>>1 != 0 => result = 1
6898 if (AOP_TYPE (result) == AOP_CRY)
6901 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6903 continueIfTrue (ifx);
6906 emitcode ("setb", "c");
6913 // lit == 0, result = left
6914 if (size && sameRegs (AOP (result), AOP (left)))
6916 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6920 // lit == 1, result = not(left)
6921 if (size && sameRegs (AOP (result), AOP (left)))
6923 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6928 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6929 emitcode ("cpl", "c");
6938 symbol *tlbl = newiTempLabel (NULL);
6939 if (AOP_TYPE (right) == AOP_CRY)
6942 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6946 int sizer = AOP_SIZE (right);
6948 // if val>>1 != 0, result = 1
6949 emitcode ("setb", "c");
6952 MOVA (aopGet (right, sizer - 1, FALSE, FALSE));
6954 // test the msb of the lsb
6955 emitcode ("anl", "a,#0xfe");
6956 emitcode ("jnz", "%05d$", tlbl->key + 100);
6960 emitcode ("rrc", "a");
6962 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6963 emitcode ("cpl", "c");
6964 emitcode ("", "%05d$:", (tlbl->key + 100));
6971 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6972 genIfxJump (ifx, "c", left, right, result);
6976 /* if left is same as result */
6977 if (sameRegs (AOP (result), AOP (left)))
6979 for (; size--; offset++)
6981 if (AOP_TYPE (right) == AOP_LIT)
6983 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
6986 /* dummy read of volatile operand */
6987 if (isOperandVolatile (left, FALSE))
6988 MOVA (aopGet (left, offset, FALSE, FALSE));
6992 else if (IS_AOP_PREG (left))
6994 MOVA (aopGet (left, offset, FALSE, TRUE));
6995 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
6996 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7000 emitcode ("xrl", "%s,%s",
7001 aopGet (left, offset, FALSE, TRUE),
7002 aopGet (right, offset, FALSE, FALSE));
7007 if (AOP_TYPE (left) == AOP_ACC)
7010 emitcode("mov", "a,b");
7011 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7015 MOVA (aopGet (right, offset, FALSE, FALSE));
7016 if (IS_AOP_PREG (left))
7018 emitcode ("xrl", "a,%s", aopGet (left, offset, FALSE, TRUE));
7019 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7022 emitcode ("xrl", "%s,a",
7023 aopGet (left, offset, FALSE, TRUE));
7030 // left & result in different registers
7031 if (AOP_TYPE (result) == AOP_CRY)
7034 // if(size), result in bit
7035 // if(!size && ifx), conditional oper: if(left ^ right)
7036 symbol *tlbl = newiTempLabel (NULL);
7037 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7039 emitcode ("setb", "c");
7042 if ((AOP_TYPE (right) == AOP_LIT) &&
7043 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7045 MOVA (aopGet (left, offset, FALSE, FALSE));
7049 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7051 emitcode("mov", "a,b");
7052 emitcode ("xrl", "a,%s",
7053 aopGet (right, offset, FALSE, FALSE));
7055 MOVA (aopGet (right, offset, FALSE, FALSE));
7056 emitcode ("xrl", "a,%s",
7057 aopGet (left, offset, FALSE, FALSE));
7060 emitcode ("jnz", "%05d$", tlbl->key + 100);
7066 emitcode ("", "%05d$:", tlbl->key + 100);
7070 jmpTrueOrFalse (ifx, tlbl, left, right, result);
7074 for (; (size--); offset++)
7077 // result = left & right
7078 if (AOP_TYPE (right) == AOP_LIT)
7080 bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL);
7084 aopGet (left, offset, FALSE, FALSE),
7086 isOperandVolatile (result, FALSE));
7090 // faster than result <- left, anl result,right
7091 // and better if result is SFR
7092 if (AOP_TYPE (left) == AOP_ACC)
7095 emitcode("mov", "a,b");
7096 emitcode ("xrl", "a,%s", aopGet (right, offset, FALSE, FALSE));
7100 MOVA (aopGet (right, offset, FALSE, FALSE));
7101 emitcode ("xrl", "a,%s",
7102 aopGet (left, offset, FALSE, TRUE));
7104 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
7110 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7111 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7112 freeAsmop (result, NULL, ic, TRUE);
7115 /*-----------------------------------------------------------------*/
7116 /* genInline - write the inline code out */
7117 /*-----------------------------------------------------------------*/
7119 genInline (iCode * ic)
7121 char *buffer, *bp, *bp1;
7123 D(emitcode ("; genInline",""));
7125 _G.inLine += (!options.asmpeep);
7127 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7128 strcpy (buffer, IC_INLINE (ic));
7130 /* emit each line as a code */
7141 /* Add \n for labels, not dirs such as c:\mydir */
7142 if ( (*bp == ':') && (isspace((unsigned char)bp[1])) )
7156 /* emitcode("",buffer); */
7157 _G.inLine -= (!options.asmpeep);
7160 /*-----------------------------------------------------------------*/
7161 /* genRRC - rotate right with carry */
7162 /*-----------------------------------------------------------------*/
7166 operand *left, *result;
7167 int size, offset = 0;
7170 D(emitcode ("; genRRC",""));
7172 /* rotate right with carry */
7173 left = IC_LEFT (ic);
7174 result = IC_RESULT (ic);
7175 aopOp (left, ic, FALSE);
7176 aopOp (result, ic, FALSE);
7178 /* move it to the result */
7179 size = AOP_SIZE (result);
7181 if (size == 1) { /* special case for 1 byte */
7182 l = aopGet (left, offset, FALSE, FALSE);
7184 emitcode ("rr", "a");
7187 /* no need to clear carry, bit7 will be written later */
7190 l = aopGet (left, offset, FALSE, FALSE);
7192 emitcode ("rrc", "a");
7193 if (AOP_SIZE (result) > 1)
7194 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
7196 /* now we need to put the carry into the
7197 highest order byte of the result */
7198 if (AOP_SIZE (result) > 1)
7200 l = aopGet (result, AOP_SIZE (result) - 1, FALSE, FALSE);
7203 emitcode ("mov", "acc.7,c");
7205 aopPut (result, "a", AOP_SIZE (result) - 1, isOperandVolatile (result, FALSE));
7206 freeAsmop (left, NULL, ic, TRUE);
7207 freeAsmop (result, NULL, ic, TRUE);
7210 /*-----------------------------------------------------------------*/
7211 /* genRLC - generate code for rotate left with carry */
7212 /*-----------------------------------------------------------------*/
7216 operand *left, *result;
7217 int size, offset = 0;
7220 D(emitcode ("; genRLC",""));
7222 /* rotate right with carry */
7223 left = IC_LEFT (ic);
7224 result = IC_RESULT (ic);
7225 aopOp (left, ic, FALSE);
7226 aopOp (result, ic, FALSE);
7228 /* move it to the result */
7229 size = AOP_SIZE (result);
7233 l = aopGet (left, offset, FALSE, FALSE);
7235 if (size == 0) { /* special case for 1 byte */
7239 emitcode("rlc","a"); /* bit0 will be written later */
7240 if (AOP_SIZE (result) > 1)
7241 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7244 l = aopGet (left, offset, FALSE, FALSE);
7246 emitcode ("rlc", "a");
7247 if (AOP_SIZE (result) > 1)
7248 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
7251 /* now we need to put the carry into the
7252 highest order byte of the result */
7253 if (AOP_SIZE (result) > 1)
7255 l = aopGet (result, 0, FALSE, FALSE);
7258 emitcode ("mov", "acc.0,c");
7260 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7261 freeAsmop (left, NULL, ic, TRUE);
7262 freeAsmop (result, NULL, ic, TRUE);
7265 /*-----------------------------------------------------------------*/
7266 /* genGetHbit - generates code get highest order bit */
7267 /*-----------------------------------------------------------------*/
7269 genGetHbit (iCode * ic)
7271 operand *left, *result;
7273 D(emitcode ("; genGetHbit",""));
7275 left = IC_LEFT (ic);
7276 result = IC_RESULT (ic);
7277 aopOp (left, ic, FALSE);
7278 aopOp (result, ic, FALSE);
7280 /* get the highest order byte into a */
7281 MOVA (aopGet (left, AOP_SIZE (left) - 1, FALSE, FALSE));
7282 if (AOP_TYPE (result) == AOP_CRY)
7284 emitcode ("rlc", "a");
7289 emitcode ("rl", "a");
7290 emitcode ("anl", "a,#0x01");
7295 freeAsmop (left, NULL, ic, TRUE);
7296 freeAsmop (result, NULL, ic, TRUE);
7299 /*-----------------------------------------------------------------*/
7300 /* genGetAbit - generates code get a single bit */
7301 /*-----------------------------------------------------------------*/
7303 genGetAbit (iCode * ic)
7305 operand *left, *right, *result;
7308 D(emitcode ("; genGetAbit",""));
7310 left = IC_LEFT (ic);
7311 right = IC_RIGHT (ic);
7312 result = IC_RESULT (ic);
7313 aopOp (left, ic, FALSE);
7314 aopOp (right, ic, FALSE);
7315 aopOp (result, ic, FALSE);
7317 shCount = (int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
7319 /* get the needed byte into a */
7320 MOVA (aopGet (left, shCount / 8, FALSE, FALSE));
7322 if (AOP_TYPE (result) == AOP_CRY)
7325 emitcode ("rlc", "a");
7326 else if ((shCount) == 0)
7327 emitcode ("rrc", "a");
7329 emitcode ("mov", "c,acc[%d]", shCount);
7337 emitcode ("rr", "a");
7340 emitcode ("rr", "a");
7343 emitcode ("anl", "a,#0x01");
7347 emitcode ("mov", "c,acc[%d]", shCount);
7348 emitcode ("clr", "a");
7349 emitcode ("rlc", "a");
7352 emitcode ("swap", "a");
7353 emitcode ("anl", "a,#0x01");
7356 emitcode ("rl", "a");
7359 emitcode ("rl", "a");
7360 emitcode ("anl", "a,#0x01");
7366 freeAsmop (left, NULL, ic, TRUE);
7367 freeAsmop (right, NULL, ic, TRUE);
7368 freeAsmop (result, NULL, ic, TRUE);
7371 /*-----------------------------------------------------------------*/
7372 /* genGetByte - generates code get a single byte */
7373 /*-----------------------------------------------------------------*/
7375 genGetByte (iCode * ic)
7377 operand *left, *right, *result;
7380 D(emitcode ("; genGetByte",""));
7382 left = IC_LEFT (ic);
7383 right = IC_RIGHT (ic);
7384 result = IC_RESULT (ic);
7385 aopOp (left, ic, FALSE);
7386 aopOp (right, ic, FALSE);
7387 aopOp (result, ic, FALSE);
7389 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7391 aopGet (left, offset, FALSE, FALSE),
7393 isOperandVolatile (result, FALSE));
7395 freeAsmop (left, NULL, ic, TRUE);
7396 freeAsmop (right, NULL, ic, TRUE);
7397 freeAsmop (result, NULL, ic, TRUE);
7400 /*-----------------------------------------------------------------*/
7401 /* genGetWord - generates code get two bytes */
7402 /*-----------------------------------------------------------------*/
7404 genGetWord (iCode * ic)
7406 operand *left, *right, *result;
7409 D(emitcode ("; genGetWord",""));
7411 left = IC_LEFT (ic);
7412 right = IC_RIGHT (ic);
7413 result = IC_RESULT (ic);
7414 aopOp (left, ic, FALSE);
7415 aopOp (right, ic, FALSE);
7416 aopOp (result, ic, FALSE);
7418 offset = (int)floatFromVal (AOP (right)->aopu.aop_lit) / 8;
7420 aopGet (left, offset, FALSE, FALSE),
7422 isOperandVolatile (result, FALSE));
7424 aopGet (left, offset+1, FALSE, FALSE),
7426 isOperandVolatile (result, FALSE));
7428 freeAsmop (left, NULL, ic, TRUE);
7429 freeAsmop (right, NULL, ic, TRUE);
7430 freeAsmop (result, NULL, ic, TRUE);
7433 /*-----------------------------------------------------------------*/
7434 /* genSwap - generates code to swap nibbles or bytes */
7435 /*-----------------------------------------------------------------*/
7437 genSwap (iCode * ic)
7439 operand *left, *result;
7441 D(emitcode ("; genSwap",""));
7443 left = IC_LEFT (ic);
7444 result = IC_RESULT (ic);
7445 aopOp (left, ic, FALSE);
7446 aopOp (result, ic, FALSE);
7448 switch (AOP_SIZE (left))
7450 case 1: /* swap nibbles in byte */
7451 MOVA (aopGet (left, 0, FALSE, FALSE));
7452 emitcode ("swap", "a");
7453 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
7455 case 2: /* swap bytes in word */
7456 if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result)))
7458 MOVA (aopGet (left, 0, FALSE, FALSE));
7459 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7460 0, isOperandVolatile (result, FALSE));
7461 aopPut (result, "a", 1, isOperandVolatile (result, FALSE));
7463 else if (operandsEqu (left, result))
7466 bool pushedB = FALSE, leftInB = FALSE;
7468 MOVA (aopGet (left, 0, FALSE, FALSE));
7469 if (aopGetUsesAcc(left, 1) || aopGetUsesAcc(result, 0))
7472 emitcode ("mov", "b,a");
7476 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7477 0, isOperandVolatile (result, FALSE));
7478 aopPut (result, reg, 1, isOperandVolatile (result, FALSE));
7485 aopPut (result, aopGet (left, 1, FALSE, FALSE),
7486 0, isOperandVolatile (result, FALSE));
7487 aopPut (result, aopGet (left, 0, FALSE, FALSE),
7488 1, isOperandVolatile (result, FALSE));
7492 wassertl(FALSE, "unsupported SWAP operand size");
7495 freeAsmop (left, NULL, ic, TRUE);
7496 freeAsmop (result, NULL, ic, TRUE);
7500 /*-----------------------------------------------------------------*/
7501 /* AccRol - rotate left accumulator by known count */
7502 /*-----------------------------------------------------------------*/
7504 AccRol (int shCount)
7506 shCount &= 0x0007; // shCount : 0..7
7513 emitcode ("rl", "a");
7516 emitcode ("rl", "a");
7517 emitcode ("rl", "a");
7520 emitcode ("swap", "a");
7521 emitcode ("rr", "a");
7524 emitcode ("swap", "a");
7527 emitcode ("swap", "a");
7528 emitcode ("rl", "a");
7531 emitcode ("rr", "a");
7532 emitcode ("rr", "a");
7535 emitcode ("rr", "a");
7540 /*-----------------------------------------------------------------*/
7541 /* AccLsh - left shift accumulator by known count */
7542 /*-----------------------------------------------------------------*/
7544 AccLsh (int shCount)
7549 emitcode ("add", "a,acc");
7550 else if (shCount == 2)
7552 emitcode ("add", "a,acc");
7553 emitcode ("add", "a,acc");
7557 /* rotate left accumulator */
7559 /* and kill the lower order bits */
7560 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
7565 /*-----------------------------------------------------------------*/
7566 /* AccRsh - right shift accumulator by known count */
7567 /*-----------------------------------------------------------------*/
7569 AccRsh (int shCount)
7576 emitcode ("rrc", "a");
7580 /* rotate right accumulator */
7581 AccRol (8 - shCount);
7582 /* and kill the higher order bits */
7583 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7588 /*-----------------------------------------------------------------*/
7589 /* AccSRsh - signed right shift accumulator by known count */
7590 /*-----------------------------------------------------------------*/
7592 AccSRsh (int shCount)
7599 emitcode ("mov", "c,acc.7");
7600 emitcode ("rrc", "a");
7602 else if (shCount == 2)
7604 emitcode ("mov", "c,acc.7");
7605 emitcode ("rrc", "a");
7606 emitcode ("mov", "c,acc.7");
7607 emitcode ("rrc", "a");
7611 tlbl = newiTempLabel (NULL);
7612 /* rotate right accumulator */
7613 AccRol (8 - shCount);
7614 /* and kill the higher order bits */
7615 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
7616 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7617 emitcode ("orl", "a,#0x%02x",
7618 (unsigned char) ~SRMask[shCount]);
7619 emitcode ("", "%05d$:", tlbl->key + 100);
7624 /*-----------------------------------------------------------------*/
7625 /* shiftR1Left2Result - shift right one byte from left to result */
7626 /*-----------------------------------------------------------------*/
7628 shiftR1Left2Result (operand * left, int offl,
7629 operand * result, int offr,
7630 int shCount, int sign)
7632 MOVA (aopGet (left, offl, FALSE, FALSE));
7633 /* shift right accumulator */
7638 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7641 /*-----------------------------------------------------------------*/
7642 /* shiftL1Left2Result - shift left one byte from left to result */
7643 /*-----------------------------------------------------------------*/
7645 shiftL1Left2Result (operand * left, int offl,
7646 operand * result, int offr, int shCount)
7649 l = aopGet (left, offl, FALSE, FALSE);
7651 /* shift left accumulator */
7653 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7656 /*-----------------------------------------------------------------*/
7657 /* movLeft2Result - move byte from left to result */
7658 /*-----------------------------------------------------------------*/
7660 movLeft2Result (operand * left, int offl,
7661 operand * result, int offr, int sign)
7664 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7666 l = aopGet (left, offl, FALSE, FALSE);
7668 if (*l == '@' && (IS_AOP_PREG (result)))
7670 emitcode ("mov", "a,%s", l);
7671 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7676 aopPut (result, l, offr, isOperandVolatile (result, FALSE));
7679 /* MSB sign in acc.7 ! */
7680 if (getDataSize (left) == offl + 1)
7682 emitcode ("mov", "a,%s", l);
7683 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
7690 /*-----------------------------------------------------------------*/
7691 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7692 /*-----------------------------------------------------------------*/
7696 emitcode ("rrc", "a");
7697 emitcode ("xch", "a,%s", x);
7698 emitcode ("rrc", "a");
7699 emitcode ("xch", "a,%s", x);
7702 /*-----------------------------------------------------------------*/
7703 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7704 /*-----------------------------------------------------------------*/
7708 emitcode ("xch", "a,%s", x);
7709 emitcode ("rlc", "a");
7710 emitcode ("xch", "a,%s", x);
7711 emitcode ("rlc", "a");
7714 /*-----------------------------------------------------------------*/
7715 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7716 /*-----------------------------------------------------------------*/
7720 emitcode ("xch", "a,%s", x);
7721 emitcode ("add", "a,acc");
7722 emitcode ("xch", "a,%s", x);
7723 emitcode ("rlc", "a");
7726 /*-----------------------------------------------------------------*/
7727 /* AccAXLsh - left shift a:x by known count (0..7) */
7728 /*-----------------------------------------------------------------*/
7730 AccAXLsh (char *x, int shCount)
7745 case 5: // AAAAABBB:CCCCCDDD
7747 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7749 emitcode ("anl", "a,#0x%02x",
7750 SLMask[shCount]); // BBB00000:CCCCCDDD
7752 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7754 AccRol (shCount); // DDDCCCCC:BBB00000
7756 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7758 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7760 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7762 emitcode ("anl", "a,#0x%02x",
7763 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7765 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7767 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7770 case 6: // AAAAAABB:CCCCCCDD
7771 emitcode ("anl", "a,#0x%02x",
7772 SRMask[shCount]); // 000000BB:CCCCCCDD
7773 emitcode ("mov", "c,acc.0"); // c = B
7774 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7776 AccAXRrl1 (x); // BCCCCCCD:D000000B
7777 AccAXRrl1 (x); // BBCCCCCC:DD000000
7779 emitcode("rrc","a");
7780 emitcode("xch","a,%s", x);
7781 emitcode("rrc","a");
7782 emitcode("mov","c,acc.0"); //<< get correct bit
7783 emitcode("xch","a,%s", x);
7785 emitcode("rrc","a");
7786 emitcode("xch","a,%s", x);
7787 emitcode("rrc","a");
7788 emitcode("xch","a,%s", x);
7791 case 7: // a:x <<= 7
7793 emitcode ("anl", "a,#0x%02x",
7794 SRMask[shCount]); // 0000000B:CCCCCCCD
7796 emitcode ("mov", "c,acc.0"); // c = B
7798 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7800 AccAXRrl1 (x); // BCCCCCCC:D0000000
7808 /*-----------------------------------------------------------------*/
7809 /* AccAXRsh - right shift a:x known count (0..7) */
7810 /*-----------------------------------------------------------------*/
7812 AccAXRsh (char *x, int shCount)
7820 AccAXRrl1 (x); // 0->a:x
7825 AccAXRrl1 (x); // 0->a:x
7828 AccAXRrl1 (x); // 0->a:x
7833 case 5: // AAAAABBB:CCCCCDDD = a:x
7835 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7837 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7839 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7841 emitcode ("anl", "a,#0x%02x",
7842 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7844 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7846 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7848 emitcode ("anl", "a,#0x%02x",
7849 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7851 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7853 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7855 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7858 case 6: // AABBBBBB:CCDDDDDD
7860 emitcode ("mov", "c,acc.7");
7861 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7863 emitcode ("mov", "c,acc.7");
7864 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7866 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7868 emitcode ("anl", "a,#0x%02x",
7869 SRMask[shCount]); // 000000AA:BBBBBBCC
7872 case 7: // ABBBBBBB:CDDDDDDD
7874 emitcode ("mov", "c,acc.7"); // c = A
7876 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7878 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7880 emitcode ("anl", "a,#0x%02x",
7881 SRMask[shCount]); // 0000000A:BBBBBBBC
7889 /*-----------------------------------------------------------------*/
7890 /* AccAXRshS - right shift signed a:x known count (0..7) */
7891 /*-----------------------------------------------------------------*/
7893 AccAXRshS (char *x, int shCount)
7901 emitcode ("mov", "c,acc.7");
7902 AccAXRrl1 (x); // s->a:x
7906 emitcode ("mov", "c,acc.7");
7907 AccAXRrl1 (x); // s->a:x
7909 emitcode ("mov", "c,acc.7");
7910 AccAXRrl1 (x); // s->a:x
7915 case 5: // AAAAABBB:CCCCCDDD = a:x
7917 tlbl = newiTempLabel (NULL);
7918 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7920 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7922 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7924 emitcode ("anl", "a,#0x%02x",
7925 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7927 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7929 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7931 emitcode ("anl", "a,#0x%02x",
7932 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7934 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7936 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7938 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7940 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7941 emitcode ("orl", "a,#0x%02x",
7942 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7944 emitcode ("", "%05d$:", tlbl->key + 100);
7945 break; // SSSSAAAA:BBBCCCCC
7947 case 6: // AABBBBBB:CCDDDDDD
7949 tlbl = newiTempLabel (NULL);
7950 emitcode ("mov", "c,acc.7");
7951 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7953 emitcode ("mov", "c,acc.7");
7954 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7956 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7958 emitcode ("anl", "a,#0x%02x",
7959 SRMask[shCount]); // 000000AA:BBBBBBCC
7961 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7962 emitcode ("orl", "a,#0x%02x",
7963 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7965 emitcode ("", "%05d$:", tlbl->key + 100);
7967 case 7: // ABBBBBBB:CDDDDDDD
7969 tlbl = newiTempLabel (NULL);
7970 emitcode ("mov", "c,acc.7"); // c = A
7972 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7974 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7976 emitcode ("anl", "a,#0x%02x",
7977 SRMask[shCount]); // 0000000A:BBBBBBBC
7979 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
7980 emitcode ("orl", "a,#0x%02x",
7981 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7983 emitcode ("", "%05d$:", tlbl->key + 100);
7990 /*-----------------------------------------------------------------*/
7991 /* shiftL2Left2Result - shift left two bytes from left to result */
7992 /*-----------------------------------------------------------------*/
7994 shiftL2Left2Result (operand * left, int offl,
7995 operand * result, int offr, int shCount)
7997 if (sameRegs (AOP (result), AOP (left)) &&
7998 ((offl + MSB16) == offr))
8000 /* don't crash result[offr] */
8001 MOVA (aopGet (left, offl, FALSE, FALSE));
8002 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8006 movLeft2Result (left, offl, result, offr, 0);
8007 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8009 /* ax << shCount (x = lsb(result)) */
8010 AccAXLsh (aopGet (result, offr, FALSE, FALSE), shCount);
8011 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8015 /*-----------------------------------------------------------------*/
8016 /* shiftR2Left2Result - shift right two bytes from left to result */
8017 /*-----------------------------------------------------------------*/
8019 shiftR2Left2Result (operand * left, int offl,
8020 operand * result, int offr,
8021 int shCount, int sign)
8023 if (sameRegs (AOP (result), AOP (left)) &&
8024 ((offl + MSB16) == offr))
8026 /* don't crash result[offr] */
8027 MOVA (aopGet (left, offl, FALSE, FALSE));
8028 emitcode ("xch", "a,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
8032 movLeft2Result (left, offl, result, offr, 0);
8033 MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
8035 /* a:x >> shCount (x = lsb(result)) */
8037 AccAXRshS (aopGet (result, offr, FALSE, FALSE), shCount);
8039 AccAXRsh (aopGet (result, offr, FALSE, FALSE), shCount);
8040 if (getDataSize (result) > 1)
8041 aopPut (result, "a", offr + MSB16, isOperandVolatile (result, FALSE));
8044 /*-----------------------------------------------------------------*/
8045 /* shiftLLeftOrResult - shift left one byte from left, or to result */
8046 /*-----------------------------------------------------------------*/
8048 shiftLLeftOrResult (operand * left, int offl,
8049 operand * result, int offr, int shCount)
8051 MOVA (aopGet (left, offl, FALSE, FALSE));
8052 /* shift left accumulator */
8054 /* or with result */
8055 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8056 /* back to result */
8057 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8060 /*-----------------------------------------------------------------*/
8061 /* shiftRLeftOrResult - shift right one byte from left,or to result */
8062 /*-----------------------------------------------------------------*/
8064 shiftRLeftOrResult (operand * left, int offl,
8065 operand * result, int offr, int shCount)
8067 MOVA (aopGet (left, offl, FALSE, FALSE));
8068 /* shift right accumulator */
8070 /* or with result */
8071 emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
8072 /* back to result */
8073 aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
8076 /*-----------------------------------------------------------------*/
8077 /* genlshOne - left shift a one byte quantity by known count */
8078 /*-----------------------------------------------------------------*/
8080 genlshOne (operand * result, operand * left, int shCount)
8082 D(emitcode ("; genlshOne",""));
8084 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8087 /*-----------------------------------------------------------------*/
8088 /* genlshTwo - left shift two bytes by known amount != 0 */
8089 /*-----------------------------------------------------------------*/
8091 genlshTwo (operand * result, operand * left, int shCount)
8095 D(emitcode ("; genlshTwo",""));
8097 size = getDataSize (result);
8099 /* if shCount >= 8 */
8107 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8109 movLeft2Result (left, LSB, result, MSB16, 0);
8111 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8114 /* 1 <= shCount <= 7 */
8118 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8120 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8124 /*-----------------------------------------------------------------*/
8125 /* shiftLLong - shift left one long from left to result */
8126 /* offl = LSB or MSB16 */
8127 /*-----------------------------------------------------------------*/
8129 shiftLLong (operand * left, operand * result, int offr)
8132 int size = AOP_SIZE (result);
8134 if (size >= LSB + offr)
8136 l = aopGet (left, LSB, FALSE, FALSE);
8138 emitcode ("add", "a,acc");
8139 if (sameRegs (AOP (left), AOP (result)) &&
8140 size >= MSB16 + offr && offr != LSB)
8141 emitcode ("xch", "a,%s",
8142 aopGet (left, LSB + offr, FALSE, FALSE));
8144 aopPut (result, "a", LSB + offr, isOperandVolatile (result, FALSE));
8147 if (size >= MSB16 + offr)
8149 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8151 l = aopGet (left, MSB16, FALSE, FALSE);
8154 emitcode ("rlc", "a");
8155 if (sameRegs (AOP (left), AOP (result)) &&
8156 size >= MSB24 + offr && offr != LSB)
8157 emitcode ("xch", "a,%s",
8158 aopGet (left, MSB16 + offr, FALSE, FALSE));
8160 aopPut (result, "a", MSB16 + offr, isOperandVolatile (result, FALSE));
8163 if (size >= MSB24 + offr)
8165 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8167 l = aopGet (left, MSB24, FALSE, FALSE);
8170 emitcode ("rlc", "a");
8171 if (sameRegs (AOP (left), AOP (result)) &&
8172 size >= MSB32 + offr && offr != LSB)
8173 emitcode ("xch", "a,%s",
8174 aopGet (left, MSB24 + offr, FALSE, FALSE));
8176 aopPut (result, "a", MSB24 + offr, isOperandVolatile (result, FALSE));
8179 if (size > MSB32 + offr)
8181 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8183 l = aopGet (left, MSB32, FALSE, FALSE);
8186 emitcode ("rlc", "a");
8187 aopPut (result, "a", MSB32 + offr, isOperandVolatile (result, FALSE));
8190 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8193 /*-----------------------------------------------------------------*/
8194 /* genlshFour - shift four byte by a known amount != 0 */
8195 /*-----------------------------------------------------------------*/
8197 genlshFour (operand * result, operand * left, int shCount)
8201 D(emitcode ("; genlshFour",""));
8203 size = AOP_SIZE (result);
8205 /* if shifting more that 3 bytes */
8210 /* lowest order of left goes to the highest
8211 order of the destination */
8212 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8214 movLeft2Result (left, LSB, result, MSB32, 0);
8215 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8216 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8217 aopPut (result, zero, MSB24, isOperandVolatile (result, FALSE));
8221 /* more than two bytes */
8222 else if (shCount >= 16)
8224 /* lower order two bytes goes to higher order two bytes */
8226 /* if some more remaining */
8228 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8231 movLeft2Result (left, MSB16, result, MSB32, 0);
8232 movLeft2Result (left, LSB, result, MSB24, 0);
8234 aopPut (result, zero, MSB16, isOperandVolatile (result, FALSE));
8235 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8239 /* if more than 1 byte */
8240 else if (shCount >= 8)
8242 /* lower order three bytes goes to higher order three bytes */
8247 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8249 movLeft2Result (left, LSB, result, MSB16, 0);
8255 movLeft2Result (left, MSB24, result, MSB32, 0);
8256 movLeft2Result (left, MSB16, result, MSB24, 0);
8257 movLeft2Result (left, LSB, result, MSB16, 0);
8258 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8260 else if (shCount == 1)
8261 shiftLLong (left, result, MSB16);
8264 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8265 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8266 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8267 aopPut (result, zero, LSB, isOperandVolatile (result, FALSE));
8272 /* 1 <= shCount <= 7 */
8273 else if (shCount <= 2)
8275 shiftLLong (left, result, LSB);
8277 shiftLLong (result, result, LSB);
8279 /* 3 <= shCount <= 7, optimize */
8282 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8283 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8284 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8288 /*-----------------------------------------------------------------*/
8289 /* genLeftShiftLiteral - left shifting by known count */
8290 /*-----------------------------------------------------------------*/
8292 genLeftShiftLiteral (operand * left,
8297 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8300 D(emitcode ("; genLeftShiftLiteral",""));
8302 freeAsmop (right, NULL, ic, TRUE);
8304 aopOp (left, ic, FALSE);
8305 aopOp (result, ic, FALSE);
8307 size = getSize (operandType (result));
8310 emitcode ("; shift left ", "result %d, left %d", size,
8314 /* I suppose that the left size >= result size */
8319 movLeft2Result (left, size, result, size, 0);
8323 else if (shCount >= (size * 8))
8325 aopPut (result, zero, size, isOperandVolatile (result, FALSE));
8331 genlshOne (result, left, shCount);
8335 genlshTwo (result, left, shCount);
8339 genlshFour (result, left, shCount);
8342 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8343 "*** ack! mystery literal shift!\n");
8347 freeAsmop (left, NULL, ic, TRUE);
8348 freeAsmop (result, NULL, ic, TRUE);
8351 /*-----------------------------------------------------------------*/
8352 /* genLeftShift - generates code for left shifting */
8353 /*-----------------------------------------------------------------*/
8355 genLeftShift (iCode * ic)
8357 operand *left, *right, *result;
8360 symbol *tlbl, *tlbl1;
8363 D(emitcode ("; genLeftShift",""));
8365 right = IC_RIGHT (ic);
8366 left = IC_LEFT (ic);
8367 result = IC_RESULT (ic);
8369 aopOp (right, ic, FALSE);
8371 /* if the shift count is known then do it
8372 as efficiently as possible */
8373 if (AOP_TYPE (right) == AOP_LIT)
8375 genLeftShiftLiteral (left, right, result, ic);
8379 /* shift count is unknown then we have to form
8380 a loop get the loop count in B : Note: we take
8381 only the lower order byte since shifting
8382 more that 32 bits make no sense anyway, ( the
8383 largest size of an object can be only 32 bits ) */
8386 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8387 emitcode ("inc", "b");
8388 freeAsmop (right, NULL, ic, TRUE);
8389 aopOp (left, ic, FALSE);
8390 aopOp (result, ic, FALSE);
8392 /* now move the left to the result if they are not the same */
8393 if (!sameRegs (AOP (left), AOP (result)) &&
8394 AOP_SIZE (result) > 1)
8397 size = AOP_SIZE (result);
8401 l = aopGet (left, offset, FALSE, TRUE);
8402 if (*l == '@' && (IS_AOP_PREG (result)))
8405 emitcode ("mov", "a,%s", l);
8406 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8409 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8414 tlbl = newiTempLabel (NULL);
8415 size = AOP_SIZE (result);
8417 tlbl1 = newiTempLabel (NULL);
8419 /* if it is only one byte then */
8422 symbol *tlbl1 = newiTempLabel (NULL);
8424 l = aopGet (left, 0, FALSE, FALSE);
8426 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8427 emitcode ("", "%05d$:", tlbl->key + 100);
8428 emitcode ("add", "a,acc");
8429 emitcode ("", "%05d$:", tlbl1->key + 100);
8430 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8432 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8436 reAdjustPreg (AOP (result));
8438 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8439 emitcode ("", "%05d$:", tlbl->key + 100);
8440 l = aopGet (result, offset, FALSE, FALSE);
8442 emitcode ("add", "a,acc");
8443 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8446 l = aopGet (result, offset, FALSE, FALSE);
8448 emitcode ("rlc", "a");
8449 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
8451 reAdjustPreg (AOP (result));
8453 emitcode ("", "%05d$:", tlbl1->key + 100);
8454 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8457 freeAsmop (left, NULL, ic, TRUE);
8458 freeAsmop (result, NULL, ic, TRUE);
8461 /*-----------------------------------------------------------------*/
8462 /* genrshOne - right shift a one byte quantity by known count */
8463 /*-----------------------------------------------------------------*/
8465 genrshOne (operand * result, operand * left,
8466 int shCount, int sign)
8468 D(emitcode ("; genrshOne",""));
8470 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8473 /*-----------------------------------------------------------------*/
8474 /* genrshTwo - right shift two bytes by known amount != 0 */
8475 /*-----------------------------------------------------------------*/
8477 genrshTwo (operand * result, operand * left,
8478 int shCount, int sign)
8480 D(emitcode ("; genrshTwo",""));
8482 /* if shCount >= 8 */
8487 shiftR1Left2Result (left, MSB16, result, LSB,
8490 movLeft2Result (left, MSB16, result, LSB, sign);
8491 addSign (result, MSB16, sign);
8494 /* 1 <= shCount <= 7 */
8496 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8499 /*-----------------------------------------------------------------*/
8500 /* shiftRLong - shift right one long from left to result */
8501 /* offl = LSB or MSB16 */
8502 /*-----------------------------------------------------------------*/
8504 shiftRLong (operand * left, int offl,
8505 operand * result, int sign)
8507 int isSameRegs=sameRegs(AOP(left),AOP(result));
8509 if (isSameRegs && offl>1) {
8510 // we are in big trouble, but this shouldn't happen
8511 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8514 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8519 emitcode ("rlc", "a");
8520 emitcode ("subb", "a,acc");
8522 emitcode ("xch", "a,%s", aopGet (left, MSB32, FALSE, FALSE));
8524 aopPut (result, "a", MSB32, isOperandVolatile (result, FALSE));
8525 MOVA (aopGet (left, MSB32, FALSE, FALSE));
8528 aopPut (result, zero, MSB32, isOperandVolatile (result, FALSE));
8533 emitcode ("clr", "c");
8535 emitcode ("mov", "c,acc.7");
8538 emitcode ("rrc", "a");
8540 if (isSameRegs && offl==MSB16) {
8541 emitcode ("xch", "a,%s",aopGet (left, MSB24, FALSE, FALSE));
8543 aopPut (result, "a", MSB32-offl, isOperandVolatile (result, FALSE));
8544 MOVA (aopGet (left, MSB24, FALSE, FALSE));
8547 emitcode ("rrc", "a");
8548 if (isSameRegs && offl==1) {
8549 emitcode ("xch", "a,%s",aopGet (left, MSB16, FALSE, FALSE));
8551 aopPut (result, "a", MSB24-offl, isOperandVolatile (result, FALSE));
8552 MOVA (aopGet (left, MSB16, FALSE, FALSE));
8554 emitcode ("rrc", "a");
8555 aopPut (result, "a", MSB16 - offl, isOperandVolatile (result, FALSE));
8559 MOVA (aopGet (left, LSB, FALSE, FALSE));
8560 emitcode ("rrc", "a");
8561 aopPut (result, "a", LSB, isOperandVolatile (result, FALSE));
8565 /*-----------------------------------------------------------------*/
8566 /* genrshFour - shift four byte by a known amount != 0 */
8567 /*-----------------------------------------------------------------*/
8569 genrshFour (operand * result, operand * left,
8570 int shCount, int sign)
8572 D(emitcode ("; genrshFour",""));
8574 /* if shifting more that 3 bytes */
8579 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8581 movLeft2Result (left, MSB32, result, LSB, sign);
8582 addSign (result, MSB16, sign);
8584 else if (shCount >= 16)
8588 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8591 movLeft2Result (left, MSB24, result, LSB, 0);
8592 movLeft2Result (left, MSB32, result, MSB16, sign);
8594 addSign (result, MSB24, sign);
8596 else if (shCount >= 8)
8600 shiftRLong (left, MSB16, result, sign);
8601 else if (shCount == 0)
8603 movLeft2Result (left, MSB16, result, LSB, 0);
8604 movLeft2Result (left, MSB24, result, MSB16, 0);
8605 movLeft2Result (left, MSB32, result, MSB24, sign);
8606 addSign (result, MSB32, sign);
8610 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8611 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8612 /* the last shift is signed */
8613 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8614 addSign (result, MSB32, sign);
8618 { /* 1 <= shCount <= 7 */
8621 shiftRLong (left, LSB, result, sign);
8623 shiftRLong (result, LSB, result, sign);
8627 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8628 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8629 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8634 /*-----------------------------------------------------------------*/
8635 /* genRightShiftLiteral - right shifting by known count */
8636 /*-----------------------------------------------------------------*/
8638 genRightShiftLiteral (operand * left,
8644 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8647 D(emitcode ("; genRightShiftLiteral",""));
8649 freeAsmop (right, NULL, ic, TRUE);
8651 aopOp (left, ic, FALSE);
8652 aopOp (result, ic, FALSE);
8655 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8659 size = getDataSize (left);
8660 /* test the LEFT size !!! */
8662 /* I suppose that the left size >= result size */
8665 size = getDataSize (result);
8667 movLeft2Result (left, size, result, size, 0);
8670 else if (shCount >= (size * 8))
8673 /* get sign in acc.7 */
8674 MOVA (aopGet (left, size - 1, FALSE, FALSE));
8676 addSign (result, LSB, sign);
8683 genrshOne (result, left, shCount, sign);
8687 genrshTwo (result, left, shCount, sign);
8691 genrshFour (result, left, shCount, sign);
8697 freeAsmop (left, NULL, ic, TRUE);
8698 freeAsmop (result, NULL, ic, TRUE);
8701 /*-----------------------------------------------------------------*/
8702 /* genSignedRightShift - right shift of signed number */
8703 /*-----------------------------------------------------------------*/
8705 genSignedRightShift (iCode * ic)
8707 operand *right, *left, *result;
8710 symbol *tlbl, *tlbl1;
8713 D(emitcode ("; genSignedRightShift",""));
8715 /* we do it the hard way put the shift count in b
8716 and loop thru preserving the sign */
8718 right = IC_RIGHT (ic);
8719 left = IC_LEFT (ic);
8720 result = IC_RESULT (ic);
8722 aopOp (right, ic, FALSE);
8725 if (AOP_TYPE (right) == AOP_LIT)
8727 genRightShiftLiteral (left, right, result, ic, 1);
8730 /* shift count is unknown then we have to form
8731 a loop get the loop count in B : Note: we take
8732 only the lower order byte since shifting
8733 more that 32 bits make no sense anyway, ( the
8734 largest size of an object can be only 32 bits ) */
8737 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8738 emitcode ("inc", "b");
8739 freeAsmop (right, NULL, ic, TRUE);
8740 aopOp (left, ic, FALSE);
8741 aopOp (result, ic, FALSE);
8743 /* now move the left to the result if they are not the
8745 if (!sameRegs (AOP (left), AOP (result)) &&
8746 AOP_SIZE (result) > 1)
8749 size = AOP_SIZE (result);
8753 l = aopGet (left, offset, FALSE, TRUE);
8754 if (*l == '@' && IS_AOP_PREG (result))
8757 emitcode ("mov", "a,%s", l);
8758 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8761 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8766 /* mov the highest order bit to OVR */
8767 tlbl = newiTempLabel (NULL);
8768 tlbl1 = newiTempLabel (NULL);
8770 size = AOP_SIZE (result);
8772 MOVA (aopGet (left, offset, FALSE, FALSE));
8773 emitcode ("rlc", "a");
8774 emitcode ("mov", "ov,c");
8775 /* if it is only one byte then */
8778 l = aopGet (left, 0, FALSE, FALSE);
8780 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8781 emitcode ("", "%05d$:", tlbl->key + 100);
8782 emitcode ("mov", "c,ov");
8783 emitcode ("rrc", "a");
8784 emitcode ("", "%05d$:", tlbl1->key + 100);
8785 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8787 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8791 reAdjustPreg (AOP (result));
8792 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8793 emitcode ("", "%05d$:", tlbl->key + 100);
8794 emitcode ("mov", "c,ov");
8797 l = aopGet (result, offset, FALSE, FALSE);
8799 emitcode ("rrc", "a");
8800 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8802 reAdjustPreg (AOP (result));
8803 emitcode ("", "%05d$:", tlbl1->key + 100);
8804 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8808 freeAsmop (left, NULL, ic, TRUE);
8809 freeAsmop (result, NULL, ic, TRUE);
8812 /*-----------------------------------------------------------------*/
8813 /* genRightShift - generate code for right shifting */
8814 /*-----------------------------------------------------------------*/
8816 genRightShift (iCode * ic)
8818 operand *right, *left, *result;
8822 symbol *tlbl, *tlbl1;
8825 D(emitcode ("; genRightShift",""));
8827 /* if signed then we do it the hard way preserve the
8828 sign bit moving it inwards */
8829 letype = getSpec (operandType (IC_LEFT (ic)));
8831 if (!SPEC_USIGN (letype))
8833 genSignedRightShift (ic);
8837 /* signed & unsigned types are treated the same : i.e. the
8838 signed is NOT propagated inwards : quoting from the
8839 ANSI - standard : "for E1 >> E2, is equivalent to division
8840 by 2**E2 if unsigned or if it has a non-negative value,
8841 otherwise the result is implementation defined ", MY definition
8842 is that the sign does not get propagated */
8844 right = IC_RIGHT (ic);
8845 left = IC_LEFT (ic);
8846 result = IC_RESULT (ic);
8848 aopOp (right, ic, FALSE);
8850 /* if the shift count is known then do it
8851 as efficiently as possible */
8852 if (AOP_TYPE (right) == AOP_LIT)
8854 genRightShiftLiteral (left, right, result, ic, 0);
8858 /* shift count is unknown then we have to form
8859 a loop get the loop count in B : Note: we take
8860 only the lower order byte since shifting
8861 more that 32 bits make no sense anyway, ( the
8862 largest size of an object can be only 32 bits ) */
8865 emitcode ("mov", "b,%s", aopGet (right, 0, FALSE, FALSE));
8866 emitcode ("inc", "b");
8867 freeAsmop (right, NULL, ic, TRUE);
8868 aopOp (left, ic, FALSE);
8869 aopOp (result, ic, FALSE);
8871 /* now move the left to the result if they are not the
8873 if (!sameRegs (AOP (left), AOP (result)) &&
8874 AOP_SIZE (result) > 1)
8877 size = AOP_SIZE (result);
8881 l = aopGet (left, offset, FALSE, TRUE);
8882 if (*l == '@' && IS_AOP_PREG (result))
8885 emitcode ("mov", "a,%s", l);
8886 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
8889 aopPut (result, l, offset, isOperandVolatile (result, FALSE));
8894 tlbl = newiTempLabel (NULL);
8895 tlbl1 = newiTempLabel (NULL);
8896 size = AOP_SIZE (result);
8899 /* if it is only one byte then */
8902 l = aopGet (left, 0, FALSE, FALSE);
8904 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8905 emitcode ("", "%05d$:", tlbl->key + 100);
8907 emitcode ("rrc", "a");
8908 emitcode ("", "%05d$:", tlbl1->key + 100);
8909 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8911 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
8915 reAdjustPreg (AOP (result));
8916 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
8917 emitcode ("", "%05d$:", tlbl->key + 100);
8921 l = aopGet (result, offset, FALSE, FALSE);
8923 emitcode ("rrc", "a");
8924 aopPut (result, "a", offset--, isOperandVolatile (result, FALSE));
8926 reAdjustPreg (AOP (result));
8928 emitcode ("", "%05d$:", tlbl1->key + 100);
8929 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
8933 freeAsmop (left, NULL, ic, TRUE);
8934 freeAsmop (result, NULL, ic, TRUE);
8937 /*-----------------------------------------------------------------*/
8938 /* emitPtrByteGet - emits code to get a byte into A through a */
8939 /* pointer register (R0, R1, or DPTR). The */
8940 /* original value of A can be preserved in B. */
8941 /*-----------------------------------------------------------------*/
8943 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
8950 emitcode ("mov", "b,a");
8951 emitcode ("mov", "a,@%s", rname);
8956 emitcode ("mov", "b,a");
8957 emitcode ("movx", "a,@%s", rname);
8962 emitcode ("mov", "b,a");
8963 emitcode ("movx", "a,@dptr");
8968 emitcode ("mov", "b,a");
8969 emitcode ("clr", "a");
8970 emitcode ("movc", "a,@a+dptr");
8976 emitcode ("push", "b");
8977 emitcode ("push", "acc");
8979 emitcode ("lcall", "__gptrget");
8981 emitcode ("pop", "b");
8986 /*-----------------------------------------------------------------*/
8987 /* emitPtrByteSet - emits code to set a byte from src through a */
8988 /* pointer register (R0, R1, or DPTR). */
8989 /*-----------------------------------------------------------------*/
8991 emitPtrByteSet (char *rname, int p_type, char *src)
9000 emitcode ("mov", "@%s,a", rname);
9003 emitcode ("mov", "@%s,%s", rname, src);
9008 emitcode ("movx", "@%s,a", rname);
9013 emitcode ("movx", "@dptr,a");
9018 emitcode ("lcall", "__gptrput");
9023 /*-----------------------------------------------------------------*/
9024 /* genUnpackBits - generates code for unpacking bits */
9025 /*-----------------------------------------------------------------*/
9027 genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
9029 int offset = 0; /* result byte offset */
9030 int rsize; /* result size */
9031 int rlen = 0; /* remaining bitfield length */
9032 sym_link *etype; /* bitfield type information */
9033 int blen; /* bitfield length */
9034 int bstr; /* bitfield starting bit within byte */
9037 D(emitcode ("; genUnpackBits",""));
9039 etype = getSpec (operandType (result));
9040 rsize = getSize (operandType (result));
9041 blen = SPEC_BLEN (etype);
9042 bstr = SPEC_BSTR (etype);
9044 if (ifx && blen <= 8)
9046 emitPtrByteGet (rname, ptype, FALSE);
9049 SNPRINTF (buffer, sizeof(buffer),
9051 genIfxJump (ifx, buffer, NULL, NULL, NULL);
9056 emitcode ("anl", "a,#0x%02x",
9057 (((unsigned char) -1) >> (8 - blen)) << bstr);
9058 genIfxJump (ifx, "a", NULL, NULL, NULL);
9064 /* If the bitfield length is less than a byte */
9067 emitPtrByteGet (rname, ptype, FALSE);
9069 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
9070 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9074 /* Bit field did not fit in a byte. Copy all
9075 but the partial byte at the end. */
9076 for (rlen=blen;rlen>=8;rlen-=8)
9078 emitPtrByteGet (rname, ptype, FALSE);
9079 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9081 emitcode ("inc", "%s", rname);
9084 /* Handle the partial byte at the end */
9087 emitPtrByteGet (rname, ptype, FALSE);
9088 emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
9089 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9097 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
9102 /*-----------------------------------------------------------------*/
9103 /* genDataPointerGet - generates code when ptr offset is known */
9104 /*-----------------------------------------------------------------*/
9106 genDataPointerGet (operand * left,
9112 int size, offset = 0;
9114 D(emitcode ("; genDataPointerGet",""));
9116 aopOp (result, ic, TRUE);
9118 /* get the string representation of the name */
9119 l = aopGet (left, 0, FALSE, TRUE);
9120 size = AOP_SIZE (result);
9124 sprintf (buffer, "(%s + %d)", l + 1, offset);
9126 sprintf (buffer, "%s", l + 1);
9127 aopPut (result, buffer, offset++, isOperandVolatile (result, FALSE));
9130 freeAsmop (left, NULL, ic, TRUE);
9131 freeAsmop (result, NULL, ic, TRUE);
9134 /*-----------------------------------------------------------------*/
9135 /* genNearPointerGet - emitcode for near pointer fetch */
9136 /*-----------------------------------------------------------------*/
9138 genNearPointerGet (operand * left,
9147 sym_link *rtype, *retype;
9148 sym_link *ltype = operandType (left);
9151 D(emitcode ("; genNearPointerGet",""));
9153 rtype = operandType (result);
9154 retype = getSpec (rtype);
9156 aopOp (left, ic, FALSE);
9158 /* if left is rematerialisable and
9159 result is not bitfield variable type and
9160 the left is pointer to data space i.e
9161 lower 128 bytes of space */
9162 if (AOP_TYPE (left) == AOP_IMMD &&
9163 !IS_BITFIELD (retype) &&
9164 DCL_TYPE (ltype) == POINTER)
9166 genDataPointerGet (left, result, ic);
9170 /* if the value is already in a pointer register
9171 then don't need anything more */
9172 if (!AOP_INPREG (AOP (left)))
9174 if (IS_AOP_PREG (left))
9176 // Aha, it is a pointer, just in disguise.
9177 rname = aopGet (left, 0, FALSE, FALSE);
9180 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9181 __FILE__, __LINE__);
9186 emitcode ("mov", "a%s,%s", rname + 1, rname);
9187 rname++; // skip the '@'.
9192 /* otherwise get a free pointer register */
9194 preg = getFreePtr (ic, &aop, FALSE);
9195 emitcode ("mov", "%s,%s",
9197 aopGet (left, 0, FALSE, TRUE));
9202 rname = aopGet (left, 0, FALSE, FALSE);
9204 //aopOp (result, ic, FALSE);
9205 aopOp (result, ic, result?TRUE:FALSE);
9207 /* if bitfield then unpack the bits */
9208 if (IS_BITFIELD (retype))
9209 genUnpackBits (result, rname, POINTER, ifx);
9212 /* we have can just get the values */
9213 int size = AOP_SIZE (result);
9218 if (ifx || IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9221 emitcode ("mov", "a,@%s", rname);
9223 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9227 sprintf (buffer, "@%s", rname);
9228 aopPut (result, buffer, offset, isOperandVolatile (result, FALSE));
9232 emitcode ("inc", "%s", rname);
9236 /* now some housekeeping stuff */
9237 if (aop) /* we had to allocate for this iCode */
9239 if (pi) { /* post increment present */
9240 aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9242 freeAsmop (NULL, aop, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9246 /* we did not allocate which means left
9247 already in a pointer register, then
9248 if size > 0 && this could be used again
9249 we have to point it back to where it
9251 if ((AOP_SIZE (result) > 1 &&
9252 !OP_SYMBOL (left)->remat &&
9253 (OP_SYMBOL (left)->liveTo > ic->seq ||
9257 int size = AOP_SIZE (result) - 1;
9259 emitcode ("dec", "%s", rname);
9263 if (ifx && !ifx->generated)
9265 genIfxJump (ifx, "a", left, NULL, result);
9269 freeAsmop (result, NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
9270 freeAsmop (left, NULL, ic, TRUE);
9271 if (pi) pi->generated = 1;
9274 /*-----------------------------------------------------------------*/
9275 /* genPagedPointerGet - emitcode for paged pointer fetch */
9276 /*-----------------------------------------------------------------*/
9278 genPagedPointerGet (operand * left,
9287 sym_link *rtype, *retype;
9289 D(emitcode ("; genPagedPointerGet",""));
9291 rtype = operandType (result);
9292 retype = getSpec (rtype);
9294 aopOp (left, ic, FALSE);
9296 /* if the value is already in a pointer register
9297 then don't need anything more */
9298 if (!AOP_INPREG (AOP (left)))
9300 /* otherwise get a free pointer register */
9302 preg = getFreePtr (ic, &aop, FALSE);
9303 emitcode ("mov", "%s,%s",
9305 aopGet (left, 0, FALSE, TRUE));
9309 rname = aopGet (left, 0, FALSE, FALSE);
9311 aopOp (result, ic, FALSE);
9313 /* if bitfield then unpack the bits */
9314 if (IS_BITFIELD (retype))
9315 genUnpackBits (result, rname, PPOINTER, ifx);
9318 /* we have can just get the values */
9319 int size = AOP_SIZE (result);
9325 emitcode ("movx", "a,@%s", rname);
9327 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
9332 emitcode ("inc", "%s", rname);
9336 /* now some housekeeping stuff */
9337 if (aop) /* we had to allocate for this iCode */
9339 if (pi) aopPut (left, rname, 0, isOperandVolatile (left, FALSE));
9340 freeAsmop (NULL, aop, ic, TRUE);
9344 /* we did not allocate which means left
9345 already in a pointer register, then
9346 if size > 0 && this could be used again
9347 we have to point it back to where it
9349 if ((AOP_SIZE (result) > 1 &&
9350 !OP_SYMBOL (left)->remat &&
9351 (OP_SYMBOL (left)->liveTo > ic->seq ||
9355 int size = AOP_SIZE (result) - 1;
9357 emitcode ("dec", "%s", rname);
9361 if (ifx && !ifx->generated)
9363 genIfxJump (ifx, "a", left, NULL, result);
9367 freeAsmop (left, NULL, ic, TRUE);
9368 freeAsmop (result, NULL, ic, TRUE);
9369 if (pi) pi->generated = 1;
9373 /*--------------------------------------------------------------------*/
9374 /* loadDptrFromOperand - load dptr (and optionally B) from operand op */
9375 /*--------------------------------------------------------------------*/
9377 loadDptrFromOperand (operand *op, bool loadBToo)
9379 if (AOP_TYPE (op) != AOP_STR)
9381 /* if this is rematerializable */
9382 if (AOP_TYPE (op) == AOP_IMMD)
9384 emitcode ("mov", "dptr,%s", aopGet (op, 0, TRUE, FALSE));
9387 if (AOP(op)->aopu.aop_immd.from_cast_remat)
9388 emitcode ("mov", "b,%s",aopGet (op, AOP_SIZE(op)-1, FALSE, FALSE));
9391 wassertl(FALSE, "need pointerCode");
9392 emitcode ("", "; mov b,???");
9393 /* genPointerGet and genPointerSet originally did different
9394 ** things for this case. Both seem wrong.
9395 ** from genPointerGet:
9396 ** emitcode ("mov", "b,#%d", pointerCode (retype));
9397 ** from genPointerSet:
9398 ** emitcode ("mov", "b,%s + 1", aopGet (result, 0, TRUE, FALSE));
9403 else if (AOP_TYPE (op) == AOP_DPTR)
9407 MOVA (aopGet (op, 0, FALSE, FALSE));
9408 emitcode ("push", "acc");
9409 MOVA (aopGet (op, 1, FALSE, FALSE));
9410 emitcode ("push", "acc");
9411 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9412 emitcode ("pop", "dph");
9413 emitcode ("pop", "dpl");
9417 MOVA (aopGet (op, 0, FALSE, FALSE));
9418 emitcode ("push", "acc");
9419 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9420 emitcode ("pop", "dpl");
9424 { /* we need to get it byte by byte */
9425 emitcode ("mov", "dpl,%s", aopGet (op, 0, FALSE, FALSE));
9426 emitcode ("mov", "dph,%s", aopGet (op, 1, FALSE, FALSE));
9428 emitcode ("mov", "b,%s", aopGet (op, 2, FALSE, FALSE));
9433 /*-----------------------------------------------------------------*/
9434 /* genFarPointerGet - gget value from far space */
9435 /*-----------------------------------------------------------------*/
9437 genFarPointerGet (operand * left,
9438 operand * result, iCode * ic, iCode * pi, iCode * ifx)
9441 sym_link *retype = getSpec (operandType (result));
9443 D(emitcode ("; genFarPointerGet",""));
9445 aopOp (left, ic, FALSE);
9446 loadDptrFromOperand (left, FALSE);
9448 /* so dptr now contains the address */
9449 aopOp (result, ic, FALSE);
9451 /* if bit then unpack */
9452 if (IS_BITFIELD (retype))
9453 genUnpackBits (result, "dptr", FPOINTER, ifx);
9456 size = AOP_SIZE (result);
9461 emitcode ("movx", "a,@dptr");
9463 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9465 emitcode ("inc", "dptr");
9469 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9471 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9472 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9476 if (ifx && !ifx->generated)
9478 genIfxJump (ifx, "a", left, NULL, result);
9481 freeAsmop (left, NULL, ic, TRUE);
9482 freeAsmop (result, NULL, ic, TRUE);
9485 /*-----------------------------------------------------------------*/
9486 /* genCodePointerGet - gget value from code space */
9487 /*-----------------------------------------------------------------*/
9489 genCodePointerGet (operand * left,
9490 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9493 sym_link *retype = getSpec (operandType (result));
9495 D(emitcode ("; genCodePointerGet",""));
9497 aopOp (left, ic, FALSE);
9498 loadDptrFromOperand (left, FALSE);
9500 /* so dptr now contains the address */
9501 aopOp (result, ic, FALSE);
9503 /* if bit then unpack */
9504 if (IS_BITFIELD (retype))
9505 genUnpackBits (result, "dptr", CPOINTER, ifx);
9508 size = AOP_SIZE (result);
9515 emitcode ("clr", "a");
9516 emitcode ("movc", "a,@a+dptr");
9518 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9519 emitcode ("inc", "dptr");
9523 emitcode ("mov", "a,#0x%02x", offset);
9524 emitcode ("movc", "a,@a+dptr");
9526 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9531 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9533 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9534 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9538 if (ifx && !ifx->generated)
9540 genIfxJump (ifx, "a", left, NULL, result);
9543 freeAsmop (left, NULL, ic, TRUE);
9544 freeAsmop (result, NULL, ic, TRUE);
9547 /*-----------------------------------------------------------------*/
9548 /* genGenPointerGet - gget value from generic pointer space */
9549 /*-----------------------------------------------------------------*/
9551 genGenPointerGet (operand * left,
9552 operand * result, iCode * ic, iCode *pi, iCode *ifx)
9555 sym_link *retype = getSpec (operandType (result));
9557 D(emitcode ("; genGenPointerGet",""));
9559 aopOp (left, ic, FALSE);
9560 loadDptrFromOperand (left, TRUE);
9562 /* so dptr know contains the address */
9563 aopOp (result, ic, FALSE);
9565 /* if bit then unpack */
9566 if (IS_BITFIELD (retype))
9567 genUnpackBits (result, "dptr", GPOINTER, ifx);
9570 size = AOP_SIZE (result);
9575 emitcode ("lcall", "__gptrget");
9577 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
9579 emitcode ("inc", "dptr");
9583 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR)
9585 aopPut (left, "dpl", 0, isOperandVolatile (left, FALSE));
9586 aopPut (left, "dph", 1, isOperandVolatile (left, FALSE));
9590 if (ifx && !ifx->generated)
9592 genIfxJump (ifx, "a", left, NULL, result);
9596 freeAsmop (left, NULL, ic, TRUE);
9597 freeAsmop (result, NULL, ic, TRUE);
9600 /*-----------------------------------------------------------------*/
9601 /* genPointerGet - generate code for pointer get */
9602 /*-----------------------------------------------------------------*/
9604 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
9606 operand *left, *result;
9607 sym_link *type, *etype;
9610 D(emitcode ("; genPointerGet",""));
9612 left = IC_LEFT (ic);
9613 result = IC_RESULT (ic);
9615 if (getSize (operandType (result))>1)
9618 /* depending on the type of pointer we need to
9619 move it to the correct pointer register */
9620 type = operandType (left);
9621 etype = getSpec (type);
9622 /* if left is of type of pointer then it is simple */
9623 if (IS_PTR (type) && !IS_FUNC (type->next))
9624 p_type = DCL_TYPE (type);
9627 /* we have to go by the storage class */
9628 p_type = PTR_TYPE (SPEC_OCLS (etype));
9631 /* special case when cast remat */
9632 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9633 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9634 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9635 type = operandType (left);
9636 p_type = DCL_TYPE (type);
9638 /* now that we have the pointer type we assign
9639 the pointer values */
9645 genNearPointerGet (left, result, ic, pi, ifx);
9649 genPagedPointerGet (left, result, ic, pi, ifx);
9653 genFarPointerGet (left, result, ic, pi, ifx);
9657 genCodePointerGet (left, result, ic, pi, ifx);
9661 genGenPointerGet (left, result, ic, pi, ifx);
9669 /*-----------------------------------------------------------------*/
9670 /* genPackBits - generates code for packed bit storage */
9671 /*-----------------------------------------------------------------*/
9673 genPackBits (sym_link * etype,
9675 char *rname, int p_type)
9677 int offset = 0; /* source byte offset */
9678 int rlen = 0; /* remaining bitfield length */
9679 int blen; /* bitfield length */
9680 int bstr; /* bitfield starting bit within byte */
9681 int litval; /* source literal value (if AOP_LIT) */
9682 unsigned char mask; /* bitmask within current byte */
9684 D(emitcode ("; genPackBits",""));
9686 blen = SPEC_BLEN (etype);
9687 bstr = SPEC_BSTR (etype);
9689 /* If the bitfield length is less than a byte */
9692 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9693 (unsigned char) (0xFF >> (8 - bstr)));
9695 if (AOP_TYPE (right) == AOP_LIT)
9697 /* Case with a bitfield length <8 and literal source
9699 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9701 litval &= (~mask) & 0xff;
9702 emitPtrByteGet (rname, p_type, FALSE);
9703 if ((mask|litval)!=0xff)
9704 emitcode ("anl","a,#0x%02x", mask);
9706 emitcode ("orl","a,#0x%02x", litval);
9710 if ((blen==1) && (p_type!=GPOINTER))
9712 /* Case with a bitfield length == 1 and no generic pointer
9714 if (AOP_TYPE (right) == AOP_CRY)
9715 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9718 MOVA (aopGet (right, 0, FALSE, FALSE));
9719 emitcode ("rrc","a");
9721 emitPtrByteGet (rname, p_type, FALSE);
9722 emitcode ("mov","acc.%d,c",bstr);
9727 /* Case with a bitfield length < 8 and arbitrary source
9729 MOVA (aopGet (right, 0, FALSE, FALSE));
9730 /* shift and mask source value */
9732 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9735 /* transfer A to B and get next byte */
9736 emitPtrByteGet (rname, p_type, TRUE);
9738 emitcode ("anl", "a,#0x%02x", mask);
9739 emitcode ("orl", "a,b");
9740 if (p_type == GPOINTER)
9741 emitcode ("pop", "b");
9747 emitPtrByteSet (rname, p_type, "a");
9751 /* Bit length is greater than 7 bits. In this case, copy */
9752 /* all except the partial byte at the end */
9753 for (rlen=blen;rlen>=8;rlen-=8)
9755 emitPtrByteSet (rname, p_type,
9756 aopGet (right, offset++, FALSE, TRUE) );
9758 emitcode ("inc", "%s", rname);
9761 /* If there was a partial byte at the end */
9764 mask = (((unsigned char) -1 << rlen) & 0xff);
9766 if (AOP_TYPE (right) == AOP_LIT)
9768 /* Case with partial byte and literal source
9770 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9771 litval >>= (blen-rlen);
9772 litval &= (~mask) & 0xff;
9773 emitPtrByteGet (rname, p_type, FALSE);
9774 if ((mask|litval)!=0xff)
9775 emitcode ("anl","a,#0x%02x", mask);
9777 emitcode ("orl","a,#0x%02x", litval);
9782 /* Case with partial byte and arbitrary source
9784 MOVA (aopGet (right, offset++, FALSE, FALSE));
9785 emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
9788 /* transfer A to B and get next byte */
9789 emitPtrByteGet (rname, p_type, TRUE);
9791 emitcode ("anl", "a,#0x%02x", mask);
9792 emitcode ("orl", "a,b");
9793 if (p_type == GPOINTER)
9794 emitcode ("pop", "b");
9798 emitPtrByteSet (rname, p_type, "a");
9804 /*-----------------------------------------------------------------*/
9805 /* genDataPointerSet - remat pointer to data space */
9806 /*-----------------------------------------------------------------*/
9808 genDataPointerSet (operand * right,
9812 int size, offset = 0;
9813 char *l, buffer[256];
9815 D(emitcode ("; genDataPointerSet",""));
9817 aopOp (right, ic, FALSE);
9819 l = aopGet (result, 0, FALSE, TRUE);
9820 size = AOP_SIZE (right);
9824 sprintf (buffer, "(%s + %d)", l + 1, offset);
9826 sprintf (buffer, "%s", l + 1);
9827 emitcode ("mov", "%s,%s", buffer,
9828 aopGet (right, offset++, FALSE, FALSE));
9831 freeAsmop (right, NULL, ic, TRUE);
9832 freeAsmop (result, NULL, ic, TRUE);
9835 /*-----------------------------------------------------------------*/
9836 /* genNearPointerSet - emitcode for near pointer put */
9837 /*-----------------------------------------------------------------*/
9839 genNearPointerSet (operand * right,
9847 sym_link *retype, *letype;
9848 sym_link *ptype = operandType (result);
9850 D(emitcode ("; genNearPointerSet",""));
9852 retype = getSpec (operandType (right));
9853 letype = getSpec (ptype);
9854 aopOp (result, ic, FALSE);
9856 /* if the result is rematerializable &
9857 in data space & not a bit variable */
9858 if (AOP_TYPE (result) == AOP_IMMD &&
9859 DCL_TYPE (ptype) == POINTER &&
9860 !IS_BITVAR (retype) &&
9861 !IS_BITVAR (letype))
9863 genDataPointerSet (right, result, ic);
9867 /* if the value is already in a pointer register
9868 then don't need anything more */
9869 if (!AOP_INPREG (AOP (result)))
9872 //AOP_TYPE (result) == AOP_STK
9876 // Aha, it is a pointer, just in disguise.
9877 rname = aopGet (result, 0, FALSE, FALSE);
9880 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
9881 __FILE__, __LINE__);
9886 emitcode ("mov", "a%s,%s", rname + 1, rname);
9887 rname++; // skip the '@'.
9892 /* otherwise get a free pointer register */
9894 preg = getFreePtr (ic, &aop, FALSE);
9895 emitcode ("mov", "%s,%s",
9897 aopGet (result, 0, FALSE, TRUE));
9903 rname = aopGet (result, 0, FALSE, FALSE);
9906 aopOp (right, ic, FALSE);
9908 /* if bitfield then unpack the bits */
9909 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
9910 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
9913 /* we have can just get the values */
9914 int size = AOP_SIZE (right);
9919 l = aopGet (right, offset, FALSE, TRUE);
9923 emitcode ("mov", "@%s,a", rname);
9926 emitcode ("mov", "@%s,%s", rname, l);
9928 emitcode ("inc", "%s", rname);
9933 /* now some housekeeping stuff */
9934 if (aop) /* we had to allocate for this iCode */
9937 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
9938 freeAsmop (NULL, aop, ic, TRUE);
9942 /* we did not allocate which means left
9943 already in a pointer register, then
9944 if size > 0 && this could be used again
9945 we have to point it back to where it
9947 if ((AOP_SIZE (right) > 1 &&
9948 !OP_SYMBOL (result)->remat &&
9949 (OP_SYMBOL (result)->liveTo > ic->seq ||
9953 int size = AOP_SIZE (right) - 1;
9955 emitcode ("dec", "%s", rname);
9960 if (pi) pi->generated = 1;
9961 freeAsmop (result, NULL, ic, TRUE);
9962 freeAsmop (right, NULL, ic, TRUE);
9965 /*-----------------------------------------------------------------*/
9966 /* genPagedPointerSet - emitcode for Paged pointer put */
9967 /*-----------------------------------------------------------------*/
9969 genPagedPointerSet (operand * right,
9977 sym_link *retype, *letype;
9979 D(emitcode ("; genPagedPointerSet",""));
9981 retype = getSpec (operandType (right));
9982 letype = getSpec (operandType (result));
9984 aopOp (result, ic, FALSE);
9986 /* if the value is already in a pointer register
9987 then don't need anything more */
9988 if (!AOP_INPREG (AOP (result)))
9990 /* otherwise get a free pointer register */
9992 preg = getFreePtr (ic, &aop, FALSE);
9993 emitcode ("mov", "%s,%s",
9995 aopGet (result, 0, FALSE, TRUE));
9999 rname = aopGet (result, 0, FALSE, FALSE);
10001 aopOp (right, ic, FALSE);
10003 /* if bitfield then unpack the bits */
10004 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10005 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
10008 /* we have can just get the values */
10009 int size = AOP_SIZE (right);
10014 l = aopGet (right, offset, FALSE, TRUE);
10017 emitcode ("movx", "@%s,a", rname);
10020 emitcode ("inc", "%s", rname);
10026 /* now some housekeeping stuff */
10027 if (aop) /* we had to allocate for this iCode */
10030 aopPut (result, rname, 0, isOperandVolatile (result, FALSE));
10031 freeAsmop (NULL, aop, ic, TRUE);
10035 /* we did not allocate which means left
10036 already in a pointer register, then
10037 if size > 0 && this could be used again
10038 we have to point it back to where it
10040 if (AOP_SIZE (right) > 1 &&
10041 !OP_SYMBOL (result)->remat &&
10042 (OP_SYMBOL (result)->liveTo > ic->seq ||
10045 int size = AOP_SIZE (right) - 1;
10047 emitcode ("dec", "%s", rname);
10052 if (pi) pi->generated = 1;
10053 freeAsmop (result, NULL, ic, TRUE);
10054 freeAsmop (right, NULL, ic, TRUE);
10059 /*-----------------------------------------------------------------*/
10060 /* genFarPointerSet - set value from far space */
10061 /*-----------------------------------------------------------------*/
10063 genFarPointerSet (operand * right,
10064 operand * result, iCode * ic, iCode * pi)
10067 sym_link *retype = getSpec (operandType (right));
10068 sym_link *letype = getSpec (operandType (result));
10070 D(emitcode ("; genFarPointerSet",""));
10072 aopOp (result, ic, FALSE);
10073 loadDptrFromOperand (result, FALSE);
10075 /* so dptr know contains the address */
10076 aopOp (right, ic, FALSE);
10078 /* if bit then unpack */
10079 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10080 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
10083 size = AOP_SIZE (right);
10088 char *l = aopGet (right, offset++, FALSE, FALSE);
10090 emitcode ("movx", "@dptr,a");
10092 emitcode ("inc", "dptr");
10095 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10096 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10097 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10100 freeAsmop (result, NULL, ic, TRUE);
10101 freeAsmop (right, NULL, ic, TRUE);
10104 /*-----------------------------------------------------------------*/
10105 /* genGenPointerSet - set value from generic pointer space */
10106 /*-----------------------------------------------------------------*/
10108 genGenPointerSet (operand * right,
10109 operand * result, iCode * ic, iCode * pi)
10112 sym_link *retype = getSpec (operandType (right));
10113 sym_link *letype = getSpec (operandType (result));
10115 D(emitcode ("; genGenPointerSet",""));
10117 aopOp (result, ic, FALSE);
10118 loadDptrFromOperand (result, TRUE);
10120 /* so dptr know contains the address */
10121 aopOp (right, ic, FALSE);
10123 /* if bit then unpack */
10124 if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
10125 genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
10128 size = AOP_SIZE (right);
10133 char *l = aopGet (right, offset++, FALSE, FALSE);
10135 emitcode ("lcall", "__gptrput");
10137 emitcode ("inc", "dptr");
10141 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
10142 aopPut (result, "dpl", 0, isOperandVolatile (result, FALSE));
10143 aopPut (result, "dph", 1, isOperandVolatile (result, FALSE));
10146 freeAsmop (result, NULL, ic, TRUE);
10147 freeAsmop (right, NULL, ic, TRUE);
10150 /*-----------------------------------------------------------------*/
10151 /* genPointerSet - stores the value into a pointer location */
10152 /*-----------------------------------------------------------------*/
10154 genPointerSet (iCode * ic, iCode *pi)
10156 operand *right, *result;
10157 sym_link *type, *etype;
10160 D(emitcode ("; genPointerSet",""));
10162 right = IC_RIGHT (ic);
10163 result = IC_RESULT (ic);
10165 /* depending on the type of pointer we need to
10166 move it to the correct pointer register */
10167 type = operandType (result);
10168 etype = getSpec (type);
10169 /* if left is of type of pointer then it is simple */
10170 if (IS_PTR (type) && !IS_FUNC (type->next))
10172 p_type = DCL_TYPE (type);
10176 /* we have to go by the storage class */
10177 p_type = PTR_TYPE (SPEC_OCLS (etype));
10180 /* special case when cast remat */
10181 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10182 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10183 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10184 type = operandType (result);
10185 p_type = DCL_TYPE (type);
10187 /* now that we have the pointer type we assign
10188 the pointer values */
10194 genNearPointerSet (right, result, ic, pi);
10198 genPagedPointerSet (right, result, ic, pi);
10202 genFarPointerSet (right, result, ic, pi);
10206 genGenPointerSet (right, result, ic, pi);
10210 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10211 "genPointerSet: illegal pointer type");
10216 /*-----------------------------------------------------------------*/
10217 /* genIfx - generate code for Ifx statement */
10218 /*-----------------------------------------------------------------*/
10220 genIfx (iCode * ic, iCode * popIc)
10222 operand *cond = IC_COND (ic);
10226 D(emitcode ("; genIfx",""));
10228 aopOp (cond, ic, FALSE);
10230 /* get the value into acc */
10231 if (AOP_TYPE (cond) != AOP_CRY)
10236 if (AOP(cond)->aopu.aop_dir)
10237 dup = Safe_strdup(AOP(cond)->aopu.aop_dir);
10239 /* the result is now in the accumulator or a directly addressable bit */
10240 freeAsmop (cond, NULL, ic, TRUE);
10242 /* if there was something to be popped then do it */
10246 /* if the condition is a bit variable */
10248 genIfxJump(ic, dup, NULL, NULL, NULL);
10249 else if (isbit && IS_ITEMP (cond) && SPIL_LOC (cond))
10250 genIfxJump (ic, SPIL_LOC (cond)->rname, NULL, NULL, NULL);
10251 else if (isbit && !IS_ITEMP (cond))
10252 genIfxJump (ic, OP_SYMBOL (cond)->rname, NULL, NULL, NULL);
10254 genIfxJump (ic, "a", NULL, NULL, NULL);
10259 /*-----------------------------------------------------------------*/
10260 /* genAddrOf - generates code for address of */
10261 /*-----------------------------------------------------------------*/
10263 genAddrOf (iCode * ic)
10265 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10268 D(emitcode ("; genAddrOf",""));
10270 aopOp (IC_RESULT (ic), ic, FALSE);
10272 /* if the operand is on the stack then we
10273 need to get the stack offset of this
10277 /* if it has an offset then we need to compute
10281 emitcode ("mov", "a,%s", SYM_BP (sym));
10282 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
10283 ((char) (sym->stack - _G.nRegsSaved)) :
10284 ((char) sym->stack)) & 0xff);
10285 aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10289 /* we can just move _bp */
10290 aopPut (IC_RESULT (ic), SYM_BP (sym), 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10292 /* fill the result with zero */
10293 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10298 aopPut (IC_RESULT (ic), zero, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10304 /* object not on stack then we need the name */
10305 size = AOP_SIZE (IC_RESULT (ic));
10310 char s[SDCC_NAME_MAX];
10312 sprintf (s, "#(%s >> %d)",
10316 sprintf (s, "#%s", sym->rname);
10317 aopPut (IC_RESULT (ic), s, offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10321 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10325 /*-----------------------------------------------------------------*/
10326 /* genFarFarAssign - assignment when both are in far space */
10327 /*-----------------------------------------------------------------*/
10329 genFarFarAssign (operand * result, operand * right, iCode * ic)
10331 int size = AOP_SIZE (right);
10335 D(emitcode ("; genFarFarAssign",""));
10337 /* first push the right side on to the stack */
10340 l = aopGet (right, offset++, FALSE, FALSE);
10342 emitcode ("push", "acc");
10345 freeAsmop (right, NULL, ic, FALSE);
10346 /* now assign DPTR to result */
10347 aopOp (result, ic, FALSE);
10348 size = AOP_SIZE (result);
10351 emitcode ("pop", "acc");
10352 aopPut (result, "a", --offset, isOperandVolatile (result, FALSE));
10354 freeAsmop (result, NULL, ic, FALSE);
10358 /*-----------------------------------------------------------------*/
10359 /* genAssign - generate code for assignment */
10360 /*-----------------------------------------------------------------*/
10362 genAssign (iCode * ic)
10364 operand *result, *right;
10366 unsigned long lit = 0L;
10368 D(emitcode("; genAssign",""));
10370 result = IC_RESULT (ic);
10371 right = IC_RIGHT (ic);
10373 /* if they are the same */
10374 if (operandsEqu (result, right) &&
10375 !isOperandVolatile (result, FALSE) &&
10376 !isOperandVolatile (right, FALSE))
10379 aopOp (right, ic, FALSE);
10381 /* special case both in far space */
10382 if (AOP_TYPE (right) == AOP_DPTR &&
10383 IS_TRUE_SYMOP (result) &&
10384 isOperandInFarSpace (result))
10387 genFarFarAssign (result, right, ic);
10391 aopOp (result, ic, TRUE);
10393 /* if they are the same registers */
10394 if (sameRegs (AOP (right), AOP (result)) &&
10395 !isOperandVolatile (result, FALSE) &&
10396 !isOperandVolatile (right, FALSE))
10399 /* if the result is a bit */
10400 if (AOP_TYPE (result) == AOP_CRY)
10403 /* if the right size is a literal then
10404 we know what the value is */
10405 if (AOP_TYPE (right) == AOP_LIT)
10407 if (((int) operandLitValue (right)))
10408 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10410 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10414 /* the right is also a bit variable */
10415 if (AOP_TYPE (right) == AOP_CRY)
10417 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10418 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10422 /* we need to or */
10424 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10428 /* bit variables done */
10430 size = AOP_SIZE (result);
10432 if (AOP_TYPE (right) == AOP_LIT)
10433 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10435 (AOP_TYPE (result) != AOP_REG) &&
10436 (AOP_TYPE (right) == AOP_LIT) &&
10437 !IS_FLOAT (operandType (right)) &&
10440 while ((size) && (lit))
10443 aopGet (right, offset, FALSE, FALSE),
10445 isOperandVolatile (result, FALSE));
10450 emitcode ("clr", "a");
10453 aopPut (result, "a", offset, isOperandVolatile (result, FALSE));
10462 aopGet (right, offset, FALSE, FALSE),
10464 isOperandVolatile (result, FALSE));
10470 freeAsmop (right, NULL, ic, TRUE);
10471 freeAsmop (result, NULL, ic, TRUE);
10474 /*-----------------------------------------------------------------*/
10475 /* genJumpTab - generates code for jump table */
10476 /*-----------------------------------------------------------------*/
10478 genJumpTab (iCode * ic)
10480 symbol *jtab,*jtablo,*jtabhi;
10482 unsigned int count;
10484 D(emitcode ("; genJumpTab",""));
10486 count = elementsInSet( IC_JTLABELS (ic) );
10490 /* this algorithm needs 9 cycles and 7 + 3*n bytes
10491 if the switch argument is in a register.
10492 (8 cycles and 6+2*n bytes if peepholes can change ljmp to sjmp) */
10493 /* (MB) What if peephole converts ljmp to sjmp or ret ???
10494 How will multiply by three be updated ???*/
10495 aopOp (IC_JTCOND (ic), ic, FALSE);
10496 /* get the condition into accumulator */
10497 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10499 /* multiply by three */
10500 emitcode ("add", "a,acc");
10501 emitcode ("add", "a,%s", aopGet (IC_JTCOND (ic), 0, FALSE, FALSE));
10502 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10504 jtab = newiTempLabel (NULL);
10505 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
10506 emitcode ("jmp", "@a+dptr");
10507 emitcode ("", "%05d$:", jtab->key + 100);
10508 /* now generate the jump labels */
10509 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10510 jtab = setNextItem (IC_JTLABELS (ic)))
10511 emitcode ("ljmp", "%05d$", jtab->key + 100);
10515 /* this algorithm needs 14 cycles and 13 + 2*n bytes
10516 if the switch argument is in a register.
10517 For n>6 this algorithm may be more compact */
10518 jtablo = newiTempLabel (NULL);
10519 jtabhi = newiTempLabel (NULL);
10521 /* get the condition into accumulator.
10522 Using b as temporary storage, if register push/pop is needed */
10523 aopOp (IC_JTCOND (ic), ic, FALSE);
10524 l = aopGet (IC_JTCOND (ic), 0, FALSE, FALSE);
10525 if ((AOP_TYPE (IC_JTCOND (ic)) == AOP_R0 && _G.r0Pushed) ||
10526 (AOP_TYPE (IC_JTCOND (ic)) == AOP_R1 && _G.r1Pushed))
10528 // (MB) what if B is in use???
10529 wassertl(!BINUSE, "B was in use");
10530 emitcode ("mov", "b,%s", l);
10533 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
10537 emitcode ("add", "a,#(%05d$-3-.)", jtablo->key + 100);
10538 emitcode ("movc", "a,@a+pc");
10539 emitcode ("push", "acc");
10542 emitcode ("add", "a,#(%05d$-3-.)", jtabhi->key + 100);
10543 emitcode ("movc", "a,@a+pc");
10544 emitcode ("push", "acc");
10548 /* this scales up to n<=255, but needs two more bytes
10549 and changes dptr */
10550 emitcode ("mov", "dptr,#%05d$", jtablo->key + 100);
10551 emitcode ("movc", "a,@a+dptr");
10552 emitcode ("push", "acc");
10555 emitcode ("mov", "dptr,#%05d$", jtabhi->key + 100);
10556 emitcode ("movc", "a,@a+dptr");
10557 emitcode ("push", "acc");
10560 emitcode ("ret", "");
10562 /* now generate jump table, LSB */
10563 emitcode ("", "%05d$:", jtablo->key + 100);
10564 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10565 jtab = setNextItem (IC_JTLABELS (ic)))
10566 emitcode (".db", "%05d$", jtab->key + 100);
10568 /* now generate jump table, MSB */
10569 emitcode ("", "%05d$:", jtabhi->key + 100);
10570 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
10571 jtab = setNextItem (IC_JTLABELS (ic)))
10572 emitcode (".db", "%05d$>>8", jtab->key + 100);
10576 /*-----------------------------------------------------------------*/
10577 /* genCast - gen code for casting */
10578 /*-----------------------------------------------------------------*/
10580 genCast (iCode * ic)
10582 operand *result = IC_RESULT (ic);
10583 sym_link *ctype = operandType (IC_LEFT (ic));
10584 sym_link *rtype = operandType (IC_RIGHT (ic));
10585 operand *right = IC_RIGHT (ic);
10588 D(emitcode("; genCast",""));
10590 /* if they are equivalent then do nothing */
10591 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10594 aopOp (right, ic, FALSE);
10595 aopOp (result, ic, FALSE);
10597 /* if the result is a bit (and not a bitfield) */
10598 // if (AOP_TYPE (result) == AOP_CRY)
10599 if (IS_BITVAR (OP_SYMBOL (result)->type)
10600 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
10602 /* if the right size is a literal then
10603 we know what the value is */
10604 if (AOP_TYPE (right) == AOP_LIT)
10606 if (((int) operandLitValue (right)))
10607 aopPut (result, one, 0, isOperandVolatile (result, FALSE));
10609 aopPut (result, zero, 0, isOperandVolatile (result, FALSE));
10614 /* the right is also a bit variable */
10615 if (AOP_TYPE (right) == AOP_CRY)
10617 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10618 aopPut (result, "c", 0, isOperandVolatile (result, FALSE));
10622 /* we need to or */
10624 aopPut (result, "a", 0, isOperandVolatile (result, FALSE));
10629 /* if they are the same size : or less */
10630 if (AOP_SIZE (result) <= AOP_SIZE (right))
10633 /* if they are in the same place */
10634 if (sameRegs (AOP (right), AOP (result)))
10637 /* if they in different places then copy */
10638 size = AOP_SIZE (result);
10643 aopGet (right, offset, FALSE, FALSE),
10645 isOperandVolatile (result, FALSE));
10652 /* if the result is of type pointer */
10653 if (IS_PTR (ctype))
10657 sym_link *type = operandType (right);
10658 sym_link *etype = getSpec (type);
10660 /* pointer to generic pointer */
10661 if (IS_GENPTR (ctype))
10664 p_type = DCL_TYPE (type);
10667 if (SPEC_SCLS(etype)==S_REGISTER) {
10668 // let's assume it is a generic pointer
10671 /* we have to go by the storage class */
10672 p_type = PTR_TYPE (SPEC_OCLS (etype));
10676 /* the first two bytes are known */
10677 size = GPTRSIZE - 1;
10682 aopGet (right, offset, FALSE, FALSE),
10684 isOperandVolatile (result, FALSE));
10687 /* the last byte depending on type */
10689 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
10694 // pointerTypeToGPByte will have bitched.
10698 sprintf(gpValStr, "#0x%x", gpVal);
10699 aopPut (result, gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
10704 /* just copy the pointers */
10705 size = AOP_SIZE (result);
10710 aopGet (right, offset, FALSE, FALSE),
10712 isOperandVolatile (result, FALSE));
10718 /* so we now know that the size of destination is greater
10719 than the size of the source */
10720 /* we move to result for the size of source */
10721 size = AOP_SIZE (right);
10726 aopGet (right, offset, FALSE, FALSE),
10728 isOperandVolatile (result, FALSE));
10732 /* now depending on the sign of the source && destination */
10733 size = AOP_SIZE (result) - AOP_SIZE (right);
10734 /* if unsigned or not an integral type */
10735 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
10738 aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
10742 /* we need to extend the sign :{ */
10743 char *l = aopGet (right, AOP_SIZE (right) - 1,
10746 emitcode ("rlc", "a");
10747 emitcode ("subb", "a,acc");
10749 aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
10752 /* we are done hurray !!!! */
10755 freeAsmop (right, NULL, ic, TRUE);
10756 freeAsmop (result, NULL, ic, TRUE);
10760 /*-----------------------------------------------------------------*/
10761 /* genDjnz - generate decrement & jump if not zero instrucion */
10762 /*-----------------------------------------------------------------*/
10764 genDjnz (iCode * ic, iCode * ifx)
10766 symbol *lbl, *lbl1;
10770 D(emitcode ("; genDjnz",""));
10772 /* if the if condition has a false label
10773 then we cannot save */
10774 if (IC_FALSE (ifx))
10777 /* if the minus is not of the form
10779 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
10780 !IS_OP_LITERAL (IC_RIGHT (ic)))
10783 if (operandLitValue (IC_RIGHT (ic)) != 1)
10786 /* if the size of this greater than one then no
10788 if (getSize (operandType (IC_RESULT (ic))) > 1)
10791 /* otherwise we can save BIG */
10792 lbl = newiTempLabel (NULL);
10793 lbl1 = newiTempLabel (NULL);
10795 aopOp (IC_RESULT (ic), ic, FALSE);
10797 if (AOP_NEEDSACC(IC_RESULT(ic)))
10799 /* If the result is accessed indirectly via
10800 * the accumulator, we must explicitly write
10801 * it back after the decrement.
10803 char *rByte = aopGet (IC_RESULT(ic), 0, FALSE, FALSE);
10805 if (strcmp(rByte, "a"))
10807 /* Something is hopelessly wrong */
10808 fprintf(stderr, "*** warning: internal error at %s:%d\n",
10809 __FILE__, __LINE__);
10810 /* We can just give up; the generated code will be inefficient,
10811 * but what the hey.
10813 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10816 emitcode ("dec", "%s", rByte);
10817 aopPut (IC_RESULT (ic), rByte, 0, isOperandVolatile (IC_RESULT (ic), FALSE));
10818 emitcode ("jnz", "%05d$", lbl->key + 100);
10820 else if (IS_AOP_PREG (IC_RESULT (ic)))
10822 emitcode ("dec", "%s",
10823 aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10824 MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
10825 emitcode ("jnz", "%05d$", lbl->key + 100);
10829 emitcode ("djnz", "%s,%05d$", aopGet (IC_RESULT (ic), 0, FALSE, FALSE),
10832 emitcode ("sjmp", "%05d$", lbl1->key + 100);
10833 emitcode ("", "%05d$:", lbl->key + 100);
10834 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
10835 emitcode ("", "%05d$:", lbl1->key + 100);
10837 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10838 ifx->generated = 1;
10842 /*-----------------------------------------------------------------*/
10843 /* genReceive - generate code for a receive iCode */
10844 /*-----------------------------------------------------------------*/
10846 genReceive (iCode * ic)
10848 int size = getSize (operandType (IC_RESULT (ic)));
10851 D(emitcode ("; genReceive",""));
10853 if (ic->argreg == 1)
10854 { /* first parameter */
10855 if (isOperandInFarSpace (IC_RESULT (ic)) &&
10856 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
10857 IS_TRUE_SYMOP (IC_RESULT (ic))))
10860 int receivingA = 0;
10863 for (offset = 0; offset<size; offset++)
10864 if (!strcmp (fReturn[offset], "a"))
10869 if (size==1 || getTempRegs(tempRegs, size-1, ic))
10871 for (offset = size-1; offset>0; offset--)
10872 emitcode("mov","%s,%s", tempRegs[roffset++]->name, fReturn[offset]);
10873 emitcode("mov","a,%s", fReturn[0]);
10875 aopOp (IC_RESULT (ic), ic, FALSE);
10877 aopPut (IC_RESULT (ic), "a", offset,
10878 isOperandVolatile (IC_RESULT (ic), FALSE));
10879 for (offset = 1; offset<size; offset++)
10880 aopPut (IC_RESULT (ic), tempRegs[--roffset]->name, offset,
10881 isOperandVolatile (IC_RESULT (ic), FALSE));
10887 if (getTempRegs(tempRegs, size, ic))
10889 for (offset = 0; offset<size; offset++)
10890 emitcode("mov","%s,%s", tempRegs[offset]->name, fReturn[offset]);
10891 aopOp (IC_RESULT (ic), ic, FALSE);
10892 for (offset = 0; offset<size; offset++)
10893 aopPut (IC_RESULT (ic), tempRegs[offset]->name, offset,
10894 isOperandVolatile (IC_RESULT (ic), FALSE));
10899 offset = fReturnSizeMCS51 - size;
10902 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
10903 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
10906 aopOp (IC_RESULT (ic), ic, FALSE);
10907 size = AOP_SIZE (IC_RESULT (ic));
10911 emitcode ("pop", "acc");
10912 aopPut (IC_RESULT (ic), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10918 aopOp (IC_RESULT (ic), ic, FALSE);
10920 assignResultValue (IC_RESULT (ic), NULL);
10923 else if (ic->argreg > 12)
10924 { /* bit parameters */
10925 if (OP_SYMBOL (IC_RESULT (ic))->regs[0]->rIdx != ic->argreg-5)
10927 aopOp (IC_RESULT (ic), ic, FALSE);
10928 emitcode ("mov", "c,%s", rb1regs[ic->argreg-5]);
10929 outBitC(IC_RESULT (ic));
10933 { /* other parameters */
10935 aopOp (IC_RESULT (ic), ic, FALSE);
10936 rb1off = ic->argreg;
10939 aopPut (IC_RESULT (ic), rb1regs[rb1off++ -5], offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
10944 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10947 /*-----------------------------------------------------------------*/
10948 /* genDummyRead - generate code for dummy read of volatiles */
10949 /*-----------------------------------------------------------------*/
10951 genDummyRead (iCode * ic)
10956 D(emitcode("; genDummyRead",""));
10958 op = IC_RIGHT (ic);
10959 if (op && IS_SYMOP (op))
10961 aopOp (op, ic, FALSE);
10963 /* if the result is a bit */
10964 if (AOP_TYPE (op) == AOP_CRY)
10965 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10968 /* bit variables done */
10970 size = AOP_SIZE (op);
10974 MOVA (aopGet (op, offset, FALSE, FALSE));
10979 freeAsmop (op, NULL, ic, TRUE);
10983 if (op && IS_SYMOP (op))
10985 aopOp (op, ic, FALSE);
10987 /* if the result is a bit */
10988 if (AOP_TYPE (op) == AOP_CRY)
10989 emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir);
10992 /* bit variables done */
10994 size = AOP_SIZE (op);
10998 MOVA (aopGet (op, offset, FALSE, FALSE));
11003 freeAsmop (op, NULL, ic, TRUE);
11007 /*-----------------------------------------------------------------*/
11008 /* genCritical - generate code for start of a critical sequence */
11009 /*-----------------------------------------------------------------*/
11011 genCritical (iCode *ic)
11013 symbol *tlbl = newiTempLabel (NULL);
11015 D(emitcode("; genCritical",""));
11017 if (IC_RESULT (ic))
11019 aopOp (IC_RESULT (ic), ic, TRUE);
11020 aopPut (IC_RESULT (ic), one, 0, 0);
11021 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11022 aopPut (IC_RESULT (ic), zero, 0, 0);
11023 emitcode ("", "%05d$:", (tlbl->key + 100));
11024 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11028 emitcode ("setb", "c");
11029 emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */
11030 emitcode ("clr", "c");
11031 emitcode ("", "%05d$:", (tlbl->key + 100));
11032 emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/
11036 /*-----------------------------------------------------------------*/
11037 /* genEndCritical - generate code for end of a critical sequence */
11038 /*-----------------------------------------------------------------*/
11040 genEndCritical (iCode *ic)
11042 D(emitcode("; genEndCritical",""));
11046 aopOp (IC_RIGHT (ic), ic, FALSE);
11047 if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
11049 emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir);
11050 emitcode ("mov", "ea,c");
11054 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_DUMMY)
11055 MOVA (aopGet (IC_RIGHT (ic), 0, FALSE, FALSE));
11056 emitcode ("rrc", "a");
11057 emitcode ("mov", "ea,c");
11059 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
11063 emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */
11064 emitcode ("mov", "ea,c");
11068 /*-----------------------------------------------------------------*/
11069 /* gen51Code - generate code for 8051 based controllers */
11070 /*-----------------------------------------------------------------*/
11072 gen51Code (iCode * lic)
11076 /* int cseq = 0; */
11078 _G.currentFunc = NULL;
11079 lineHead = lineCurr = NULL;
11081 /* print the allocation information */
11082 if (allocInfo && currFunc)
11083 printAllocInfo (currFunc, codeOutFile);
11084 /* if debug information required */
11085 if (options.debug && currFunc)
11087 debugFile->writeFunction (currFunc, lic);
11089 /* stack pointer name */
11090 if (options.useXstack)
11096 for (ic = lic; ic; ic = ic->next)
11098 _G.current_iCode = ic;
11100 if (ic->lineno && cln != ic->lineno)
11104 debugFile->writeCLine (ic);
11106 if (!options.noCcodeInAsm) {
11107 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
11108 printCLine(ic->filename, ic->lineno));
11113 if (ic->seqPoint && ic->seqPoint != cseq)
11115 emitcode ("", "; sequence point %d", ic->seqPoint);
11116 cseq = ic->seqPoint;
11119 if (options.iCodeInAsm) {
11120 char regsInUse[80];
11123 for (i=0; i<8; i++) {
11124 sprintf (®sInUse[i],
11125 "%c", ic->riu & (1<<i) ? i+'0' : '-');
11128 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
11130 /* if the result is marked as
11131 spilt and rematerializable or code for
11132 this has already been generated then
11134 if (resultRemat (ic) || ic->generated)
11137 /* depending on the operation */
11157 /* IPOP happens only when trying to restore a
11158 spilt live range, if there is an ifx statement
11159 following this pop then the if statement might
11160 be using some of the registers being popped which
11161 would destory the contents of the register so
11162 we need to check for this condition and handle it */
11164 ic->next->op == IFX &&
11165 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
11166 genIfx (ic->next, ic);
11184 genEndFunction (ic);
11204 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
11221 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
11225 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
11232 /* note these two are xlated by algebraic equivalence
11233 during parsing SDCC.y */
11234 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11235 "got '>=' or '<=' shouldn't have come here");
11239 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
11251 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
11255 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
11259 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
11295 genRightShift (ic);
11298 case GET_VALUE_AT_ADDRESS:
11300 hasInc (IC_LEFT (ic), ic,
11301 getSize (operandType (IC_RESULT (ic)))),
11302 ifxForOp (IC_RESULT (ic), ic) );
11306 if (POINTER_SET (ic))
11307 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
11333 addSet (&_G.sendSet, ic);
11336 case DUMMY_READ_VOLATILE:
11345 genEndCritical (ic);
11357 _G.current_iCode = NULL;
11359 /* now we are ready to call the
11360 peep hole optimizer */
11361 if (!options.nopeep)
11362 peepHole (&lineHead);
11364 /* now do the actual printing */
11365 printLine (lineHead, codeOutFile);